10-3. Thymeleaf

๋™๋™์ฃผยท2024๋…„ 6์›” 9์ผ
0

spring ๊ธฐ๋ง๊ณ ์‚ฌ

๋ชฉ๋ก ๋ณด๊ธฐ
7/11

๐Ÿฅ  template fragment (๊ณตํ†ต์˜์—ญ์ฒ˜๋ฆฌ, ์ฝ”๋“œ์žฌ์‚ฌ์šฉ)

  • ๋‹ค๋ฅธ template์— ์ •์˜๋œ ์ฝ”๋“œ์˜ ์ผ๋ถ€๋ถ„(fragment)์„ ๊ฐ€์ ธ์™€์„œ ํฌํ•จ ๊ฐ€๋Šฅ

1. ๊ณตํ†ต ์˜์—ญ ์ •์˜

<footer>๋ฅผ th:fragment๋ฅผ ์ด์šฉํ•ด ์กฐ๊ฐํ™”ํ•˜์˜€๊ณ  ์ด๋ฆ„์€ footerFragment๋กœ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

  • [footer.html]
<html xmlns:th="http://www.thymeleaf.org">
<body>

<footer th:fragment="footerFragment">
  <p> COPYRIGHT@ dhk22</p>
</footer>

</body>
</html>

2. fragment expression

  • ~{template-name} : ์ง€์ •๋œ template์˜ ์ฝ”๋“œ ์ „์ฒด๋ฅผ ์‚ฝ์ž…
  • ~{template-name::selector} : selector๋Š” ํŠน์ • fragment์˜ ์ด๋ฆ„ ๋˜๋Š” id
    ์†์„ฑ ๊ฐ’์„ ์ง€์ •
  • ~{::selector} / ~{this::selector} : ๊ฐ™์€ template ์•ˆ์— ์žˆ๋Š” fragment ์ด์šฉ

    ::๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์•ž์—๋Š” ์กฐ๊ฐ์ด ์žˆ๋Š” ๊ฒฝ๋กœ๋ฅผ, ๋’ค์—๋Š” ์กฐ๊ฐ์˜ ์ด๋ฆ„์„ ์„ค์ •ํ•ด์ค๋‹ˆ๋‹ค.


๐Ÿ’ฅ ID๋ฅผ ์ด์šฉํ•œ fragment ์‚ฝ์ž…


3. fragment ์‚ฌ์šฉ ๋ฐฉ๋ฒ• 3๊ฐ€์ง€

1) th:insert
insert๋Š” ํƒœ๊ทธ ๋‚ด๋กœ ์กฐ๊ฐ์„ ์‚ฝ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
์—ฌ๊ธฐ์„œ ํƒœ๊ทธ ๋‚ด๋ž€ <div> ์•ˆ์ชฝ์— <footer>๊ฐ€ ์œ„์น˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด ์กฐ๊ฐํ™”ํ•œ footer๊ฐ€ div ๋‚ด๋กœ ์‚ฝ์ž…๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2) th:replace
replace๋Š” ํ•ด๋‹น ํƒœ๊ทธ๋ฅผ ์™„์ „ํžˆ ๋Œ€์ฒดํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด ์กฐ๊ฐํ™”ํ•œ footer๊ฐ€ div๋ฅผ ๋Œ€์ฒดํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3) th:include
include๋Š” ๋‚ด์šฉ๋งŒ ์‚ฝ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด <footer>๊ฐ€ ์ƒ๋žต๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค.

4. Parameterizable fragment (ํŒŒ๋ผ๋ฏธํ„ฐ)

Fragment๋ฅผ ์ด์šฉํ•  ๋•Œ ํ•จ์ˆ˜์™€ ์œ ์‚ฌํ•˜๊ฒŒ parameter ๊ฐ’ ์ „๋‹ฌ ๊ฐ€๋Šฅ

