https://yelin1217.tistory.com/458
[TIL/View Template] thymeleaf 문법 - 기본 기능(2)
이전에 작성한 thymeleaf 문법 - 기본 기능 (1) 글과 이어지는 내용입니다!https://yelin1217.tistory.com/457 [TIL/View Template] thymeleaf 문법 - 기본 기능 (1)[타임리프 기본 기능의 종류]- 링크 : https://www.thymeleaf.o
yelin1217.tistory.com
1. 반복
타임리프에서 반복은 th:each를 사용한다. 추가로 반복에서 사용할 수 있는 여러 상태 값을 지원한다.
반복 기능
<tr th:each="user : ${users}">
반복시 오른쪽 컬렉션(${users})의 값을 하나씩 꺼내서 왼쪽 변수(user)에 담아서 태그를 반복 실행한다.
th:each는 List 뿐만 아니라 배열, java.util.Iterable, java.util.Enumeration을 구현한 모든 객체를 반복에 사용할 수 있다.
Map도 사용할 수 있는데 이 경우 변수에 담기는 값은 Map.Entry이다.
반복 상태 유지
<tr th:each="user, userStat : ${users}">
반복의 두번째 파라미터를 설정해서 반복의 상태를 확인할 수 있다.
두번째 파라미터는 생략이 가능한데, 생략하면 지정한 변수명 + Stat가 된다.
index : 0부터 시작하는 값
count : 1부터 시작하는 값
size : 전체 사이즈
even , odd : 홀수, 짝수 여부( boolean )
first , last :처음, 마지막 여부( boolean )
current : 현재 객체
controller
@GetMapping("/each")
public String each(Model model) {
addUsers(model);
return "basic/each";
}
private void addUsers(Model model) {
List<User> list = new ArrayList<>();
list.add(new User("userA", 10));
list.add(new User("userB", 20));
list.add(new User("userC", 30));
model.addAttribute("users", list);
}
@Data
static class User {
private String username;
private int age;
public User(String username, int age) {
this.username = username;
this.age = age;
}
}
each.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>기본 테이블</h1>
<table border="1">
<tr>
<th>username</th>
<th>age</th>
</tr>
<tr th:each="user : ${users}">
<td th:text="${user.username}">username</td>
<td th:text="${user.age}">0</td>
</tr>
</table>
<h1>반복 상태 유지</h1>
<table border="1">
<tr>
<th>count</th>
<th>username</th>
<th>age</th>
<th>etc</th>
</tr>
<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>
</table>
</body>
</html>
결과는 아래와 같다.

2. 조건부 평가
타임리프의 조건식은 if와 unless가 있다. unless는 if의 반대이다.
타임리프는 해당 조건이 맞지 않으면 태그 자체를 렌더링 하지 않는다.
switch도 사용할 수 있는데 *은 만족하는 조건이 없을 때 사용하는 디폴트이다.
Controller
@GetMapping("/condition")
public String condition(Model model) {
addUsers(model);
return "basic/condition";
}
private void addUsers(Model model) {
List<User> list = new ArrayList<>();
list.add(new User("userA", 10));
list.add(new User("userB", 20));
list.add(new User("userC", 30));
model.addAttribute("users", list);
}
@Data
static class User {
private String username;
private int age;
public User(String username, int age) {
this.username = username;
this.age = age;
}
}
condition.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>if, unless</h1>
<table border="1">
<tr>
<th>count</th>
<th>username</th>
<th>age</th>
</tr>
<tr th:each="user, userStat : ${users}">
<td th:text="${userStat.count}">1</td>
<td th:text="${user.username}">username</td>
<td>
<span th:text="${user.age}">0</span>
<span th:text="'미성년자'" th:if="${user.age lt 20}"></span>
<span th:text="'미성년자'" th:unless="${user.age ge 20}"></span>
</td>
</tr>
</table>
<h1>switch</h1>
<table border="1">
<tr>
<th>count</th>
<th>username</th>
<th>age</th>
</tr>
<tr th:each="user, userStat : ${users}">
<td th:text="${userStat.count}">1</td>
<td th:text="${user.username}">username</td>
<td th:switch="${user.age}">
<span th:case="10">10살</span>
<span th:case="20">20살</span>
<span th:case="*">기타</span>
</td>
</tr>
</table>
</body>
</html>
결과는 아래와 같다.

