Thymeleaf 태그 레퍼런스 (2.1.4 버전 기준)

본 문서는 아래 링크에 기재된 내용을 번역한 문서이다.

http://qiita.com/rubytomato@github/items/ac65c2203d16d1a1bbd7

개요

Thymeleaf를 Spring-Boot의 뷰 템플릿 엔진으로서 사용하는 경우의 사용법을 기술한다.

환경

  • Windows 7 (64bit)
  • Java 1.8.0_65
  • Spring-Boot 1.3.0
    • Thymeleaf 2.1.4

참고

변수

text (th:text)

변수 값을 태그의 텍스트로 표시할 때에는 th:text 속성과 ${...} 구문(변수식)을 사용한다.

1
2
3
/* Java */
String username = "kyeongjin";
model.addAttribute("username", username);
1
2
<!-- Thymeleaf 템플릿 -->
<p th:text="${username}">name</p>
1
2
<!-- HTML 출력 결과 -->
<p>kyeongjin</p>

unescape text (th:utext)

변수의 값을 escape 처리하지 않고 표시할 때에는 th:utext 속성을 사용한다.

th:text 구문은 escape 처리를 하고 텍스트를 출력하기 때문에 변수 내 태그 문자가 들어있어도 무시하고 텍스트로 표시함.

1
2
3
/* Java */
String message = "<p>Hello World!</p>";
model.addAttribute("message", message);
1
2
3
<!-- Thymeleaf 템플릿 -->
<div th:text="${message}"></div>
<div th:utext="${message}"></div>
1
2
3
<!-- HTML 출력 결과 -->
<div>&lt;p&gt;Hello World!&lt;/p&gt;</div> <!-- 실제 브라우저에서는 '<p>Hello World!</p>'로 표시됨 -->
<div><p>Hello World!</p></div>

인라인 처리 (th:inline)

태그 내 텍스트 중 일부를 Controller로부터 전달된 변수 값으로 표시하려 할 경우 th:inline 속성을 사용하고 표시할 변수를 [[…]]로 묶는다.

일반적인 태그에서는 잘 사용되지 않으며 script 태그에서 주로 사용된다. 일반적으로 여러 줄의 코드를 가진 javascript 코드의 내 변수에 Controller로부터 받은 파라미터 값으로 초기화할 때 사용한다.

1
2
<!-- Thymeleaf 템플릿 -->
<p th:inline="text">Hello, [[${session.user.name}]]!</p>
1
2
<!-- HTML 출력 결과 -->
<p>Hello, kyeongjin</p>

문자열 연결

문자열과 변수를 + 연산자로 연결할 수 있다.

1
2
<!-- Thymeleaf 템플릿 -->
<p th:text="'Hello, ' + ${username}"></p>
1
2
<!-- HTML 출력 결과 -->
<p>Hello, kyeongjin</p>

치환처리

|${…}|를 사용하면 텍스트 내에 변수 값을 포함시킬 수 있다.

1
2
<!-- Thymeleaf 템플릿 -->
<p th:text="|Hello, ${username}|"></p>
1
2
<!-- HTML 출력 결과 -->
<p>Hello, kyeongjin</p>

기본값 설정

변수 값이 null일 경우, null 대신에 표시할 기본값을 설정할 수 있다.

기본값을 정의하는 방법으로는 ?: 또는 #string 이라는 표현 도구 객체(Expression Utility Object)를 사용한다.

?: (삼항연산자)

1
2
/* Java */
String username = null;
1
2
<!-- Thymeleaf 템플릿 -->
<p th:text="${username}?: 'unknown'"></p>
1
2
<!-- HTML 출력 결과 -->
<p>unknown</p>

#strings.defaultString

1
2
<!-- Thymeleaf 템플릿 -->
<p th:text="${#strings.defaultString(username, 'unknown')}"></p>
1
2
<!-- HTML 출력 결과 -->
<p>unknown</p>

표현 형식 (Format)