<!-- /WEB-INF/templates/footer.html -->
<div th:fragment="frag(onevar, twovar)">
    <p th:text="${onevar} + ' - ' + ${twovar}">...</p>
</div>
  • th:fragment="frag(onevar, twovar)": frag๋ผ๋Š” ์ด๋ฆ„์˜ ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ์ •์˜ํ•˜๊ณ  onevar์™€ twovar๋ผ๋Š” ๋‘ ๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ›์Œ
<div th:insert="footer::frag(${value1}, ${value2})">...</div>
  • 'footer.html' ํŒŒ์ผ์˜ 'frag'๋ฅผ ํ˜ธ์ถœํ•˜๋Š” fragment ์‚ฝ์ž… ์˜ˆ์‹œ

5. flexible layouts

parameter๋ฅผ ๊ฐ–๋Š” fragment๋ฅผ ์ด์šฉํ•ด์„œ template layout ์ •์˜

  • title๊ณผ link๊ฐ€ ์•„๋ž˜ template์—์„œ ๋„˜๊ฒจ์ฃผ๋Š”๋Œ€๋กœ ๋ฐ”๋€Œ๊ฒŒ ๋˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ๊ณตํ†ต ์ฝ”๋“œ๋กœ ์‚ฌ์šฉ

6. th:remove

thymeleaf template engine์—์„œ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๊ณ  ์ œ๊ฑฐํ•  ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ํ‘œ์‹œ

 <tr class="odd" th:remove="all">
 <td>Blue Lettuce</td>
 <td>9.55</td>
 <td>no</td>
 </tr>
 <tr th:remove="all">
 <td>Mild Cinnamon</td>
 <td>1.99</td>
 <td>yes</td>
 </tr>
  • template ์ฒ˜๋ฆฌ ์‹œ ์‚ญ์ œ๋จ

7. Command ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•œ form ์ž…์ถœ๋ ฅ ์ฒ˜๋ฆฌ

<!--login/loginForm.html -->
 	<form action="#" th:action="@{login}" th:object="${loginCommand}"method="post">
 		<p>
		 <label for="email" th:text="#{email}">email</label>:<br>
		 <input type="text" th:field="*{email}" />
 	</p>        
     	<!-- <input type="text" id="email"name="email"th:value="*{email}"/> ๊ณผ๋™์ผ -->
	<p>
 		<label for="password" th:text="#{password}">password</label>:<br>
		<input type="password" th:field="*{password}" />
	</p>
	<p>
		<input type="checkbox" th:field="*{rememberEmail}" value="true"/> 
	</p>
 		<input type="submit"value="๋กœ๊ทธ์ธ" th:value="#{login.btn}">
 </form>
  • <form>์— th:object ์†์„ฑ์„ ์ด์šฉํ•ด์„œ command ๊ฐ์ฒด ์ง€์ •
    • ๋ณ€์ˆ˜ ์‹(${...})์„ ํ†ตํ•ด view์— ์ „๋‹ฌ๋œ ๋ชจ๋ธ ๊ฐ์ฒด ์ƒ์„ฑ
  • checkbox, radio button, dropdown list์— ์ ์šฉ ๊ฐ€๋Šฅ!

8. ๊ฒ€์ฆ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ (#fields)

  • errors(โ€˜field-nameโ€™), errors(โ€˜*โ€™): field error message ๋ชฉ๋ก ์ œ๊ณต
  • globalErrors(): global error message ๋ชฉ๋ก ์ œ๊ณต
  • hasErrors(โ€˜property-nameโ€™), hasErrors(โ€˜*โ€™), hasGlobalErrors(): field error ๋˜๋Š” global error์˜ ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ

๐Ÿฅฐ ์ถœ์ฒ˜: https://velog.io/@dhk22/Thymeleaf-Fragment-%EA%B3%B5%ED%86%B5%EC%98%81%EC%97%AD%EC%B2%98%EB%A6%AC

0๊ฐœ์˜ ๋Œ“๊ธ€