- 스프링에서 JSP 위주로 View를 개발하는 것처럼 스프링 부트는 Thymeleaf라는 템플릿 엔진 이용
1. Thymeleaf 기초 문법
1) 인텔리제이 설정
- Thymeleaf를 이용하기 위해 html 파일의 네임스페이스에 Thymeleaf를 지정하는 것
- 네임스페이스를 지정하면 'th:'와 같은 Thymeleaf의 모든 기능을 사용할 수 있게됨
<!-- hello.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${msg}"></h1>
</body>
</html>
- 'th:'로 시작하는 기능을 사용할 수는 있지만 Model에 담긴 데이터를 사용할 때 '해당 변수를 찾을 수 없다'는 에러가 발생할 수 있어 인텔리제이의 Setting > Thymeleaf 검색 > Unresolved references in Thymeleaf expression variables' 체크 해제

- Thymeleaf 출력
- Thymeleaf는 Model로 전달된 데이터를 출력하기 위해 HTML 태그 내에 'th:,,'로 시작하는 속성을 이용하거나 인라인 이용
- SampleController에서 ex1()을 추가해서 '/ex/ex1'이라는 경로 호출할 때 동작하도록 구성
// SampleController
package org.zerock.b01.controller;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Arrays;
import java.util.List;
@Controller
@Log4j2
public class SampleController {
...
@GetMapping("/ex/ex1")
public void ex1(Model model) {
List<String> list = Arrays.asList("AAA", "BBB", "CCC", "DDD");
model.addAttribute("list", list);
}
}
- templates > ex 디렉토리 생성 > ex1.html 추가하여 결과화면 생성
<!-- ex1.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h4>[[${list}]]</h4>
<hr/>
<h4 th:text="${list}"></h4>
</body>
</html>

- th:with를 이용한 변수 선언
- Thymeleaf를 이용하는 과정에서 임시로 변수를 선언해야 하는 상황에서 'th:with'를 이용해서 간단히 처리 가능
- 'th:with'로 만드는 변수는 '변수명 = 값' 형태로, ','를 이용해 여러 개 선언 가능
<!-- hello.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${msg}"></h1>
<!-- 임시 변수 선언 -->
<div th:with="num1 = ${10}, num2 = ${20}">
<h4 th:text="${num1 + num2}"></h4>
</div>
</body>
</html>

2) 반복문과 제어문 처리
- 크게 두 가지 방법
- 반복이 필요한 태그에 'th:each'를 적용하는 방법
- <th:block>이라는 별도의 태그를 이용하는 방법
<!-- ex1.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 반복이 필요한 태그에 'th:each'를 적용하는 방법 -->
<ul>
<li th:each="str: ${list}" th:text="${str}"></li>
</ul>
<!-- <th:block>이라는 별도의 태그를 이용하는 방법 -->
<ul>
<th:block th:each="str: ${list}">
<li>[[${str}]]</li>
</th:block>
</ul>
</body>
</html>
- 결과는 동일

- 반복문의 status 변수
- Thymeleaf는 th:each를 처리할 때 현재 반복문의 내부 상태에 변수를 추가해서 사용할 수 있음
- 일명 status 변수라고 하며 index / count / size / first / last / odd / even 등을 이용해 자주 사용하는 값 출력 가
<!-- ex1.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
...
<ul>
<li th:each="str,status: ${list}">
[[${status.index}]] -- [[${str}]]
</li>
</ul>
</body>
</html>

- th:if / th:unless / th:switch
- Thymeleaf는 제어문의 형태로 th:if / th:unless / th:switch를 이용할 수 있음
<!-- ex1.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
...
<ul>
<li th:each="str,status: ${list}">
<span th:if="${status.odd}">ODD -- [[${str}]]</span>
<span th:unless="${status.odd}">EVEN -- [[${str}]]</span>
</li>
</ul>
</body>
</html>

- '? ' 사용하여 더 편하게 이항 혹은 삼항 처리 가
<!-- ex1.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
...
<!-- 이항 연산자로 사용 -->
<ul>
<li th:each="str,status: ${list}">
<span th:text="${status.odd}?'ODD ---' + ${str}"></span>
</li>
</ul>
<!-- 삼항 연산자로 사용 -->
<ul>
<li th:each="str,status: ${list}">
<span th:text="${status.odd}?'ODD ---' + ${str} : 'EVEN ---' + ${str}"></span>
</li>
</ul>
</body>
</html>

- th:switch는 th:case와 같이 사용해서 Switch 문을 처리할 때 사용할 수 있음
<!-- ex1.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
...
<!-- 3으로 나눈 나머지의 결과에 따라 각각의 결과를 출력 -->
<ul>
<li th:each="str,status: ${list}">
<th:block th:switch="${status.index % 3}">
<span th:case="0">0</span>
<span th:case="1">1</span>
<span th:case="2">2</span>
</th:block>
</li>
</ul>
</body>
</html>

