📌 1️⃣ Thymeleaf란?
Thymeleaf는 Spring Boot에서 HTML을 동적으로 렌더링하는 템플릿 엔진이야.
즉, Controller에서 데이터를 받아와서 HTML에 출력할 수 있어.
📌 2️⃣ Thymeleaf 기본 설정
✅ 1️⃣ Thymeleaf 의존성 추가 (Spring Boot 프로젝트에서 기본 포함됨)
build.gradle 또는 pom.xml에서 Thymeleaf를 추가해야 해.
📌 Gradle 프로젝트
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
}
📌 Maven 프로젝트
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
✅ 2️⃣ View Resolver 설정 (application.yml)
Spring Boot에서는 기본적으로 templates/ 폴더에서 Thymeleaf 파일을 찾는다.
spring:
thymeleaf:
prefix: classpath:/templates/ # 템플릿 파일 경로
suffix: .html # 확장자 설정
➡ return "hello"; 하면 templates/hello.html 파일을 찾아 렌더링해!
📌 3️⃣ 기본적인 Thymeleaf 문법
Thymeleaf는 HTML과 함께 사용할 수 있는 문법을 제공해.
✅ 1️⃣ Controller에서 데이터 전달
📌 Controller (HelloController.java)
@Controller
public class HelloController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("message", "안녕하세요, Thymeleaf!");
return "hello"; // hello.html로 이동
}
}
✅ 2️⃣ HTML에서 데이터 출력
📌 hello.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Thymeleaf 예제</title>
</head>
<body>
<h1 th:text="${message}">기본 메시지</h1>
</body>
</html>
📌 th:text="${message}" → Controller에서 넘긴 데이터를 HTML에 출력!
➡ http://localhost:8080/hello 접속하면 안녕하세요, Thymeleaf!가 출력됨.
📌 4️⃣ Thymeleaf에서 변수 사용하기
✅ 1️⃣ 변수 표현
<p th:text="${name}">기본 이름</p>
📌 th:text="${name}" → name 변수를 출력한다.
✅ 2️⃣ 조건문 (if, unless)
<p th:if="${age >= 18}">성인입니다.</p>
<p th:unless="${age >= 18}">미성년자입니다.</p>
📌 th:if → 조건이 참이면 표시
📌 th:unless → 조건이 거짓이면 표시
✅ 3️⃣ 반복문 (each)
📌 Controller에서 List 전달
@GetMapping("/users")
public String users(Model model) {
List<String> users = Arrays.asList("Alice", "Bob", "Charlie");
model.addAttribute("users", users);
return "userList";
}
📌 Thymeleaf에서 반복문 사용 (userList.html)
<ul>
<li th:each="user : ${users}" th:text="${user}"></li>
</ul>
➡ http://localhost:8080/users 접속하면
- Alice
- Bob
- Charlie
이렇게 출력됨!
✅ 4️⃣ 링크 연결 (th:href)
📌 URL을 동적으로 생성할 때 사용
<a th:href="@{/profile/{id}(id=${userId})}">프로필 보기</a>
➡ @{} 안에서 {id}는 동적으로 변환됨.
➡ userId = 5 이면, /profile/5로 변환
✅ 5️⃣ 폼 데이터 전송 (th:action, th:method)
📌 폼 데이터를 컨트롤러로 보낼 때 사용
<form th:action="@{/submit}" th:method="post">
<input type="text" name="username" placeholder="이름 입력">
<button type="submit">제출</button>
</form>
➡ th:action="@{/submit}" → /submit URL로 데이터 전송
➡ th:method="post" → POST 방식으로 전송
✅ 6️⃣ 값을 HTML 속성에 넣기 (th:attr)
📌 HTML 태그의 속성값을 동적으로 변경 가능
<img th:src="@{${profileImageUrl}}" alt="프로필 이미지">
➡ profileImageUrl = "/images/user1.png" 이면,
➡ <img src="/images/user1.png" alt="프로필 이미지">로 변환됨.
✅ 7️⃣ Switch 문 (th:switch, th:case)
📌 여러 조건 중 하나만 실행할 때 사용
<div th:switch="${role}">
<p th:case="'admin'">관리자입니다.</p>
<p th:case="'user'">일반 사용자입니다.</p>
<p th:case="*">알 수 없는 권한입니다.</p>
</div>
➡ role = "admin"이면 "관리자입니다." 출력
✅ 8️⃣ 날짜 포맷팅 (#dates.format)
📌 Java의 LocalDateTime 데이터를 사람이 읽기 쉽게 변환
<p th:text="${#dates.format(joinDate, 'yyyy-MM-dd HH:mm')}"></p>
➡ joinDate = 2025-04-01T10:30:00
➡ "2025-04-01 10:30" 으로 출력
✅ 9️⃣ Boolean 값 출력 (th:checked)
📌 체크박스를 true/false 값으로 제어
<input type="checkbox" th:checked="${user.isSubscribed}">
➡ user.isSubscribed = true 이면 체크됨 ✅
➡ user.isSubscribed = false 이면 체크 해제됨 ❌
✅ 🔟 Fragment (템플릿 재사용)
📌 공통 UI를 따로 분리해서 재사용할 때 사용
📌 공통 헤더 파일 (header.html)
<div th:fragment="header">
<h1>공통 헤더</h1>
</div>
📌 다른 HTML에서 삽입
<div th:replace="~{header :: header}"></div>
➡ 여러 페이지에서 공통된 부분을 쉽게 관리 가능!
📌 5️⃣ 폼 데이터 처리 (데이터 입력 & 전송)
Thymeleaf를 사용하면 HTML 폼 데이터를 Controller로 쉽게 전송할 수 있어.
✅ 1️⃣ DTO 클래스 만들기
@Getter @Setter
public class UserDTO {
private String name;
private String email;
}
✅ 2️⃣ 회원 가입 폼 만들기 (form.html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>회원 가입</title>
</head>
<body>
<form action="/signup" method="post" th:object="${user}">
이름: <input type="text" th:field="*{name}"><br>
이메일: <input type="email" th:field="*{email}"><br>
<button type="submit">가입</button>
</form>
</body>
</html>
📌 th:field="*{name}" → UserDTO의 name과 연결됨
📌 th:field="*{email}" → UserDTO의 email과 연결됨
✅ 3️⃣ Controller에서 폼 데이터 받기
@Controller
public class UserController {
@GetMapping("/signup")
public String showForm(Model model) {
model.addAttribute("user", new UserDTO());
return "form"; // form.html
}
@PostMapping("/signup")
public String processForm(@ModelAttribute UserDTO userDTO) {
log.info("가입한 사용자: " + userDTO.getName() + ", 이메일: " + userDTO.getEmail());
return "success"; // 성공 페이지
}
}
📌 @ModelAttribute 를 사용해서 Thymeleaf에서 입력한 데이터를 받아올 수 있어!
📌 6️⃣ Thymeleaf에서 URL 처리
Thymeleaf에서는 동적으로 URL을 생성할 수도 있어.
✅ 1️⃣ 정적 URL (@{})
<a th:href="@{/home}">홈으로 이동</a>
📌 클릭하면 /home 페이지로 이동
✅ 2️⃣ 동적 URL (@{/path/{변수명}(변수)} )
<a th:href="@{/user/{id}(id=${user.id})}">프로필 보기</a>
📌 결과 → /user/123
📌 7️⃣ Thymeleaf Fragment (재사용 가능한 템플릿)
반복적으로 사용되는 코드(예: 헤더, 푸터)를 Fragment로 만들 수 있어.
📌 1️⃣ header.html (공통 헤더)
<div th:fragment="header">
<h1>공통 헤더</h1>
</div>
📌 2️⃣ index.html (Fragment 사용)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Thymeleaf Fragment</title>
</head>
<body>
<div th:replace="fragments/header :: header"></div>
<p>메인 페이지</p>
</body>
</html>
📌 th:replace="fragments/header :: header" → header.html의 Fragment 삽입
🔥 오늘 배운 핵심 정리
개념 | 설명 |
Thymeleaf | Spring의 템플릿 엔진 (HTML을 동적으로 렌더링) |
View Resolver | View 이름을 실제 HTML 파일과 연결 |
Thymeleaf 문법 | th:text, th:each, th:if 등 활용 |
폼 데이터 처리 | th:field로 DTO와 연동 가능 |
URL 처리 | @{} 문법으로 URL 동적 생성 |
Fragment | 공통 HTML 부분을 재사용 가능 |
🤔 Thymeleaf를 안 쓰면 어떤 일이 벌어질까?
만약 Thymeleaf 없이 순수한 HTML과 Spring만 사용해서 데이터를 클라이언트에 전달하려면 다음과 같은 문제가 생긴다.
🚨 1️⃣ HTML에서 동적으로 데이터를 넣을 수 없다.
Thymeleaf 없이 HTML을 작성하면, 서버에서 데이터를 동적으로 삽입할 방법이 없어.
예를 들어, HelloController에서 사용자 이름을 동적으로 넣고 싶다고 하자.
📌 Thymeleaf를 사용한 경우
<h1 th:text="'안녕하세요, ' + ${name} + '님!'"></h1>
➡ 컨트롤러에서 model.addAttribute("name", "Alice") 를 추가하면 안녕하세요, Alice님! 이 출력됨.
📌 Thymeleaf 없이 하면?
<h1>안녕하세요, ${name}님!</h1>
이렇게 하면 ${name}은 그냥 문자열로 남아있고, 브라우저에서 해석되지 않는다.
🚨 즉, 서버에서 데이터를 주입하는 기능이 없음.
🚨 2️⃣ JSP (Java Server Pages)를 사용해야 한다.
Thymeleaf가 없으면 JSP 같은 다른 기술을 사용해야 하는데, JSP는 단점이 많다.
JSP에서는 <%= name %> 같은 스크립트 코드를 HTML에 직접 써야 한다.
📌 JSP 예제
<h1>안녕하세요, <%= request.getAttribute("name") %>님!</h1>
🚨 단점
- HTML과 Java 코드가 섞여서 유지보수하기 어렵다.
- 서버에서만 실행 가능 (정적 페이지로 미리 확인 불가능).
- 확장성과 보안성이 떨어진다.
🚨 3️⃣ API 방식으로 데이터를 내려야 한다.
Thymeleaf 없이 HTML을 사용하려면, JSON API를 만들어서 데이터를 내려주고 JavaScript (AJAX, Fetch API) 로 받아서 동적으로 추가해야 한다.
📌 Controller에서 JSON 데이터 반환 (Thymeleaf 없이)
@RestController
public class ApiController {
@GetMapping("/api/hello")
public Map<String, String> hello() {
Map<String, String> response = new HashMap<>();
response.put("name", "Alice");
return response;
}
}
📌 HTML + JavaScript로 데이터를 가져와서 넣기
<!DOCTYPE html>
<html>
<head>
<script>
fetch('/api/hello')
.then(response => response.json())
.then(data => {
document.getElementById("greeting").innerText = "안녕하세요, " + data.name + "님!";
});
</script>
</head>
<body>
<h1 id="greeting">로딩 중...</h1>
</body>
</html>
🚨 단점
- 매번 fetch 요청을 보내야 하므로 네트워크 비용 증가
- 단순한 정적 페이지에도 JavaScript가 필요
- 서버-클라이언트 간 API 설계가 필요
✅ 결론: 그래서 Thymeleaf를 쓰는 이유!
Thymeleaf는 Spring과 자연스럽게 통합되면서도, JSP보다 가볍고 강력한 기능을 제공한다.
✔ HTML 파일을 그대로 유지하면서 동적 데이터 삽입 가능
✔ 서버에서 미리 데이터를 HTML에 삽입해서 전송 (빠름)
✔ JSP보다 유지보수 쉽고, JavaScript 없이도 동적 페이지 구현 가능
즉, Thymeleaf를 사용하면 HTML과 데이터를 쉽게 연결하면서, 개발이 훨씬 편리해진다! 🚀
'프로그래밍 > Spring' 카테고리의 다른 글
http응답 상태 코드 참조 사이트 (0) | 2025.04.03 |
---|---|
@Controller와 @RestController의 차이 (0) | 2025.04.02 |
Spring View란? +DTO,VO (0) | 2025.03.31 |
Spring Controller란? (0) | 2025.03.28 |
JDK 동적 프록시 (JDK Dynamic Proxy) (0) | 2025.03.27 |