| 표현식 |
문법 |
설명 |
사용 예시 |
| Variable Expressions |
${...} |
변수 값을 출력할 때 사용 |
${user.name} |
| Selection Variable Expressions |
*{...} |
선택된 객체(현재 객체)의 값을 출력 |
*{name} |
| Message Expressions |
#{...} |
국제화 메시지 출력 |
#{home.message} |
| Link URL Expressions |
@{...} |
URL 경로 생성 |
@{/home} |
| Fragment Expressions |
~{...} |
다른 템플릿 조각 포함 |
~{layout/header} |
1. 텍스트 출력
1) th:text
- 태그 안의 기존 텍스트를 통째로 치환
- HTML 특수문자(<, >, & 등)를 자동으로 이스케이프 처리
- th:text 대신 인라인 표현식 [[ ]]으로도 사용 가능
<p th:text="${user.name}">기본값</p> # 기본값 → user.name 치환
<p>[[${user.name}]]</p>
2) th:utext
- HTML 태그가 포함된 텍스트를 이스케이프 없이 그대로 출력
- 이스케이프를 하지 않으므로 XSS 공격에 주의해서 사용
- th:utext 대신 인라인 표현식 [( )]으로도 사용 가능
<!-- model에서 "안녕하세요 <b>홍길동</b>" 을 전달했을 때 -->
<!-- th:text → 태그가 문자로 그대로 출력됨 -->
<p th:text="${msg}"></p>
<!-- 결과: 안녕하세요 <b>홍길동</b> -->
<!-- th:utext → 태그가 실제 HTML로 렌더링됨 -->
<p th:utext="${msg}"></p>
<!-- 결과: 안녕하세요 홍길동(굵게) -->
<p>[(${msg})]</p>
2. 속성 바인딩
1) th:value
- <input> 등의 value 속성에 서버 값을 바인딩
<input type="text" th:value="${user.name}" />
2) th:href
- <a> 태그의 href 속성에 URL을 동적으로 바인딩
- @{ } 표현식으로 URL을 작성하며 경로 변수와 파라미터도 지원
<!-- 기본 -->
<a th:href="@{/user/list}">목록</a>
<!-- 경로 변수 -->
<a th:href="@{/user/{id}(id=${user.id})}">상세</a>
<!-- 결과: /user/1 -->
<!-- 쿼리 파라미터 -->
<a th:href="@{/user/list(page=1, size=10)}">목록</a>
<!-- 결과: /user/list?page=1&size=10 -->
<!-- 경로 변수 + 쿼리 파라미터 혼합 -->
<a th:href="@{/user/{id}/posts(id=${user.id}, page=1)}">게시글</a>
<!-- 결과: /user/1/posts?page=1 -->
3) th:src
- <img>, <script> 등의 src 속성에 동적으로 값을 바인딩
<img th:src="@{/images/{fileName}(fileName=${user.profileImg})}" />
<script th:src="@{/js/app.js}"></script>
4) th:action
- <form> 태그의 action 속성에 URL을 바인딩
<form th:action="@{/user/save}" method="post">
<form th:action="@{/user/{id}(id=${user.id})}" method="post">
5) th:attr
- 특정 속성 전용 문법이 없을 때 임의의 속성을 동적으로 설정
<button th:attr="data-id=${user.id}">삭제</button>
<!-- 결과: <button data-id="1">삭제</button> -->
<!-- 여러 속성 동시에 설정 -->
<button th:attr="data-id=${user.id}, data-name=${user.name}">수정</button>
3. 조건부 렌더링
1) th:if / th:unless
- th:if : 조건이 true일 때 요소를 렌더링
- th:unless : 조건이 false일 때 요소를 렌더링 (th:if의 반대)
- 조건이 맞지 않으면 해당 태그 자체가 HTML에서 제거됨
<p th:if="${user.isAdmin}">관리자입니다.</p>
<p th:unless="${user.isAdmin}">일반 사용자입니다.</p>
2) th:switch / th:case
- Java의 switch문과 동일한 역할
- th:case="*"는 default에 해당
<div th:switch="${user.role}">
<p th:case="'ADMIN'">관리자</p>
<p th:case="'USER'">일반 사용자</p>
<p th:case="*">알 수 없음</p>
</div>
4. 반복문
1) th:each
- 컬렉션을 순회하면서 HTML 요소를 반복 생성
- 두 번째 변수(iterStat)로 반복 상태 정보를 얻을 수 있음 (생략 가능)
<tr th:each="user : ${userList}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
</tr>
2) 반복 상태 변수 (iterStat)
| 속성 |
타입 |
의미 |
| index |
int |
0부터 시작하는 인덱스 |
| count |
int |
1부터 시작하는 순번 |
| size |
int |
전체 요소 수 |
| first |
boolean |
첫 번째 요소 여부 |
| last |
boolean |
마지막 요소 여부 |
| even |
boolean |
짝수 번째 여부 (count 기준) |
| odd |
boolean |
홀수 번째 여부 (count 기준) |
<tr th:each="user, iterStat : ${userList}"
th:classappend="${iterStat.odd} ? 'odd-row' : 'even-row'">
<td th:text="${iterStat.count}"></td>
<td th:text="${user.name}"></td>
<td th:text="${iterStat.last} ? '마지막' : ''"></td>
</tr>
5. CSS / 스타일 제어
1) th:class
<p th:class="${isActive} ? 'active' : 'inactive'">상태</p>
2) th:classappend
- 기존 class를 유지하면서 조건에 따라 클래스를 추가
<p class="btn" th:classappend="${isActive} ? ' active'">버튼</p>
<!-- 결과: class="btn active" 또는 class="btn" -->
3) th:style
<p th:style="'color:' + ${fontColor} + '; font-size:16px;'">텍스트</p>