Spring Boot

5. 타임리프 사용하기 - 패스트캠퍼스 백엔드 부트캠프 3기

gkss2tpt 2025. 3. 5. 17:48

1. 타임리프(thymleaf)란?

  • 자바 웹개발에 이상적인 '모던 서버 사이드 자바 템플릿 엔진'
  • HTML과 유사해서 디자이너와 개발자간의 협업을 쉽게 해준다.
  • 확장성이 뛰어나며, 커스터마이징이 쉽다.
  • 다양한 도구와 확장 프로그램으로 구성된 에코 시스템 제공

2. 타임리프 템플릿

  • 타임리프 템플릿(*.html)은 HTML과 유사해서 편집 후 내용 확인이 쉽다.
  • th:* 속성은 타임리프 전용 속성이며, 브라우저는 이를 무시한다.

 

3. th:text와 th:utext

  • th:text는 ${...}을 해석해서 태그의 텍스트 노드로
<span th:text="${lastName}">Namkung</span>
<span>[[${lastName}]]</span>
  • 스프링 컨트롤러의 작업결과를 텍스트로 보여준다.
  • 문자열('...') 결합(+)과 리터럴 치환(|...|)
<span th:text="'My name is' + ${lastName}+','+${firstName}"></span>
<span th:text="|My name is ${lastName}, ${firstName}|"></span>
  • th:utext는 태그의 <, >를 &lt;, &gt;로 바꾸지 않고 그대로
<span th:text="${'<i>Namkung,Seong</i>'}">Namkung,Seong</span>
<span th:utext="${'<i>Namkung,Seong</i>'}">Namkung,Seong</span>

  • test.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymleaf.org">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<h1 th:text="${lastName}">lastName</h1>
<h1>[[${firstName}]]</h1>
</body>
</html>
  • TestController
@GetMapping("/test")
public String test(Model m){
    m.addAttribute("lastName", "choi");
    m.addAttribute("firstName", "hoe");

    return "test";
}

 

  • browser에서 source를 보면 Model로 넘겨준 값들이 잘 바뀌어있다.

  • utext의 < > 자동 변경
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymleaf.org">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<h1 th:text="${lastName}">lastName</h1>
<h1>[[${firstName}]]</h1>
<span th:text="${'<i>choi,hoe</i>'}" ></span>
<span th:utext="${'<i>choi,hoe</i>'}" ></span>
</body>
</html>

  • utext는 태그에 사용되는 부등호를 변환하지않고 그대로 보여준다.
  • 템플릿
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymleaf.org">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
<h1 th:text="${lastName}">lastName</h1>
<h1>[[${firstName}]]</h1>
<h1 th:text="'My name is ' + ${lastName} + ', ' + ${firstName}">My name is lastName firstName</h1>
<h1 th:text="|My name is ${lastName}, ${firstName}|"></h1>
<span th:text="${'<i>choi,hoe</i>'}" ></span>
<span th:utext="${'<i>choi,hoe</i>'}" ></span>
</body>
</html>
  • 코드사이에 || 를 넣어주면 ''나 +를 안넣어줘도된다.

 

4. th:if, th:unless, th:switch로 조건부 처리

  • 특정 조건에 맞는 경우만 처리
<tr th:if="${list.size}==0">
    <td>게시물이 없습니다.</td>
</tr>
  • if not(반대) ~가아닐때
<tr th:unless="${list.size}!=0">
    <td>게시물이 없습니다.</td>
</tr>
  • 삼항 연산자
<tr th:class="${status.even} ? 'even' : 'odd'">
    ...
</tr>
  • swtich문
<div th:switch="${user.grade}">
    <span th:case="A">특급</span>
    <span th:case="B">고급</span>
    <span th:case="C">중급</span>
    <span th:case="*">기타</span>
</div

<table border="1px">
    <tr th:each="item : ${list}">
        <td th:text="${item}"></td>
    </tr>
    <tr th:if="${list.size()}==0">
        <td>게시물이 없습니다.</td>
    </tr>
</table>
@GetMapping("/test")
public String test(Model m){
    m.addAttribute("lastName", "choi");
    m.addAttribute("firstName", "hoe");
    m.addAttribute("list", Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee"));
    return "test";
}
  • list추가

  • 게시물이 없습니다가 나오지 않는데...
<table border="1px">
    <tr th:each="item : ${list}">
        <td th:text="${item}"></td>
    </tr>
    <tr th:unless="${list.size()}==0">
        <td>게시물이 없습니다.</td>
    </tr>
</table>
  • th:if를 th:unless로 바꿔주면...

  • 게시물이 없습니다까지 나온다. -> size가 0이 아니기때문에 나온것

5. th:each와 th:block을 이용한 반복(1)

  • Iterable의 반복 처리는 th:each 또는 th:block 사용. 향상된 for문과 유사
  • list의 요소가 하나씩 opt로 들어간다.
<select multiple>
    <option th:each="opt : ${list}" th:value="${opt}">[[${opt}]]</option>
</select>
  • th:each를 쓰기 어려운 경우, th:block으로 처리
<th:block th:each="opt : ${list}">
    <input type="checkbox" th:value="${opt}">[[${opt}]]<br/>
</th:block>
  • input태그의 범위는 <input ... >까지라서 [[${opt}]] 코드는 반복이되지 않는다.

5. th:each와 th:block을 이용한 반복(2) - status변수

  • 반복 관련 정보(index(반복횟수 0부터 시작), count(반복횟수 1부터시작), size(list사이즈), odd(홀수), even(짝수), first(첫번째), last(마지막), current(현재)) 제공
<select multiple>
    <option th:each="opt, status : ${list}" th:value="${opt}">
    [[${status.index}]].[[${opt}]]
    </option>
</select>
  • status는 객체 -> 반복안에서 객체를 참조해서 사용가능
  • status변수의 선언을 생략하면, '변수명+Stat'을 사용
<select multiple>
<option th:each="opt : ${list}" th:value="${opt}" th:selected="${optStat.first}">
    [[${optStat.index}]].[[${opt}]]
</option>
</select>