3. 주석
1) 표준 HTML 주석 :
자바스크립트의 표준 HTML 주석은 타임리프가 렌더링 하지 않고, 그대로 남겨둔다.
2) 타임리프 파서 주석 :
타임리프 파서 주석은 타임리프의 진짜 주석이다. 렌더링에서 주석 부분을 제거한다.
3) 타임리프 프로토타입 주석 :
타임리프 프로토타입은 약간 특이한데, HTML 주석에 약간의 구문을 더했다. HTML 파일을 웹 브라우저에서 그대로 열어보면 HTML 주석이기 때문에 이 부분이 웹 브라우저가 렌더링하지 않는다. 타임리프 렌더링을 거치면 이 부분이 정상 렌더링 된다.
쉽게 이야기해서 HTML 파일을 그대로 열어보면 주석처리가 되지만, 타임리프를 렌더링 한 경우에만 보이는 기능이다.
contoller
@GetMapping("/comments")
public String comments(Model model) {
model.addAttribute("data", "Spring!");
return "basic/comments";
}
comments.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>예시</h1>
<span th:text="${data}">html data</span>
<h1>1. 표준 HTML 주석</h1>
<!--
<span th:text="${data}">html data</span>
-->
<h1>2. 타임리프 파서 주석</h1>
<!--/* [[${data}]] */--> <!--한줄 표현-->
<!--/*--> <!--여려줄 표현-->
<span th:text="${data}">html data</span>
<!--*/-->
<h1>3. 타임리프 프로토타입 주석</h1>
<!--파일 자체로 열때는 HTML 주석으로 보여줄거고, 서버 사이드 렌더링 했을 때만 보여줄거야-->
<!--/*/
<span th:text="${data}">html data</span>
/*/-->
</body>
</html>
결과는 아래와 같다.

4. 블록
th:block은 HTML 태그가 아닌 타임리프의 유일한 자체 태그이다.
타임리프의 특성상 HTML 태그안에 속성으로 기능을 정의해서 사용하는데, 아래 예시처럼 이렇게 사용하기 애매한 경우에 사용하면된다.
<th:block>은 렌더링시 제거된다.
Controller
@GetMapping("/block")
public String block(Model model) {
addUsers(model);
return "basic/block";
}
private void addUsers(Model model) {
List<User> list = new ArrayList<>();
list.add(new User("userA", 10));
list.add(new User("userB", 20));
list.add(new User("userC", 30));
model.addAttribute("users", list);
}
@Data
static class User {
private String username;
private int age;
public User(String username, int age) {
this.username = username;
this.age = age;
}
}
block.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 2개의 태그 블럭을 반복하고 싶을 때 사용함. block 안에서 each가 돌아감 -->
<th:block th:each="user : ${users}">
<div>
사용자 이름1 <span th:text="${user.username}"></span>
사용자 나이1 <span th:text="${user.age}"></span>
</div>
<div>
요약 <span th:text="${user.username} + ' / ' + ${user.age}"></span>
</div>
</th:block>
</body>
</html>
결과는 아래와 같다.

