Thymeleaf
View Template Engine
ํ์๋ฆฌํ๋ ์๋ต์ฉ์ผ๋ก ๋ง๋ค์ด์ง. ์ปจํธ๋กค๋ฌ๊ฐ ๋ณด๋ด์ค ๋ด์ฉ์ผ๋ก ํํํ๋ค.
Spring EL
Spring Expression Language
๋ฐํ์์ ๋ฉ์๋ ํธ์ถ ๋ฐ ๊ธฐ๋ณธ ๋ฌธ์์ด ํ ํ๋ฆฟ ๋ฑ์ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
1) ${...} ํํ์ - ๋ณ์ ํํ์
์ปจํธ๋กค๋ฌ์์ ์ ๋ฌ๋ฐ์ ๋ณ์์ ์ ๊ทผํ ์ ์์ผ๋ฉฐ th:์์ฑ๋ช ํน์ [[ ]]์์์ ์ฌ์ฉ๊ฐ๋ฅํ๋ค.
2) @{ ... } ํํ์ - URL ํํ์
์๋ฒ์ contextPath๋ฅผ ๋ฐ์ํ URI๋ก ๋ณ๊ฒฝ๋๋ค.
3) ๋ฌธ์ ํฉ์น๊ธฐ
ํฉ์น๊ณ ์ถ์ ๋ฌธ์์ด์ "|"๋ก ๊ฐ์ธ๊ฑฐ๋ +์ฐ์ฐ์๋ฅผ ์ด์ฉํด ๋ฌธ์๋ฅผ ํฉ์น ์ ์๋ค.
<div th:text="|I am ${info.name} !! |"></div>
<div th:text="'I am '+ ${info.name} + ' !! '"></div>
4) ๋น๊ต ์ฐ์ฐ์
์ดํญ ์ฐ์ฐ์
<div th:text="${info.name != 'kim'}"></div>
์ผํญ์ฐ์ฐ์
<div th:text="${info.name == 'kim' ? 'ok' : 'no'}"></div>
<th:block th:if="${info.age > 18}"><hr><p>์
์ฅ ๊ฐ๋ฅ</p><hr></th:block>
if- else ๋ฌธ ์ธ ์ ์๋ค.
each
for ๋ฐ๋ณต๋ฌธ๊ณผ ๋น์ทํจ
<th:block th:each="data,status:${datas}">
<h1 th:text="|${status.count} ${data}|"></h1>
</th:block>
2๊ฐ ์ด์ ์ ์ ๋๋ block ํ๊ทธ๋ก ๋ฌถ๋ ๊ฒ ์ข๋ค.
data,status ์ด๋ ๊ฒ ์ ์ด์ฃผ๋ฉด row์ ๋ํ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ป์ ์ ์๋ค.
status ๊ฐ์ฒด์ ์์ฑ
index: 0๋ถํฐ ์์
count : 1๋ถํฐ ์์
size : ์ด ๊ฐ์
current : ํ์ฌ index์ ๋ณ์
even / odd : ์ง์ / ํ์ ์ฌ๋ถ
first / last : ์ฒ์ / ๋ง์ง๋ง ์ฌ๋ถ
๋งํฌ๋ ๋์ URL : th : href="@{}"
<a th:href="@{/insert(pageno=${pageno})}">
์ด ์ฝ๋๋
<a href="/insert?pageno=123">
์ด ์ฝ๋์ ๊ฐ๋ค.
th:with="${}"
๋ณ์ ํํ์ ๊ฐ์ ์ฌ์ ์ํ๋ ์์ฑ. th:with๋ฅผ ์ด์ฉํ์ฌ ์๋ก์ด ๋ณ์ ๊ฐ์ ์์ฑํ ์ ์๋ค.
<div th:with=”userId=${number}” th:text=”${usesrId}”>
ํํ์
๋ณ์ ํํ์ : ${ ... }
์ ํ ๋ณ์ ํํ์ : *{ ... }
๋ค๊ตญ์ ์ธ์ด ๊ด๋ จ ๋ฉ์ธ์ง ํํ์ : #{ ... }
๋งํฌ URL ํํ์ : @{ ... }
์กฐ๊ฐ ํํ์ : ~{ ... }
๋น๊ต์ ๋๋ฑ
๋น๊ต: >,<,>=,<= (gt, lt, ge, le)
๋๋ฑ ์ฐ์ฐ : ==, != (eq, ne)
์กฐ๊ฑด ์ฐ์ฐ
If-then : (if) ? (then)
If-then-else : (if) ? (then) : (else)
Default : (value) ?: (defaultvalue) (์์ผ๋ฉด ๊ฑ๋ฅผ ์ถ๋ ฅํ๊ณ ์๋ค๋ฉด defaultvalue๋ก ์ง์ ํ ๊ฐ์ ์ถ๋ ฅํ๋ค.)
ํน๋ณํ ํ ํฐ
No-Operation: _ (์๋ฌด๊ฒ๋ ํ์ง ๋ง์๋ผ)
ํ์๋ฆฌํ ๋ด์ฅ ๊ฐ์ฒด
#dates: java.util.Date ์์ ์ง์
#temporals : ์๋ฐ8 ๋ ์ง ์์ ์ง์ (๋ ์ง๋ ์ฃผ๋ก temporals๋ฅผ ์ฌ์ฉ)
#numbers: ์ซ์ ์์ ์ง์
@Data
@RequiredArgsConstructor ์ด๋ฉด @NonNull์ด ์์ด์ผ ์ด๊ธฐํ ํด์ค๋ค. ๋ฐ๋ฉด @AllArgsConstructor๊ฐ ์์ผ๋ฉด ๋ชจ๋ ํ๋์ ๊ฐ์ ์ด๊ธฐํํ๋ ์์ฑ์๋ฅผ ๊ตฌํํ๋๋ฐ, @Data์๋ @RequiredArgsConstructor๊ฐ ์์ผ๋ฏ๋ก ํ๋์ @NonNull์ ์ผ์ผ์ด ๋ถ์ฌ์ค์ผ ํ๋ค.
User userA = new User("์ฌ์ฉ์ A", 10);
List<User> list = new ArrayList<>();
list.add(userA);
final HashMap<String, User> map = new HashMap<>();
map.put("userA", userA);
model.addAttribute("user", userA);
model.addAttribute("users", list);
model.addAttribute("userMap", map);
์ด๋ฐ ์์ผ๋ก userA๋ฅผ ๋ง๋ค์ด์ฃผ๊ณ , add๋ก list์ ๋ฃ์ด์ค ์๋ ์๊ณ , put์ผ๋ก map์ ๋ฃ์ด์ค ์๋ ์๋ค.
<h3>์ฒซ๋ฒ์งธ ๋ฐฉ๋ฒ</h3>
<ul>
<li>${user.userName} = <span th:text="${user.userName}"></span></li>
<li>${user['userName']} = <span th:text="${user['userName']}"></span></li>
<li>${user.getuserName()} = <span th:text="${user.getUserName()}"></span></li>
</ul>
<h3>๋๋ฒ์งธ ๋ฐฉ๋ฒ</h3>
<ul>
<li>${users[0].userName} span> = <span th:text="${users[1].userName}"></span></li>
<li>${users[0]['userName']} = <span th:text="${users[1]['userName']}"></span></li>
<li>${users[0].getuserName()} = <span th:text="${users[1].getUserName()}"></span></li>
</ul>
<h3>์ธ๋ฒ์งธ ๋ฐฉ๋ฒ</h3>
<ul>
<li>${userMap['userA'].userName} = <span th:text="${userMap['userA'].userName}"></span></li>
<li>${userMap['userA']['userName']} = <span th:text="${userMap['userA'] ['userName']}"></span></li>
<li>${userMap['userA'].getuserName()} = <span th:text="${userMap['userA'].getUserName()}"></span></li>
</ul>
๊ทธ๋ฌ๋ฉด html์์ ์ด๋ฐ์์ผ๋ก ์ถ๋ ฅํ ์ ์๋ค. user์ userA๋ฅผ ๋ฃ์ด์คฌ์ ๋๋ ์ฒซ๋ฒ์งธ, users์ list๋ฅผ ๋ฃ์ด์ฃผ์์๋๋ ๋๋ฒ์งธ, userMap์ map์ ๋ฃ์ด์ฃผ์์ ๋๋ ์ธ๋ฒ์งธ ๋ฐฉ๋ฒ์ ์จ์ ์ถ๋ ฅํด์ค๋ค.
<ul th:with="first=${users[0]}">
<li>์ฒซ ๋ฒ์งธ ์ฌ๋์ ์ด๋ฆ์ '<span th:text="${first.userName}"></span>'</li>
</ul>
์ด๋ฐ์์ผ๋ก with๋ฅผ ์ฌ์ฉํด์ first์ user[0]์ ๋ฃ์ด์ค ์๋ ์๋ค.
if(session.getAttribute("count") == null)
session.setAttribute("count", new int[1]);
int su[] = (int[])session.getAttribute("count");
su[0]++;
์กฐํ์๊ฐ์ ๊ฒ์ ์ธ๋ ์ฝ๋
param, session, application์ #์ ์ฐ์ง ์๊ณ ์ด๋ค.
์๋ ๊ฒฝ์ฐ ๋๋ถ๋ถ ๋ด์ฅ๊ฐ์ฒด๋ #์ ๋ถ์ด๊ณ ์ด๋ค.
<li>spring bean = <span th:text="${@my.hello('Spring Boot!')}"></span></li>
์ธ์๋๋ bean์ค์์ my๋ผ๋ ์ด๋ฆ์ผ๋ก ๋ bean๊ฐ์ฒด๋ฅผ ์ง์ ์ฌ์ฉํ๊ณ ์ถ์๋ ์ด๋ค.. hello๋ฅผ ํธ์ถํด ๋ฆฌํด๋ ๊ฒฐ๊ณผ๋ฅผ ํํํ๊ณ ์๋ค.
@Component("my")
class HelloBean {
public String hello(String data) {
return "์๋
? " + data;
}
}
javaํ์ผ์ ์ด๋ ๊ฒ ์จ๋์ ๊ฒ์ ์ง์ ์ฌ์ฉํ๋ค.
[[${#temporals.format(startTime,'yyyy-MM-dd HH:mm:ss')}]]<br>
์ด๋ฐ์์ผ๋ก format์ ์ง์ ํด์ ์ถ๋ ฅํ ์ ์๋ค.
<li>Request Parameter = <span th:text="${param.Data}"></span></li>
์ฟผ๋ฆฌ๋ฌธ์์ด์์ param์ผ๋ก ๋ฐ์์์ Data๋ฅผ ์ถ๋ ฅํ๋ค. ์ฃผ์์ฐฝ์
http://localhost:8088/step2/basicobjects?Data=DUKE ์ด๋ฐ์์ผ๋ก ์น๋ฉด
์ด๋ ๊ฒ Data๋ฅผ ๋ฐ์์ ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
<li>${#temporals.month(startTime)} = <span th:text="${#temporals.month(startTime)}"></span></li>
์ด๋ฐ์์ผ๋ก #temporals๋ฅผ ์ด์ฉํด์ ๊ตฌํํ ์ ์๋ค.
[[${#dates.createNow()}]]
[[${#dates.createToday()}]]
createNow๋ ์ง๊ธ์ด๊ณ createToday๋ ์ค๋์ ๋ํ๋ธ๊ฒ
์ด๋ฐ์์ผ๋ก ๋ํ๋๋ค.
[[${#strings.isEmpty(param.name)}]]
ํ๋ผ๋ฏธํฐ์ name์ด ๋น์ด์๋์ง๋ฅผ ํ์ธํ๋ ์ฝ๋
๋น์ด์์ผ๋ฉด true๋ฅผ ์ค๋ค.
[[${#strings.toLowerCase(tech)}]]
์๋ฌธ์๋ก ๋ฐ๊ฟ์ค๋ค.
[[${#strings.trim(tech)}]]
์์ ๊ณต๋ฐฑ์ ์ง์์ค๋ค.
<li>${#numbers.formatDecimal(num, 3, 'COMMA', 2, 'POINT')} = <span th:text="${#numbers.formatDecimal(num, 3, 'COMMA', 2, 'POINT')}"></span></li>
์ด๋ฐ์์ผ๋ก #numbers๋ฅผ ์ฌ์ฉํด์ ์ถ๋ ฅํ๋ฉด
์ด๋ฐ์์ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
[[${param.containsKey('foo')}]]
foo๋ผ๋ ์ด๋ฆ์ ์ฟผ๋ฆฌ๊ฐ ์๋๋. ์์ผ๋ฉด true ์์ผ๋ฉด false
[[${session.sessionData} ]]
session์ ์ ์ฅ๋ ๋ฐ์ดํฐ์ค์์ sessionData๋ผ๋ ์ด๋ฆ์ ๋ฐ์ดํฐ ์ถ๋ ฅ
[[${session.keySet()} ]]
keySet()์ ์ถ๋ ฅํด์ค๋ค.
์ด๋ฐ์์ผ๋ก ์ถ๋ ฅ๋๋ค.
@RequestMapping(value="/character/detail/{name}/{number}")
public String getAllBoards(@PathVariable("number") int num, @PathVariable String name, Model model){
name์ด๋ผ๊ณ ๋ณด๊ด๋ ๊ฐ์ฒด๋ฅผ ์ฌ๊ธฐ๋ค ์ฌ์ฉํ๊ณ number๋ผ๊ณ ๋ณด๊ด๋ ๊ฐ์ฒด๋ฅผ ์ฌ๊ธฐ๋ค๊ฐ ์ค๋ค.
@PathVariable ๊ฐ๊ฐ์ ์์น์ ์์ฑ๋์ด์๋ ๊ฒฐ๊ณผ์ ๋ฐ๋ผ ์ ๋ฌ๋๊ฒ ๋๋ค. ์ด ๋งค๊ฐ๋ณ์๋ค์ ๊ฐ์ path์ ๋ณด์ ์ผ๋ถ๋ถ์ ์ ๋ฌํ๊ฒ ๋๋ค.
๋ญ๊ฐ ์ค๋ name์ผ๋ก ์ ๋ฌ๋ฐ๊ณ number๋ก ์ ๋ฌ๋ฐ๋๋ค๋ ์๋ฏธ.
@PathVariable("number") int num ๋ number๋ฅผ ์ถ์ถํด์ num์ ๋ฃ์ด์ค๋ค๋ ๋ป.
@PathVariable String name ๋ path์ ๋ณด์ธ name์ ์ถ์ถํด์ ๋งค๊ฐ๋ณ์ name์ ๋ฃ์ด์ค๋ค๋ ๋ป. ์ด๋ฆ ๊ฐ์ผ๋ฉด ("")๋ฅผ ๊ตณ์ด ๋ฃ์ด์ฃผ์ง ์๋๋ค.
<li><a th:href="@{/hello(param1=${param1}, param2=${param2})}">hello query param</a></li>
<li><a th:href="@{/hello/{param1}/{param2}(param1=${param1}, param2=${param2})}">path variable</a></li>
<li><a th:href="@{/hello/{param1}(param1=${param1}, param2=${param2})}">path variable + query parameter</a></li>
์ฐจ๋ก๋๋ก ์ด๋ฐ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค. (param1์๋ news, param2์๋ ๋จํ์ ๋ฃ์ด์ฃผ์๋ค.)
path์ ๋ค์ด๊ฐ์ง ์์ผ๋ฉด ์ฟผ๋ฆฌ๋ฌธ์์ด์ด ์จ๋ค.
<li>${nullData}?: _ = <span th:text="${nullData}?: _">๋ฐ์ดํฐ๊ฐ์์ต๋๋ค.</span></li>
nullData๊ฐ ์๊ฑฐ๋ null์ด๋ฉด ์๋ฌด๊ฒ๋ ์ํํ์ง ๋ง์๋ผ..
<input type="checkbox" name="active" th:checked="true" />
์ฒ์๋ถํฐ ์ฒดํฌ๋ ์ํ๋ก ๋ณด์ฌ์ง๊ฒ ํ๊ณ ์ถ๋ค -> th:checked="true"๋ก ๋์ผ๋ฉด ๋๋ค.
<input type="checkbox" name="active" th:checked="false" />
์ด๋ ๊ฒ ํ๋ฉด checked๊ฐ false์ด๋ค.
์ด๋ฐ์์ผ๋ก..
checked =""ํ๊ณ ์ด ์์ ์ด๋ค ๊ฐ์ด ๋ค์ด๊ฐ๋๋ผ๋ checkedํ ์ํ๋ก ๊ฐ์ฃผ๋จ. ์ฌ์ง์ด ์์ false๊ฐ ๋ค์ด๊ฐ๋..
<input type="checkbox" name="active" checked="false" />
<input type="text" class="text" th:attrappend="class=' large'" />
attrappend๋ ๋ค์ ์์ฑ์ ์ถ๊ฐํด๋ผ.. ๊ฒฐ๊ณผ ์ ์ผ๋ก class๊ฐ text large๊ฐ ๋๋ค.
<input type="text" class="text" th:attrprepend="class='large '" />
attrprepend๋ ์์ ์์ฑ์ ์ถ๊ฐํด๋ผ.. ๊ฒฐ๊ณผ์ ์ผ๋ก class๊ฐ large text๊ฐ ๋๋ค.
private void addUsers(Model model) {
List<User> list = new ArrayList<>();
list.add(new User("๋๋ฆฌ", 10));
list.add(new User("๋์น", 20));
list.add(new User("๋์ฐ๋", 30));
model.addAttribute("users", list);
}
list์ ๊ฐ์ฒด ๋ฃ์ด์ฃผ๊ณ model ๊ฐ์ฒด์ users๋ผ๋ ์ด๋ฆ์ผ๋ก list ๋ฃ์ด์ค๋ค.
ํ์๋ฆฌํ ์ฃผ์:
<!--/* */-->
ํน์
<!--/*-->
...
<!--*/-->
์ด ๋ฐฉ์์ผ๋ก ํ๋ฉด ๋ธ๋ผ์ฐ์ ์ ์ ์ก๋ ์๋๊ณ ์๋ฒ, ํด๋ผ์ด์ธํธ์ ์ ์ก๋ ์๋จ.
<-- --> ์ด๋ ๊ฒ ํ๋ฉด ๋ธ๋ผ์ฐ์ ์ ์ ์ก์ ๋๋ ์ค์ ์ํํ ๊ฒฐ๊ณผ๊ฐ ์ค๋ ๊ฒ์ ์๋. ์๋ฒ์์๋ ์ ์ธ๋๋ค. ํด๋ผ์ด์ธํธ์๋ ์ ์ก๋จ.
<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>
์ด๋ฐ ์์ผ๋ก ๋ฐ๋ณตํ ์ ์๋ค. blockํ๊ทธ๋ ํด๋ผ์ด์ธํธ๋ก ์ ์ก๋์ง ์์.
<script th:inline="javascript">
์ด ์์์ ์ํ๋๋ ๊ฑด '์๋ฐ์คํฌ๋ฆฝํธ ๊ตฌ๋ฌธ์ ๋ง๊ฒ ์ฒ๋ฆฌํด์ค.' ํ๋ ๋ป
์ด๋ ๊ฒ ํ๋ฉด ์๋ฌ๋๋ค.. ""์ด๋ฐ ์ธ์ฉ๋ถํธ ์์ด์ผ ํ๋๋ฐ ์์.
'๐ผ Full-Stack Study โก (feat. KOSA)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Spring & Ajax & Mybatis (2) | 2023.10.11 |
---|---|
Spring & Thymeleaf (2) | 2023.10.10 |
Spring Boot (1) | 2023.10.06 |
Spring Boot & Thymeleaf (1) | 2023.10.05 |
Spring (0) | 2023.10.04 |