๋ฐ์ํ
์ธํฐ๋ท ๊ฐ์๋ฅผ ์๊ฐํ๋ค๊ฐ Thymeleaf์ Decoupled Logic ์ ๊ถ๊ธํ์ฌ ์์๋ณด๊ธฐ ์ํด์ ์์ฑ์ ํ๋ ค๊ณ ํ๋ค.
Decoupled logic์ด ๋ฌด์์ผ๊น?
- decoupled (๋ถ๋ฆฌ๋) logic์ thymeleaf์ ๊ธฐ๋ฅ ์ค ํ๋์ด๋ค.
- HTML์ XML ํ
ํ๋ฆฟ์ ๋งํฌ์
๊ณผ ๋ก์ง์ด ๋ค์ด๊ฐ ๋ถ๋ถ์ ๋ถ๋ฆฌ์ํค๋ ๊ธฐ๋ฅ
- ๋ฐ๋ผ์ ๋์์ด๋์ ํ์ ์ด ์ฌ์์ง
- ์ฃผ์ ์์ด๋์ด๋ ํ ํ๋ฆฟ ๋ก์ง์ด ๋ณ๋์ ๋ก์ง ํ์ผ(ํ์ผ์ผ ํ์๋ ์์ผ๋ฏ๋ก ๋ ์ ํํ๊ฒ๋ ๋ก์ง resource์ ํด๋น)์ ์ ์
- ๊ธฐ๋ณธ์ ์ผ๋ก ์ด ๋ก์ง ๋ฆฌ์์ค๋ ํ ํ๋ฆฟ ํ์ผ๊ณผ ๊ฐ์ ์์น(์: ํด๋)์ ์๋ ์ถ๊ฐ ํ์ผ๋ก, ์ด๋ฆ์ ๊ฐ์ง๋ง ํ์ฅ์๊ฐ .th.xml์ธ ํ์ผ
/templates
+->/home.html
+->/home.th.xml
์์
- ์๋ฅผ ๋ค์ด home.html ํ์ผ์ ์์ ํ ๋ก์ง์ด ์๊ธฐ ๋๋ฌธ์ ํ๋จ์ ์ฝ๋์ฒ๋ผ ๋ณด์ผ ์ ์๋ค.
<!DOCTYPE html>
<html>
<body>
<table id="usersTable">
<tr>
<td class="username">Jeremy Grapefruit</td>
<td class="usertype">Normal User</td>
</tr>
<tr>
<td class="username">Alice Watermelon</td>
<td class="usertype">Administrator</td>
</tr>
</table>
</body>
</html>
- Thymeleaf ์ฝ๋๊ฐ ์ ํ ์์ผ๋ฉฐ, ์ด ํ ํ๋ฆฟ ํ์ผ์ Thymeleaf & ํ ํ๋ฆฟ์ ๋ํ ์ง์์ด ์๋ ๋์์ด๋๊ฐ ์์ฑ, ํธ์ง ๋ฑ ์ดํด ํ ์ ์๋ ํ ํ๋ฆฟ ํ์ผ์ด๋ค.
<?xml version="1.0"?>
<thlogic>
<attr sel="#usersTable" th:remove="all-but-first">
<attr sel="/tr[0]" th:each="user : ${users}">
<attr sel="td.username" th:text="${user.name}" />
<attr sel="td.usertype" th:text="#{|user.type.${user.type}|}" />
</attr>
</attr>
</thlogic>
- ์ฌ๊ธฐ์๋ ๋ ผ๋ฆฌ ๋ธ๋ก ์์ ๋ง์ <attr> ํ๊ทธ๊ฐ ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
- ์ด๋ฌํ <attr> ํ๊ทธ๋ Thymeleaf ๋งํฌ์ ์ ํ๊ธฐ(์ค์ ๋ก๋ AttoParser ๋งํฌ์ ์ ํ๊ธฐ)๊ฐ ํฌํจ๋ sel ์์ฑ์ ํตํด ์ ํ๋ ์๋ณธ ํ ํ๋ฆฟ์ ๋ ธ๋์ ์์ฑ ์ฃผ์ ์ ์ํํจ
- <attr> ํ๊ทธ๋ ์ค์ฒฉ๋์ด ์ ํ๊ธฐ๊ฐ ์ถ๊ฐ๋ ์ ์๋ค.
- ์๋ฅผ ๋ค์ด ์์ sel="/tr[0]"์ sel="#usersTable/tr[0]"๋ก ์ฒ๋ฆฌ๋๋ค.
- ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ์ ์ด๋ฆ <td>์ ๋ํ ์ ํ๊ธฐ๋ sel="#usersTable/tr[0]//td.username"์ผ๋ก ์ฒ๋ฆฌ๋๋ค.
Spring์์ thymeleaf์ ์ฌ์ฉํ๊ธฐ ์ํ ์ฌ์ ์์
- ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ ์ application.yaml์ ์ต์ ์ ์ถ๊ฐํด์ค์ผ ํ๋ค.
thymeleaf3:
decoupled-locig: true
- build.gradle์์ ๋ํ๋์์ spring configuration prosser๋ฅผ ์ถ๊ฐํด์ผ ํ๋ค.
- thymeleaf3์ IDE๋ฅผ ๋ ๋งค๋๋ฝ๊ฒ ์ฐ๋ํ๋ ๋ฐฉ๋ฒ
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
Spring์์ thymeleaf์ ์ฌ์ฉํ๊ธฐ ์ํ ๊ณตํต Config ํ์ผ
- ์คํ๋ง ๋ถํธ ํ๋กํผํฐ์์ ์ค์ ํ ์ ์๋๋ก ์ ๊ณต๋์ง ์์๊ธฐ ๋๋ฌธ์ ์ธํ ์ ๋ฐ๋ก ์งํ
- ThymeleafConfig ๋ผ๋ Config ํด๋์ค๋ฅผ ์์ฑ ํด์ค์ผ ํ๋ค.
@Configuration
public class ThymeleafConfig {
@Bean
public SpringResourceTemplateResolver thymeleafTemplateResolver(
SpringResourceTemplateResolver defaultTemplateResolver,
Thymeleaf3Properties thymeleaf3Properties
) {
defaultTemplateResolver.setUseDecoupledLogic(thymeleaf3Properties.isDecoupledLogic());
return defaultTemplateResolver;
}
@RequiredArgsConstructor
@Getter
@ConstructorBinding
@ConfigurationProperties("spring.thymeleaf3")
public static class Thymeleaf3Properties {
/**
* Use Thymeleaf 3 Decoupled Logic
*/
private final boolean decoupledLogic;
}
}
- ์ config ํ์ผ๊น์ง ์์ฑ ํ๊ฒ ๋๋ฉด ๊ธฐ์กด์ HTML์์ decoupled logic์ผ๋ก ํ์ฌ ๋ถ๋ฆฌํด๋ด์ผํ๋ค.
- resource > templates > articles์์ index.html ํ์ผ์ ๋์ผํ ์ด๋ฆ์ผ๋ก index.th.xml ํ์ผ์ ์์ฑ
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thyemleaf.org">
<head>
<title>๊ฒ์ํ ํ์ด์ง</title>
</head>
<body>
<header id="header"></header>
<main class="container">
</main>
<footer id="footer"></footer>
</body>
</html>
- ์์ index.html์ header ๋ฐ footer๋ก ๋ก์ง์ ๋ถ๋ฆฌํด์ค์ผ ํ๋ค.
<?xml version="1.0"?>
<thlogic>
<attr sel="#header" th:replace="header :: header"/>
<attr sel="#footer" th:replace="footer :: footer"/>
</thlogic>
- ๊ทธ๋ ๊ฒ ๋์ผํ name์ ๊ฐ์ง index.th.xml ํ์ผ์ html ํ์ผ์์ ๋ถ๋ฆฌ ๋ header์ footer๋ฅผ attr ๊ตฌ๋ฌธ์ผ๋ก ํด์ ๊ฐ์ ๋ฃ์ด์ค๋ค.
- ๋ถ๋ฆฌ๋ header ๊ตฌ๋ฌธ์ ํด๋ฆญ ํ๊ฒ ๋๋ฉด, ๊ณตํต์ผ๋ก ์ฌ์ฉ ํ ์ ์๋๋ก ์์ฑํ header.html ํ์ผ๋ก ์ด๋ํ๊ฒ ๋๋ค.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<header class="p-3 bg-dark text-white">
<div class="container">
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
<li><a id="home" href="#" class="nav-link px-2 text-secondary">Home</a></li>
</ul>
<div class="text-end">
<a role="button" class="btn btn-outline-light me-2">Login</a>
<a role="button" class="btn btn-warning">Sign-up</a>
</div>
</div>
</div>
</header>
</body>
</html>
- ์์ ์ด๋ฏธ์ง ์ฒ๋ผ ์ฌ๋ฌ ๊ณณ์์ ์ฌ์ฉ ํ ์ ์๋๋ก ํด๋์ค ๊ด๋ฆฌ๊ฐ ๋๋ค.
https://github.com/94-c/project-board/commit/1d3bcb50dcecea63f2220fcbf004fdf66110f22e
๋ฐ์ํ
'๐ฟSpring > Spring Framework' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring Framework] Spring Boot 2.* vs 3.* (0) | 2024.06.11 |
---|---|
[Spring Framework] Spring Boot์ ์์ ํ๋ก์ธ์ค (0) | 2024.05.13 |
[Spring Framework - Thymeleaf] Thymeleaf ๋? (0) | 2024.01.18 |
[Spring Framework] Transction (1) | 2024.01.11 |
[Spring Framework] Filter ์ Interceptor (1) | 2024.01.11 |