빙응의 공부 블로그
[Spring]타임리프(Thymeleaf)에 대해 알아보자! 본문
📝타임리프(Thymeleaf)
- 타임리프는 컨트롤러가 전달하는 데이터를 이용해 동적으로 화면을 만들어주는 뷰 템플릿 엔진이다.
- 특징
- 서버 상에서 동작하지 않아도 HTML 파일의 내용을 바로 확인이 가능
- 순수 HTML 구조를 유지하기 때문에 Natural Template이라고도 불린다.
JSP는 서버를 구동하지 않고 파일을 열면 정상적인 확인이 불가능하지만
타임리프는 쉽게 파악이 가능하여 개발이 용이하다!
타임리프 라이브러리 추가
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
타임리프 기본 선언
<html xmlns:th="http://www.thymeleaf.org">
HTML 상단에 해당 선언을 해야 타임리프 사용이 가능해진다.
📝타임리프 기본 문법
타임리프의 기본 문법은 접두어와 표현식으로 나뉜다.
접두어는 타임리프의 기능이고 표현식은 데이터를 렌더링하고 처리하는데 사용된다.
- 접두어 : th로 시작하며 타임리프가 제공하는 다양한 기능을 사용할 수 있다.
- 표현식 : 데이터를 동적으로 HTML에 삽입하거나 처리하는데 사용된다.
🚩타임리프 기본 문법 - 접두어
텍스트 - text, utext
<li>th:text = <span th:text="${data}"></span></li>
<li>th:utext = <span th:utext="${data}"></span></li>
<li>[[${data}]]</li>
<li>[(${data})]</li>
- text와 utext는 텍스트를 처리하는 접두어이다.
- 위 두가지 방법의 차이는 이스케이프 여부이다.
이스케이프?
특정 문자나 문자열을 해석되지 않게 만들거나 특수한 용도로 처리하는 것을 의미!
- 이스케이프는 주로 보안을 강화하고 데이터의 무결성을 보장하기 위한 목적으로 사용된다.
- text는 텍스트를 HTML 이스케이프하여 출력해 HTML 태그를 렌더링할 때 원치 않는 태그로 해석되는 것을 방지한다.
- utext는 HTML 이스케이프를 하지 않는다.
th:text : <b>Hello</b> --> <b>Hello</b>
th:utext : <b>Hello</b> --> <b>Hello</b>
[[${data}]] : <b>Hello</b> --> <b>Hello</b>
[(${data})] : <b>Hello</b> --> <b>Hello</b>
참고! 실제 데이터를 개발하다보면 이스케이프를 사용하지 않아서 발생하는 문제가 많기 때문에
꼭 필요할때만 이스케이프 처리를 안하면 된다.
조건 - if, unless
<div th:if="${user.isAdmin}">관리자만 접근 가능합니다.</div>
<div th:unless="${user.isAdmin}">일반 사용자용 페이지입니다.</div>
- 조건문을 사용하여 요소를 조건부로 렌더링할 수 있다.
- th:if : 조건부가 참일 때 해당 요소를 렌더링한다.
- th:unless : 조건부가 거짓일 때 해당 요소를 렌더링 한다.
반복 - each
<ul>
<li th:each="menuItem : ${menuItems}" th:text="${menuItem}">Item</li>
</ul>
- Thymeleaf에서는 반복 변수를 사용할 수 있다.
- 자바의 for(Integer num : nums)와 비슷한 것이다.
- 컬렉션의 각 항목을 반복하여 요소를 생성하는 것이다!
추가! 반복법은 반복 중에 상태를 확인할 수 있다.
<tr th:each="user, userStat : ${users}">
<td th:text="${userStat.count}">username</td>
<td th:text="${user.username}">username</td>
<td th:text="${user.age}">0</td>
<td>
index = <span th:text="${userStat.index}"></span>
count = <span th:text="${userStat.count}"></span>
size = <span th:text="${userStat.size}"></span>
even? = <span th:text="${userStat.even}"></span>
odd? = <span th:text="${userStat.odd}"></span>
first? = <span th:text="${userStat.first}"></span>
last? = <span th:text="${userStat.last}"></span>
current = <span th:text="${userStat.current}"></span>
</td>
</tr>
해당 코드는 userStat를 임의로 추가하고 특별한 상태를 확인할 수 있다.
- index : 현재 반복의 인덱스 값을 리턴한다. 0부터 시작
- count : 몇 번째인지 알 수 있다. 1부터 시작
- size : 전체 사이즈
- event, odd : 홀수, 짝수 여부
- first, last : 처음, 마지막 여부
- current : 현재 객체를 받아볼 수 있으나 잘 안쓴다.
링크 - src, href
<img th:src="@{/images/logo.png}" />
<a th:href="@{/about}" title="About Us">About</a>
- th:src : 이미지, 오디오, 비디오 및 외부 리소스 파일과 관련된 요소에 사용한다.
- th:href : 주로 링크의 URL를 만드는데 사용된다.
th:href="@{/basic/items/{itemId}(itemId=${item.id}, query='test')}"
생성 링크: http://localhost:8080/basic/items/1?query=test
객체 바인딩 - Object, action, field
객체 바인딩은 타임리프에서 HTML 폼과 서버 측 객체 간의 바인딩(매핑)을 지원하는 기능이다.
<form th:object="${user}" th:action="@{/saveUser}" method="post">
<label for="firstName">First Name:</label>
<input type="text" id="firstName" th:field="*{firstName}" />
<label for="lastName">Last Name:</label>
<input type="text" id="lastName" th:field="*{lastName}" />
<button type="submit">Save</button>
</form>
- 예제 설명)
- 해당 예제는 user 오브젝트를 바인딩하여 반환하는 역할을 한다.
- th:object="${user}" : 폼에 연결할 객체를 지정한다. "${user}"로 객체를 받아 바인딩한다.
- th:action="@{/saveUser}" : 폼의 제출 URL을 설정합니다. 사용자가 폼을 제출하면 /saveUser로 POST 요청이 전송된다
- th:field="*{firstName}" : 폼 필드를 객체의 속성과 매칭해 바인딩한다. 사용자가 값을 제출하면 객체가 업데이트된다
- 해당 예제는 user 오브젝트를 바인딩하여 반환하는 역할을 한다.
속성 적용 - attr
<button th:attr="data-id=${item.id} style='color:red;'">Click Me</button>
- 타임리프로 HTML 요소에 여러 속성을 추가하거나 수정할 수 있다.
- 이것은 템플릿 엔진을 통해 동적으로 생성되는 컨텐츠를 다룰 때 유용하다.
- th:attr : 웹 페이지에서 요소의 다양한 속성을 동적으로 조작할 수 있다.
스타일, 클래스 - Style, Class
<div th:style="'color: ' + ${textColor}">This is a text with a dynamic color.</div>
<div class="dynamic-class" th:class="${isActive} ? 'active' : 'inactive'">Content</div>
- 스타일과 클래스를 동적으로 HTML 요소에 추가할 수 있다.
- th:style : CSS요소를 타임리프를 이용해서 가져온다.
- th:Class : 클래스 요소를 추가 해당 예제는 동적인지 정적인지 결정
🚩타임리프 기본 문법 - 표현식
타임리프의 표현식은 4가지 종류가 있다.
표현식
|
구현
|
예제
|
링크 표현식
|
@{URL}
|
th:href="@{/about}
|
변수 표현식
|
${변수명}
|
th:text="${item.price}"
|
외부 자원 변수 표현식
|
#{변수명}
|
th:text="#{member.register}"
|
객체, 속성 접근 표현식
|
*{변수명}
|
th:field="*{username}"
|
URL 링크 표현식
- 타임리프로 URL 링크를 사용하는 경우 @{...}를 사용한다.
- URL 링크 표현식을 사용하면 컨텍스트가 자동으로 포함된다.
<a th:href ="@{/css/bootstrap.min.css}"> <a>
<a th:href="@{/about}">About Us</a>
// /about으로 이동하는 링크 생성
@Controller
@RequestMapping("/myapp")
public class MyController {
@GetMapping("/about")
public String aboutPage() {
return "about";
}
}
해당 코드처럼 타임리프에서 @{/about} 을 입력하면 자동으로 /myapp/about을 생성한다!
변수 표현식
- 타임리프의 변수 표현식은 서버 측 데이터를 동적으로 HTML에 삽입하거나 처리하는데 사용한다.
- 변수 표현식은 ${...}로 표현된다.
<p th:text="${username}">Guest</p>
<p th:text="${count * 2}">Default Value</p>
<p th:text="${isAdmin ? 'Admin' : 'User'}">User</p>
//연산도 가능
<ul>
<li th:each="item : ${items}" th:text="${item}">Default Item</li>
</ul>
//반복문
외부 자원 변수 표현식
- 타임리프에서 메시지 번들이나 외부 속성 파일에서 메시지를 가져오는 기능을 말한다.
- 외부 자원 변수 표현식은 #{...}으로 표현된다.
<p th:text="#{welcome.message}">Default Message</p>
다국어 지원이나 메시지를 외부로 분리하여 관리하는 경우에 많이 사용된다.
객체, 속성 접근 표현식
- 타임리프에서 서버 측 객체와 해당 객체의 속성에 접근하여 값을 가져오거나 표현하는 데 사용된다.
- 객체, 속성 접근 표현식은 *{...}으로 표현된다.
예를 들어, 다음과 같은 객체가 있다 가정해보자
public class User {
private String username;
private String email;
// 생성자, 게터, 세터 등 생략
}
이 객체를 Thymeleaf에서 사용하려면
<p th:text="*{username}">Default Username</p>
<p th:text="*{email}">Default Email</p>
위의 코드에서 *{username}과 *{email}은 각각 User 객체의 getUsername() 및 getEmail() 메서드를 호출하여 속성 값을 가져온다.
갑자기 든 생각!
위 코드는 사실 ${}으로도 할 수 있다. 그럼 왜 *{}을 써야할까?
1. 객체와 속성 접근
*{...} : 주로 Thymeleaf에서 객체와 해당 객체의 속성에 동적으로 접근할 때 사용한다.
${...} : 주로 리터럴 텍스트를 출력할 때 사용되며, Thymeleaf에서 평가되지 않은 정적인 값이 된다.
2. 문맥과 목적
*{...}: 객체 및 속성 접근, 반복문에서의 변수 등 Thymeleaf의 다양한 문법에서 동적인 값을 처리할 때 사용됩니다.
${...}: 주로 리터럴 텍스트 출력이 목적이며, 특정 Thymeleaf 문법을 사용하지 않는 경우에 주로 사용됩니다.
3.유지보수와 가독성
*{...}: 객체와 속성에 동적으로 접근할 때 코드의 가독성을 높일 수 있습니다. 객체와 속성이 변경되더라도 표현식 내부의 객체 및 속성이 자동으로 갱신되기 때문입니다.
${...}: 주로 정적인 값이므로 유지보수 측면에서는 해당 값이 변경될 때 코드를 수정해야 합니다.
선택은 개발자의 취향 및 사용되는 문맥에 따라 다를 수 있으나 Thymeleaf 문법과 관련된 동적인 작업에서는 *{...}을 사용!
'Spring > 개인공부_이론' 카테고리의 다른 글
[Spring]스프링 시큐리티 - 개요 (0) | 2024.03.21 |
---|---|
[Spring]타임리프(Thymeleaf)에 대해 알아보자! 2편 (1) | 2024.01.21 |
[Spring]로그에 대해 알아보자! - 1편 (0) | 2024.01.14 |
[Spring]의존성 주입(DI) (0) | 2023.11.20 |
[스프링/Validation] 유효성 검사 쉽게 하기 (0) | 2023.11.15 |