3) Thymeleaf 링크 처리
- Thymeleaf에서는 @로 링크를 작성하면 링크 처리됨
<a th:href="@{/hello}">Go to /hello</a>
- 링크의 쿼리 스트링 처리
- 링크를 'key=value'의 형태로 필요한 파라미터를 처리해야 할 때 상당히 편리
- 쿼리 스트링은 '()'를 이용해서 파라미터의 이름과 값을 지정
<a th:href="@{/hello(name='AAA', age=16)}">Go to /hello</a>

- 한글이나 공백에 대한 URL 인코딩 처리가 자동으로 이루어짐
<a th:href="@{/hello(name='한글 처리', age=16)}">Go to /hello</a>
- 링크를 만드는 값이 배열과 같이 여러 개일 때는 자동으로 같은 이름의 파라미터로 처리
<a th:href="@{/hello(types=${{'AA', 'BB', 'CC'}}, age=16)}">Go to /hello</a>

2. Thymeleaf의 특별한 기능들
1) 인라인 처리
- Thymeleaf에서 상황에 따라 동일한 데이터를 다르게 출력해 주는 인라인 기능은 자바스크립트를 사용할 때 편리한 기능
- 다양한 종류의 데이터를 Model로 담아서 전달하는 메서드를 SampleController에 추가
// SampleController
package org.zerock.b01.controller;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Arrays;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@Controller
@Log4j2
public class SampleController {
...
class SampleDTO {
private String p1,p2,p3;
public String getP1() {
return p1;
}
public String getP2() {
return p2;
}
public String getP3() {
return p3;
}
}
@GetMapping(("/ex/ex2"))
public void ex2(Model model) {
log.info("ex/ex2................");
List<String>strList = IntStream.range(1,10)
.mapToObj(i -> "Data"+i)
.collect(Collectors.toList());
model.addAttribute("list", strList);
Map<String, String> map = new HashMap<>();
map.put("A","AAAA");
map.put("B","BBBB");
model.addAttribute("map", map);
SampleDTO sampleDTO = new SampleDTO();
sampleDTO.p1 = "Value -- p1";
sampleDTO.p2 = "Value -- p2";
sampleDTO.p3 = "Value -- p3";
model.addAttribute("dto", sampleDTO);
}
}
- ex2 화면 구성
<!-- ex2.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div th:text="${list}"></div>
<div th:text="${map}"></div>
<div th:text="${dto}"></div>
<script th:inline="javascript">
const list = [[${list}]]
const map = [[${map}]]
const dto = [[${dto}]]
console.log(list)
console.log(map)
console.log(dto)
</script>
</body>
</html>
- html은 기존처럼 출력되고, <script> 부분은 자바스크립트에 맞는 문법으로 만들어지는 것을 확인

2) Thymeleaf의 레이아웃 기능
- <th:block>을 이용하면 레이아웃을 만들고 특정한 페이지에서 필요한 부분만 작성하는 방식으로 개발 가능
- 별도의 라이브러리 필요하므로 build.gradle에서 추가
// build.gradle
dependencies {
...
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.1.0'
}
- templates > layout 폴더 생성 > 레이아웃을 위한 layout1.html 작성
<!-- layout1.html -->
<!DOCTYPE html>
<!-- thymeleaf의 layout 작성을 위한 네임스페이스 지정 -->
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Layout Page</title>
</head>
<body>
<div>
<h3>Sample Layout Header</h3>
</div>
<!-- layout:fragment 속성을 이용하면 나중에 다른 파일에서 해당 부분만 개발 가능 -->
<div layout:fragment="content">
<p>Page content goes here</p>
</div>
<div>
<h3>Sample Layout Footer</h3>
</div>
<th:block layout:fragment="script">
</th:block>
</body>
</html>
- Samplecontroller에 레이아웃 예제를 위한 ex3()을 추가
// SampleController
package org.zerock.b01.controller;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Arrays;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@Controller
@Log4j2
public class SampleController {
...
@GetMapping("/ex/ex3")
public void ex3(Model model) {
model.addAttribute("arr", new String[]{"AAA", "BBB", "CCC"});
}
}
- layout1.html에서 layout:fragment 속성으로 처리했던 content와 script부분을 다른 파일인 ex3에서 개발할 수 있음
<!-- ex3 -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout1.html}">
<div layout:fragment="content">
<h1>ex3.html</h1>
</div>

<!-- ex3 -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout1.html}">
<div layout:fragment="content">
<h1>ex3.html</h1>
</div>
<script layout:fragment="script" th:inline="javascript">
const arr = [[${arr}]]
</script>

'back-end > Java' 카테고리의 다른 글
[자바 웹 개발 워크북] 5.1 - 스프링 부트 (0) | 2023.03.14 |
---|---|
[자바 웹 개발 워크북] 4.4 - 스프링 Web MVC 구현하기(5) (0) | 2023.02.22 |
[자바 웹 개발 워크북] 4.4 - 스프링 Web MVC 구현하기(4) (0) | 2023.02.21 |
[자바 웹 개발 워크북] 4.4 - 스프링 Web MVC 구현하기(3) (0) | 2023.02.15 |
[자바 웹 개발 워크북] 4.4 - 스프링 Web MVC 구현하기(2) (0) | 2023.02.14 |