5. 자바스크립트 인라인
타임리프는 자바스크립트에서 타임리프를 편하게 사용할 수 있는 자바스크립트 인라인 기능을 제공한다.
텍스트 렌더링
var username = [[${user.username}]];
인라인 사용 전) var username = userA;
인라인 사용 후) var username = "userA";
인라인 사용 전 렌더링 결과를 보면 userA 라는 변수 이름이 그대로 남아있다.
타임리프 입장에서는 정확하게 렌더링 한 것이지만 기대한 것은 다음과 같은 "userA"라는 문자일 것이다.
결과적으로 userA가 변수명으로 사용되어서 자바스크립트 오류가 발생한다.
다음으로 나오는 숫자 age의 경우에는 " 가 필요 없기 때문에정상 렌더링 된다.
인라인 사용 후 렌더링 결과를 보면 문자 타입인 경우 " 를 포함해준다. 추가로 자바스크립트에서 문제가 될 수 있는 문자가 포함되어 있으면 이스케이프 처리도 해준다. ex) " \"
자바스크립트 내추럴 템플릿
타임리프는 HTML 파일을 직접 열어도 동작하는 내추럴 템플릿 기능을 제공한다.
자바스크립트 인라인 기능을 사용하면 주석을 활용해서 이 기능을 사용할 수 있다.
var username2 = /*[[${user.username}]]*/ "test username";
인라인 사용 전) var username2 = /*userA*/ "test username";
인라인 사용 후) var username2 = "userA";
인라인 사용 전 결과를 보면 정말 순수하게 그대로 해석을 해버렸다. 따라서 내추럴 템플릿 기능이 동작하지 않고, 심지어 렌더링 내용이 주석처리 되어 버린다. 인라인 사용 후 결과를 보면 주석 부분이 제거되고, 기대한 "userA"가 정확하게 적용된다.
객체
객체는 JSON으로 자동 변환해준다. 인라인 사용 전에는 toString()이 호출된 값이다.
var user = [[${user}]];
인라인 사용 전) var user = BasicController.User(username=userA, age=10);
인라인 사용 후) var user = {"username":"userA","age":10};
each
자바스크립트 인라인에서 each도 사용할 수 있는데 예시와 결과는 아래 코드와 결과물을 확인하자
Controller
@GetMapping("/javascript")
public String block(Model model) {
model.addAttribute("user", new User("userA", 10));
addUsers(model);
return "basic/javascript";
}
private void addUsers(Model model) {
List<User> list = new ArrayList<>();
list.add(new User("userA", 10));
list.add(new User("userB", 20));
list.add(new User("userC", 30));
model.addAttribute("users", list);
}
@Data
static class User {
private String username;
private int age;
public User(String username, int age) {
this.username = username;
this.age = age;
}
}
javascript.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 자바스크립트 인라인 사용 전 -->
<script>
var username = [[${user.username}]];
var age = [[${user.age}]];
//자바스크립트 내추럴 템플릿
var username2 = /*[[${user.username}]]*/ "test username";
//객체
var user = [[${user}]];
</script>
<!-- 자바스크립트 인라인 사용 후 -->
<script th:inline="javascript">
var username = [[${user.username}]];
var age = [[${user.age}]];
//자바스크립트 내추럴 템플릿
var username2 = /*[[${user.username}]]*/ "test username";
//객체
var user = [[${user}]];
</script>
<!-- 자바스크립트 인라인 each -->
<script th:inline="javascript">
[# th:each="user, stat : ${users}"]
var user[[${stat.count}]] = [[${user}]];
[/]
</script>
</body>
</html>
결과는 아래와 같다.

출처 : 인프런 김영한 MVC2
'TIL > View Template' 카테고리의 다른 글
[TIL/View Template] thymeleaf - 기본 기능(4) (0) | 2024.06.11 |
---|---|
[TIL/View Template] thymeleaf 문법 - 기본 기능(2) (0) | 2024.06.09 |
[TIL/View Template] thymeleaf 문법 - 기본 기능 (1) (0) | 2024.06.03 |
[TIL/View Template] thymeleaf 극소수의 기능 (0) | 2024.06.02 |
[SIST] JSP_days14_JSON과 XML/JSON으로 ajax 처리 (0) | 2022.07.03 |