변수 값을 일정한 형식에 맞추어 표시할 때에는 표현 도구 객체(Expression Utility Object)를 사용한다.

날짜 (#dates)

1
2
3
/* Java */
Date date = new Date();
model.addAttribute("date", date);
1
2
3
4
5
6
<!-- Thymeleaf 템플릿 -->
<p th:text="${#dates.format(date, 'yyyy/MM/dd HH:mm:ss')}"></p>
<p th:text="|${#dates.day(date)}일|"></p>
<p th:text="|${#dates.month(date)}월|"></p>
<p th:text="${#dates.monthName(date)}"></p>
<p th:text="|${#dates.year(date)}년|"></p>
1
2
3
4
5
6
<!-- HTML 출력 결과 -->
<p>2016/12/02 20:26:07</p>
<p>14일</p>
<p>12월</p>
<p>12월</p>
<p>2016년</p>

현재 날짜 (#dates.createNow())

현재 날짜는 #dates.createNow()로 취득한다.

1
2
<!-- Thymeleaf 템플릿 -->
<p th:text="${#dates.format(#dates.createNow(), 'yyyy년MM월dd일 HH시mm분ss초')}"></p>
1
2
<!-- HTML 출력 결과 -->
<p>2016년12월02일 20시26분08초</p>

수치표현 (#numbers)

정수 값 표현에는 #numbers.formatInteger를, 부동소수점 표현에는 #numbers.formatDecimal을 사용한다.

1
2
3
<!-- Thymeleaf 템플릿 -->
<p th:text="${#numbers.formatInteger(1000000, 3, 'COMMA')}"></p>
<p th:text="${#numbers.formatDecimal(123456.789, 3, 'COMMA', 2, 'POINT')}"></p>
1
2
3
<!-- HTML 출력 결과 -->
<p>1,000,000</p>
<p>123,456.79</p>

메시지 리소스

메시지 리소스 파일의 값을 표시할 때에는 #{…} 구문이라든지, #messages라는 표현 도구 객체(Expression Utility Object)를 사용한다.

메시지 표현

메시지 리소스에 placeholder가 있는 경우, 메시지 키 값 뒤에 (param1, param2, param3, …)의 형태로 기술한다.

1
2
3
4
# message properties file
app.message1=Hello
app.message2=Hello, {0}!
app.message3=Hello, {0}{1}
1
2
3
4
<!-- Thymeleaf 템플릿 -->
<p th:text="#{app.message1}"></p>
<p th:text="#{app.message2(${username})}"></p>
<p th:text="#{app.message3(${username},${suffix})}"></p>
1
2
3
4
<!-- HTML 출력 결과 -->
<p>Hello</p>
<p>Hello, kyeongjin!</p>
<p>Hello, kyeongjin!?</p>

메시지 키

메시지 키의 전부 또는 일부를 변수로 지정할 수 있다.

1
2
3
# message properties file
app.am.message=Good morning!
app.pm.message=Good afternoon!
1
2
3
4
5
/* Java */
String messageKey ="app.am.message";
model.addAttribute("messageKey", messageKey);
String ap = "pm";
model.addAttribute("ap", ap);
1
2
3
<!-- Thymeleaf 템플릿 -->
<p th:text="#{${messageKey}(${username})}"></p>
<p th:text="#{|app.${ap}.message|(${username})}"></p>
1
2
3
<!-- HTML 출력 결과 -->
<p>Good morning! kyeongjin</p>
<p>Good afternoon! kyeongjin</p>

#messages 객체

1
2
3
4
5
6
<!-- Thymeleaf 템플릿 -->
<p th:text="${#messages.msg('app.message1')}"></p>
<p th:text="${#messages.msg('app.message2', username)}"></p>
<p th:text="${#messages.msg('app.message3', username, suffix)}"></p>
<p th:text="${#messages.msg(messageKey, username)}"></p>
<p th:text="${#messages.msg('app.' + ap + '.message', username)}"></p>
1
2
3
4
5
6
<!-- HTML 출력 결과 -->
<p>Hello</p>
<p>Hello, kyeongjin!</p>
<p>Hello, kyeongjin!?</p>
<p>Good morning! kyeongjin</p>
<p>Good afternoon! kyeongjin</p>

URL 링크 표현

URL 링크를 표현할 때에는 @{…} 구문을을 사용하면 편리하다.

링크 형식

변수 값을 링크의 파라미터로 사용할 때에는 (파라미터명=${'변수명'}) 형태로 표현한다. 여러 개의 파라미터가 있는 경우에는 콤마로 구분하여 기술한다.

1
2
3
<!-- Thymeleaf 템플릿 -->
<a href="/user/profile" th:href="@{/user/profile(id=${'ab123'})}">profile</a>
<a href="/user/profile" th:href="@{/user/profile(id=${'ab123'},role=${'admin'})}">profile</a>
1
2
3
<!-- HTML 출력 결과 -->
<a href="/user/profile?id=ab123">profile</a>
<a href="/user/profile?id=ab123&amp;role=admin">profile</a>

REST 형식

변수 값을 URL의 일부로서 사용할 때에는 placeholder를 {placeholder명}으로 정의하고, 그곳에 끼워넣을 값을 (placeholder명=${'변수명'}) 형태로 표현한다.

1
2
<!-- Thymeleaf 템플릿 -->
<a href="index.html" th:href="@{/user/profile/{id}/{seq}(id=${'abc'},seq=${'1000'})}">profile</a>
1
2
<!-- HTML 출력 결과 -->
<a href="/user/profile/abc/1000">profile</a>

선택변수 표현

일반적으로 변수 값을 표현할 때에는 ${…} 구문을 사용하지만, *{…} 구문(선택변수식)으로도 변수 값을 표시할 수 있다. (단, 이 경우에는 선택된 객체가 없는 경우만 해당)

하기의 템플릿은 같은 결과 값이 출력된다.

1
2
3
<!-- Thymeleaf 템플릿 -->
<p th:text="${username}"></p>
<p th:text="*{username}"></p>
1
2
3
<!-- HTML 출력 결과 -->
<p>kyeongjin</p>
<p>kyeongjin</p>

th:object 속성으로 객체를 지정하면, 선택표현식은 해당 객체 내에 멤버 변수를 대상으로 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* Java : Model class */
public class Item {
private Long id;
private String name;
private Integer price;
private Date createAt;

public Item(Long id, String name, Integer price, Date createAt) {
this.id = id;
this.name = name;
this.price = price;
this.createAt = createAt;
}
...getter/setter는 생략...
}
1
2
3
/* Java : Controller */
Item item = new Item(10000L, "맥스봉", 500, new Date());
model.addAttributes("item", item);
1
2
3
4
5
6
7
8
9
10
11
<!-- Thymeleaf 템플릿 -->
<div th:object="${item}">
<dl>
<dt>ID</dt>
<dd th:text="*{id}"></dd>
<dt>NAME</dt>
<dd th:text="*{name}"></dd>
<dt>PRICE</dt>
<dd th:text="*{price}"></dd>
</dl>
</div>
1
2
3
4
5
6
7
8
9
10
11
<!-- HTML 출력 결과 -->
<div>
<dl>
<dt>ID</dt>
<dd>10000</dd>
<dt>NAME</dt>
<dd>맥스봉</dd>
<dt>PRICE</dt>
<dd>500</dd>
</dl>
</div>

위의 코드 중 Thymeleaf 템플릿에서 th:object 속성을 사용하지 않고 기술한다면 다음과 같이 기술해야 한다.

1
2
3
4
5
6
7
8
9
10
<div>
<dl>
<dt>ID</dt>
<dd th:text="*{item.id}"></dd>
<dt>NAME</dt>
<dd th:text="*{item.name}"></dd>
<dt>PRICE</dt>
<dd th:text="*{item.price}"></dd>
</dl>
</div>

반복 처리 (th:each)

th:each 속성을 사용해서 컬렉션을 제어할 수 있다.

1
2
3
4
5
6
7
/* Java */
List<Item> items = new ArrayList<>();
items.add(new Item(10000L, "맥스봉", 10, new Date()));
items.add(new Item(10001L, "감자칩", 30, new Date()));
items.add(new Item(10002L, "믹스넛", 10, new Date()));
items.add(new Item(10003L, "기네스", 40, new Date()));
model.addAttribute("items", items);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- Thymeleaf 템플릿 -->
<table class="table table-sprite">
<tr>
<th>count</th>
<th>id</th>
<th>name</th>
<th>price</th>
<th>create</th>
<th>current.id</th>
</tr>
<tr th:each="item, stat : ${items}" th:object="${item}">
<td th:text="*{id}">id</td>
<td th:text="*{name}">name</td>
<td th:text="*{price}">price</td>
<td th:text="*{createAt}">createAt</td>
<td th:text="${stat.current.id}"></td>
</tr>
</table>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!-- HTML 출력 결과 -->
<table class="table table-sprite">
<tr>
<th>count</th>
<th>id</th>
<th>name</th>
<th>price</th>
<th>create</th>
<th>current.id</th>
</tr>
<tr>
<td>1</td>
<td>10000</td>
<td>맥스봉</td>
<td>10</td>
<td>Sun Jan 10 00:39:13 KST 2016</td>
<td>10000</td>
</tr>
<tr>
<td>2</td>
<td>10001</td>
<td>감자칩</td>
<td>30</td>
<td>Sun Jan 10 00:39:13 KST 2016</td>
<td>10001</td>
</tr>
<tr>
<td>3</td>
<td>10002</td>
<td>믹스넛</td>
<td>10</td>
<td>Sun Jan 10 00:39:13 KST 2016</td>
<td>10002</td>
</tr>
<tr>
<td>4</td>
<td>10003</td>
<td>기네스</td>
<td>40</td>
<td>Sun Jan 10 00:39:13 KST 2016</td>
<td>10003</td>
</tr>
</table>

#numbers.sequence

#numbers.sequence는 인수로 지정한 2개의 수 범위에서 배열을 생성한다.

1
2
3
4
<!-- Thymeleaf 템플릿 -->
<th:block th:each="seq : ${#numbers.sequence(1,10)}">
<p th:text="${seq}">0</p>
</th:block>
1
2
3
4
5
6
7
8
9
10
11
<!-- HTML 출력 결과 -->
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
<p>6</p>
<p>7</p>
<p>8</p>
<p>9</p>
<p>10</p>

상태변수

상태변수 내용
index 0부터 시작되는 현재의 반복 위치
count 1부터 시작되는 현재의 반복 위치
size 전채 항목 개수
current 현재의 객체
even 현재의 반복 위치가 짝수인 경우, true
odd 현재의 반복 위치가 홀수인 경우, true
first 현재의 반복 위치가 최초인 경우, true
last 현재의 반복 위치가 최종인 경우, true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- Thymeleaf 템플릿 -->
<table class="table table-sprite">
<tr>
<th>index</th>
<th>count</th>
<th>size</th>
<th>current</th>
<th>even</th>
<th>odd</th>
<th>first</th>
<th>last</th>
<th>seq</th>
</tr>
<tr th:each="seq, stat : ${#numbers.sequence(1,3)}">
<td th:text="${stat.index}"></td>
<td th:text="${stat.count}"></td>
<td th:text="${stat.size}"></td>
<td th:text="${stat.current}"></td>
<td th:text="${stat.even}"></td>
<td th:text="${stat.odd}"></td>
<td th:text="${stat.first}"></td>
<td th:text="${stat.last}"></td>
<td th:text="${seq}"></td>
</tr>
</table>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!-- HTML 출력 결과 -->
<table class="table table-sprite">
<tr>
<th>index</th>
<th>count</th>
<th>size</th>
<th>current</th>
<th>even</th>
<th>odd</th>
<th>first</th>
<th>last</th>
<th>seq</th>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>3</td>
<td>1</td>
<td>true</td>
<td>false</td>
<td>true</td>
<td>false</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>2</td>
<td>false</td>
<td>true</td>
<td>false</td>
<td>false</td>
<td>2</td>
</tr>
<tr>
<td>2</td>
<td>3</td>
<td>3</td>
<td>3</td>
<td>true</td>
<td>false</td>
<td>false</td>
<td>true</td>
<td>3</td>
</tr>
</table>

로컬 변수 (th:with)

th:with 속성을 사용하면 블록 내에서 유효한 지역 변수를 정의할 수 있다.

1
2
3
4
5
<!-- Thymeleaf 템플릿 -->
<div th:with="x=${100},y=${200}">
<p th:text="${x}"></p>
<p th:text="${y}"></p>
</div>
1
2
3
4
5
<!-- HTML 출력 결과 -->
<div>
<p>100</p>
<p>200</p>
</div>

유사 블록 (th:block)

임의로 블록을 정의하는 th:block 속성은 thymeleaf 버전 2.1부터 도입된 비교적 최신 속성이다.

1
2
3
4
5
<!-- Thymeleaf 템플릿 -->
<th:block th:with="x=${100},y=${200}">
<p th:text="${x}"></p>
<p th:text="${y}"></p>
</th:block>
1
2
3
<!-- HTML 출력 결과 -->
<p>100</p>
<p>200</p>

#ids 객체

#ids 객체는 입력 폼 내 input 태그의 id 속성과 label 태그의 for 속성을 연결할 경우 편리하다.

1
2
3
4
5
6
7
<!-- Thymeleaf 템플릿 -->
<form>
<th:block th:each="seq : ${#numbers.sequence(1,3)}">
<input type="text" name="hobby" th:id="${#ids.seq('id_hobby_')}" value="" />
<label th:text="|hobby_${seq}|" th:for="${#ids.prev('id_hobby_')}">field</label>
</th:block>
</form>
1
2
3
4
5
6
7
8
9
<!-- HTML 출력 결과 -->
<form>
<input type="text" name="hobby" value="" id="id_hobby_1">
<label for="id_hobby_1">hobby_1</label>
<input type="text" name="hobby" value="" id="id_hobby_2">
<label for="id_hobby_2">hobby_2</label>
<input type="text" name="hobby" value="" id="id_hobby_3">
<label for="id_hobby_3">hobby_3</label>
</form>
function description
#ids.seq 시퀀스 값을 반환한 후에 시퀀스 값을 1 증가시킨다.
#ids.prev 이전 시퀀스 값을 반환한다.
#ids.next 다음 시퀀스 값을 반환한다.

Spring Bean

Spring Framework 에서 관리되고 있는 bean을 Thymeleaf에서 참조할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* Java */
@Configuration(value="appConfig")
public class AppConfig {
@Value("${app.mode}")
private String mode;
public String getMode() {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
public String getCurrentDate() {
FastDateFormat df = FastDateFormat.getInstance("yyyy/MM/dd");
return df.format(new Date());
}
}
1
2
3
<!-- Thymeleaf 템플릿 -->
<p th:text="${@appConfig.getMode()}"></p>
<p th:text="${@appConfig.getCurrentDate()}"></p>
1
2
3
<!-- HTML 출력 결과 -->
<p>dev</p>
<p>2016/01/10</p>

Spring Type Convention

$이나 * 처럼 2중 중괄호를 사용하면 Spring Type Convention을 이용해서 변수 값을 변환하여 표시할 수 있다.

1
2
3
/* Java */
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date createAt;
1
2
<!-- Thymeleaf 템플릿 -->
<td th:text="*{{createAt}}">createAt</td>
1
2
<!-- HTML 출력 결과 -->
<td>2016-01-10</td>
공유하기