๋ฐ์ํ
์ด ํฌ์คํธ๋ ๋ด์ฉ์ด ๊น๋๋ค.
๋ฐ์๊ฑฐ๋ ๋ง๋ณด๊ธฐ๋ง ๋ณด์ค ๋ถ๋ค์ ์๋ ํฌ์คํธ ์ถ์ฒ๋๋ฆฝ๋๋ค.
2025.03.03 - [โจ UI/๐ค View Templates] - [Thymeleaf]ํ์๋ฆฌํ ์ฌ์ฉ๋ฒ ๊ฐ๋จ์ ๋ฆฌ
- ์ ์ธ
- <html xmlns:th="http://www.thymeleaf.org"> ๋ง HTMLํ์ผ์ ์ ์ด์ฃผ๋ฉด ๋ฐ๋ก ์ฌ์ฉ๊ฐ๋ฅํ๋ค.
- <html xmlns:th="http://www.thymeleaf.org"> ๋ง HTMLํ์ผ์ ์ ์ด์ฃผ๋ฉด ๋ฐ๋ก ์ฌ์ฉ๊ฐ๋ฅํ๋ค.
- text
- code
- ๊ฒฐ๊ณผ
- <span th:text="${data}">
โ ํ๊ทธ ์์ฑ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์นํํ ๋ ์ฌ์ฉ. - [[${data}]]
โ ์ปจํ ์ธ ์์์ ์ง์ ์ถ๋ ฅ. - ํ์๋ฆฌํ๋ ๋ค์ ๋ ๊ธฐ๋ฅ ์ ๊ณตํ๋ค.
- th:text โ th:text
- [[...]] โ [(...)]
- th:text โ th:text
- code
- Unescape
- code
java๋ก์ง thymeleaf - ๊ฒฐ๊ณผ
- escape๋ ์๋ฐ์์ html๋ก ๋์ด์ฌ ๋ ์์์ ํน์ ๊ธฐํธ<, / ๋ฑ์ ์ฒ๋ฆฌํด์ฃผ๋ ๊ฒ์ ๋งํ๋ค.
๋ฐ๋๋ก unscape๋ ๊ธฐํธ๋ฅผ ์ฒ๋ฆฌํ์ง ์๊ณ ๊ทธ๋๋ก ๋ด๋ณด๋ด๋ ๊ฒ์ ๋งํ๋ค.
๐ ์ต๋ํ ๊ธฐ๋ณธ์ธ escape๋ฅผ ์ฌ์ฉํ๋๋ก ํ์. - th:text โ th:utext
- [[...]] โ [(...)]
- code
- SpringEL ํํ์
- ์คํ๋ง์ด ๋ด๋ถ์์ ๊ฐ์ฒด๋ฅผ ์ ๊ทผํ๋ ๋ฌธ๋ฒ์ผ๋ก ํ์๋ฆฌํ๋ ์ด๋ฅผ ๊ทธ๋๋ก ์ ์ฉํ๋ค.
- code
java thymeleaf - ๊ฒฐ๊ณผ
- Object
- user.username
- user['username']
- user.getUsername()
- List
- users[0].username
- users[0]['username']
- users[0].getUsername()
- Map
- userMap['userA'].username
- userMap['userA']['username']
- userMap['userA'].getUsername()
- ์ง์ญ๋ณ์ <div th:with="first=${users[0]}">
- ์์
div ํ๊ทธ์ ์ง์ญ๋ณ์๋ฅผ ์ ์ธํ๊ธฐ ๋๋ฌธ์ div ๋ฒ์ ์์์๋ง ์ฌ์ฉ๊ฐ๋ฅํ๋ค.
- ์์
- ์คํ๋ง์ด ๋ด๋ถ์์ ๊ฐ์ฒด๋ฅผ ์ ๊ทผํ๋ ๋ฌธ๋ฒ์ผ๋ก ํ์๋ฆฌํ๋ ์ด๋ฅผ ๊ทธ๋๋ก ์ ์ฉํ๋ค.
- ์ ํธ๋ฆฌํฐ ๊ฐ์ฒด์ ๋ ์ง
- tutorial
๐ ์ ํธ๋ฆฌํฐ๋ ์ด๋ฐ ๊ฒ ์๋ค๋ ์ ๋๋ง ์๊ณ , ํ์ํ ๋ ์ฐพ์์ ์ฌ์ฉํ๋ฉด ๋๋ค. - ๋ ์ง ์์ ์ฝ๋
java thymeleaf - ๊ฒฐ๊ณผ
- ๊ทธ ์ธ ์ข
๋ฅ
- #message : ๋ฉ์์ง, ๊ตญ์ ํ ์ฒ๋ฆฌ
- #uris : URI ์ด์ค์ผ์ดํ ์ง์
- #dates : java.util.Date ์์ ์ง์
- #calendars : java.util.Calendar ์์ ์ง์
- #temporals : ์๋ฐ8 ๋ ์ง ์์ ์ง์
- #numbers : ์ซ์ ์์ ์ง์
- #strings : ๋ฌธ์ ๊ด๋ จ ํธ์ ๊ธฐ๋ฅ
- #objects : ๊ฐ์ฒด ๊ด๋ จ ๊ธฐ๋ฅ ์ ๊ณต
- #bools : boolean ๊ด๋ จ ๊ธฐ๋ฅ ์ ๊ณต
- #arrays : ๋ฐฐ์ด ๊ด๋ จ ๊ธฐ๋ฅ ์ ๊ณต
- #lists , #sets , #maps : ์ปฌ๋ ์ ๊ด๋ จ ๊ธฐ๋ฅ ์ ๊ณต
- #ids : ์์ด๋ ์ฒ๋ฆฌ ๊ด๋ จ ๊ธฐ๋ฅ ์ ๊ณต
- tutorial
- ํธ์ ๊ฐ์ฒด
- ํ์๋ฆฌํ์์ ์์ฃผ ์ฌ์ฉ๋๋ ๊ฒ๋ค์ ์ฌ์ฉํ ์ ์๊ฒ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํด์ฃผ๋ ๊ฒ์ด๋ค.
- code
๐ ํ์๋ฆฌํ๊ฐ ์ ๋ฐ์ดํธ๊ฐ ๋๋ฉด์ model์ ๋ด์ session, request ๋ฑ์ ๊ธฐ๋ณธ ๊ฐ์ฒด๋ก ์ง์ํ์ง ์๋๋ค. session์ ๋ฌด์ํด์ฃผ์ธ์ - ${param}
โ param์ด๋ ์ด๋ฆ์ผ๋ก ๋ฐ๋ก ์ฌ์ฉํ ์ ์๊ฒ ํด์ค๋ค. - ${@helloBean}
โ ํด๋น ํจ์์ ๋ด์ง ์์ ๊ฒ์ด์ด๋ ๋น ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด์ ํจ์๊น์ง ์ฌ์ฉ๊ฐ๋ฅํ๋ค.
- ํ์๋ฆฌํ์์ ์์ฃผ ์ฌ์ฉ๋๋ ๊ฒ๋ค์ ์ฌ์ฉํ ์ ์๊ฒ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํด์ฃผ๋ ๊ฒ์ด๋ค.
- URL ๋งํฌ @{๊ฒฝ๋ก}
- code
- ๊ฒฐ๊ณผ
์๋ ์ค๋ช ์ฐธ๊ณ - ๋จ์ URL
@{/hello} โ http://localhost:8080/hello - ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ
@{/hello(param1=${param1}, param2=${param2})} โ http://localhost:8080/hello?param1=data1¶m2=data2 - ๊ฒฝ๋ก ๋ณ์(path variable) ์ฌ์ฉํ๊ธฐ
@{/hello/{param1}(param1=${param1}, param2=${param2})}
โ http://localhost:8080/hello/data1/data2 - ๊ฒฝ๋ก ๋ณ์ + ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ ์ฌ์ฉํ๊ธฐ
@{/hello/{param1}(param1=${param1}, param2=${param2})}
โ http://localhost:8080/hello/data1?param2=data2 - ๋ฆฌํฐ๋ด Literal
- : ์์ค ์ฝ๋์ ๊ณ ์ ๋ ๊ฐ์ ๋งํ๋ค.
โ ํ์๋ฆฌํ th:text=๋ณ์ ๊ฐ ์์ผํ๋๋ฐ ๋ฌด์ธ๊ฐ๋ฅผ ์ ์ด๋ฃ๊ณ ์ถ์ ๋ ์ฌ์ฉํ ์ ์๋ค.
โป ํ์๋ฆฌํ์์ ๋ฌธ์ ๋ฆฌํฐ๋ด์ ํญ์ ์์ ๋ฐ์ดํ' ๋ก ๊ฐ์ธ์ผ ํ๋ค. - code
- ๊ฒฐ๊ณผ
- ๐ ๋ฆฌํฐ๋ด ๋์ฒด Literal substitutions
- <span th:text="|hello ${data}|">
- ์ด๊ฑธ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ ๊ฒ ๊ฐ๋ค. '๋ฅผ ์ฌ์ฉํ์ง ์์๋ | ๋ง ์ฌ์ฉํ๋ฉด ๋๋ฉฐ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ฝ๋ค.
- <span th:text="|hello ${data}|">
- : ์์ค ์ฝ๋์ ๊ณ ์ ๋ ๊ฐ์ ๋งํ๋ค.
- ์ฐ์ฐ
- ์๋ฐ์ ํฌ๊ฒ ๋ค๋ฅด์ง ์์. HTML์ํฐํฐ(> ๋ฑ)์ ์ฃผ์.
- code
- Elvis ์ฐ์ฐ์ : null์ฒ๋ฆฌ
- ${nullData}?:์คํ์ฝ๋
- ${nullData}?:์คํ์ฝ๋
- No-operation : ๋ฐ์ดํฐ๊ฐ null์ผ ๊ฒฝ์ฐ, ํ์๋ฆฌํ๋ ์๋ฌด๊ฒ๋ ํ์ง ์๋๋ค.
${nullData}?: _
- ์์ฑ ๊ฐ ์ค์
- <input type="text" name="mock" th:name="userA" />
โ ํ์๋ฆฌํ๋ ๊ธฐ์กด HTLM์ ์์ฑ์ธ name์ mock์์ userA๋ก ์นํํด๋ฒ๋ฆฐ๋ค. - code
- ๊ฒฐ๊ณผ
- th:classappend="large" โ class="text large"
- ํด๋์ค๋ช
๋ค์ ํ์นธ ๋๊ณ ์์ฑ๋ช
์ด ์ถ๊ฐ๋๋ค.
- th:attrappend์ th:attrprepend๋ ์ ์ฐ์ง ์๋๋ค.
- ํด๋์ค๋ช
๋ค์ ํ์นธ ๋๊ณ ์์ฑ๋ช
์ด ์ถ๊ฐ๋๋ค.
- th:checked="true" โ ์ฒดํฌ๋ฐ์ค๊ฐ checked์ํ๊ฐ ๋๋ค.
- th:checked="false" โ checked ์์ฑ ์์ฒด๋ฅผ ๋ฃ์ง ์๋๋ค.
- th:checked="false" โ checked ์์ฑ ์์ฒด๋ฅผ ๋ฃ์ง ์๋๋ค.
- <input type="text" name="mock" th:name="userA" />
- ๋ฐ๋ณต
- code
- ํ๋ฉด
- <tr th:each="user : ${users}"> โ for๋ฌธ์ฒ๋ผ ์ธ๋ฑ์ค์ ๋ด๊ธด ๋ฐ์ดํฐ๋ฅผ ํ๋์ฉ ๊บผ๋ด์ฌ ์ ์๋ค.
- ํ์๋ฆฌํ ์ ๊ณต ๊ธฐ๋ฅ Stat
- <tr th:each="user, userStat : ${users}"> โ ์ง์ ํ ๋ณ์๋ช
+ Stat ์ผ๋ก ์๋ตํด๋ ์ฌ์ฉ๊ฐ๋ฅํ๋ค. th:each="user : ${users}"
- index : 0๋ถํฐ์์ํ๋ ๊ฐ.
- count : 1๋ถํฐ ์์ํ๋ ๊ฐ.
- size : ์ ์ฒด ์ฌ์ด์ฆ.
- even, odd : ํ์, ์ง์ (Boolean).
- first, last : ์ฒ์ ๋ง์ง๋ง ์ฌ๋ถ (Boolean).
- current : ํ์ฌ ๊ฐ์ฒด.
- <tr th:each="user, userStat : ${users}"> โ ์ง์ ํ ๋ณ์๋ช
+ Stat ์ผ๋ก ์๋ตํด๋ ์ฌ์ฉ๊ฐ๋ฅํ๋ค. th:each="user : ${users}"
- code
- ์กฐ๊ฑด๋ถ ํ๊ฐ if & unless
- code
- ํ๋ฉด
- <span th:text="'๋ฏธ์ฑ๋
์'" th:if="${user.age lt 20}">
โ ์๋ฐ์ if๋ฌธ๊ณผ ๋์ผํ๋ค.
lt๋ HTML์ํฐํฐ๋ก < ์ด๋ค. 10๋์ด๋ฉด <span>ํ๊ทธ๊ฐ ์ถ๋ ฅ๋๋ค. - <span th:text="'๋ฏธ์ฑ๋
์'" th:unless="${user.age ge 20}">
โ unless๋ false์ผ ์ ์คํ๋๋ค.
ge๋ 10 >= 20์ false์ด๋ฏ๋ก ์คํ๋๋ค. - ๐ th:if์ th:unless๋ ์กฐ๊ฑด์ด ๋ง์ง ์์ผ๋ฉด ํ๊ทธ ์์ฒด๊ฐ ์ถ๋ ฅ๋์ง ์๋๋ค.
spanํ๊ทธ ๊ฐฏ์๊ฐ ๋ค๋ฅด๋ค. - <td th:switch="${user.age}">
โ java์ switch๋ฌธ๊ณผ ๋์ผํ๋ค.
๋น์ฐํ case๋ฌธ๊ณผ ๊ฐ์ด ์ฌ์ฉํ๋ค.
<span th:case="10">10์ด</span><span th:case="20">20์ด</span><span th:case="*">๊ธฐํ</span>
- code
- ์ฃผ์
- code
- ๊ฒฐ๊ณผ
- HTML์ฃผ์ <!-- -->
โ ๊ฐ๋ฐ์๋๊ตฌ์ ํ๊ธฐ๋๋ค. - ๐ํ์๋ฆฌํ ํ์ ์ฃผ์ <!--/* --> ์ฃผ์์ฒ๋ฆฌ ๋จ <!-- */-->
โ ๊ฐ๋ฐ์๋๊ตฌ์ ํ๊ธฐ๋์ง ์๋๋ค.
์ฃผ์ ์ฌ์ด์ ํ๊ทธ๋ ๋ ๋๋ง ์ ์ฃผ์์ฒ๋ฆฌ๋๋ค. - ํ์๋ฆฌํ ํ๋กํ ํ์
์ฃผ์ <!--/*/ ํ๋ฉด์ ์ถ๋ ฅ๋จ /*/-->
โ ์ฃผ์์ด์ง๋ง ๋ ๋๋ง ์ ์ค์ ํ๊ทธ๋ก ์ฒ๋ฆฌ๋์ด ์ถ๋ ฅ๋๋ค.
(์ ์ฌ์ฉ๋์ง ์์)
- HTML์ฃผ์ <!-- -->
- ๋ธ๋ก <th:block> ํ์๋ฆฌํ ์์ฒด ํ๊ทธ
- code
- ๊ฒฐ๊ณผ
- <div>ํ๊ทธ๋ฅผ ๋ธ๋ก์ผ๋ก ์ฌ๋ฌ๊ฐ๋ฅผ ๋ง๋ค์๋ค.
(์ฌ๋งํ๋ฉด ์ ์ฐ๋ ๊ฒ ์ข์ง๋ง, ํ์ํ ๊ฒฝ์ฐ๊ฐ ๊ฐ๋ ์๋ค)
- code
- ์๋ฐ์คํฌ๋ฆฝํธ ์ธ๋ผ์ธ <script th:inline="javascript">
- code
- ๊ฒฐ๊ณผ
- ํ์๋ฆฌํ ์ธ๋ผ์ธ ์ฌ์ฉ์
- ํ์๋ฆฌํ ์ธ๋ผ์ธ ์์ด ์ฌ์ฉํ๋ฉด ์์ ๊ฐ์ด ์ค๋ฅ๊ฐ ๋๊ธฐ ๋๋ฌธ์ ์ด๋ ๊ฒ ๋ณต์กํ๊ฒ ์ ์ด์ผ ํ๋ค.
- ๋ํ user = BasicController.User()์ ๊ฐ์ด ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๊ธฐ ํ๋ค๋ค.
- ํ์๋ฆฌํ ์ธ๋ผ์ธ ์์ด ์ฌ์ฉํ๋ฉด ์์ ๊ฐ์ด ์ค๋ฅ๊ฐ ๋๊ธฐ ๋๋ฌธ์ ์ด๋ ๊ฒ ๋ณต์กํ๊ฒ ์ ์ด์ผ ํ๋ค.
- ํ์๋ฆฌํ ์ฌ์ฉ ํ
- [[${user.username}]]; ์ ๊ฐ์ด ๊ฐ๋จํ ์ฌ์ฉํ ์ ์๋ค.
- /*[[${user.username}]]*/ ๋ ๋๋ง ํ๋ฉด์ ์ฃผ์ ์์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ๋ด์ถ๋ด ํ
ํ๋ฆฟ์ผ๋ก ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
- user ๋ฐ์ดํฐ๊ฐ json์ผ๋ก ๋ณํํด ๋ค์ด์จ๋ค.
- [[${user.username}]]; ์ ๊ฐ์ด ๊ฐ๋จํ ์ฌ์ฉํ ์ ์๋ค.
- for๋ฌธ ์ฌ์ฉํ๊ธฐ
- [# th:each="user, stat : ${users}"] [/]
- ์ด๋ ๊ฒ for๋ฌธ์ ๋๋ฆฌ๋ฉด json์ผ๋ก ํธํ๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
- [# th:each="user, stat : ${users}"] [/]
- code
- ํ ํ๋ฆฟ ์กฐ๊ฐ th:fragment & th:replace
- code
footer ์ ์ฉํ๋ฉด - ํ๋ฉด
- <footer th:fragment="copy"> โ ํธํฐ๋ช
์ ์ง์ ํ ์ ์๋ค.
- <div th:insert="~{template/fragment/footer :: copy}"> โ <div>ํ๊ทธ ์์ <footer>ํ๊ทธ๋ฅผ ์ถ๊ฐํ๋ค.
- <div th:replace="~{template/fragment/footer :: copy}"> โ <div>ํ๊ทธ๋ฅผ <footer>ํ๊ทธ๋ก ๋ฐ๊ฟ๋ฒ๋ฆฐ๋ค.
- footer๋ช
์ ์ง์ ํ ๋ param์ ์ง์ ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
<footer th:fragment="copyParam (param1, param2)">
<div th:replace="~{template/fragment/footer :: copyParam ('๋ฐ์ดํฐ1', '๋ฐ์ดํฐ2')}"></div> - ๋ถ๋ถ ํฌํจ ๋จ์ ํํ์
<div th:replace="template/fragment/footer :: copy">
โ ~{...} ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์์น์ด์ง๋ง ํ ํ๋ฆฟ ์กฐ๊ฐ์ ์ฌ์ฉํ๋ ์ฝ๋๊ฐ ๋จ์ํ๋ฉด ์ด ๋ถ๋ถ์ ์๋ตํ ์ ์๋ค. - ํ
ํ๋ฆฟ ๋ ์ด์์ 1
- ๊ณตํต <head>์ ์ฌ์ฉํ๋ css, javascript ๊ฐ์ ์ ๋ณด๋ค์ด ์๋๋ฐ, ๊ฐ ํ์ด์ง๋ง๋ค ์ ๋ณด๋ฅผ ๋ ์ถ๊ฐํด์ ์ฌ์ฉํ๊ณ ์ถ์ ๊ฒฝ์ฐ.
- code
java - ํ๋ฉด
- @GetMapping("layout") โ http://localhost:8080/template/layout ์ผ๋ก ๊ฐ๋ฉด layoutMain.html์ด ์ด๋ ค์ผ ํ๋ค.
- <head th:replace="template/layout/base :: common_header(~{::title},~{::link})">
th:replace๋ก base.html๋ก ๊ต์ฒดํด๋ฒ๋ฆฐ๋ค.
์ด ๋ common_header(~{::title},~{::link} ๋ฅผ ์ฌ์ฉํ๋ค. common_header๋ผ๋ ์ด๋ฆ์ผ๋ก <title>๊ณผ <link>๋ฅผ ์ ๋ฌํ๋ค. - base.html์์ <headth:fragment="common_header(title,links)">๋ก ์ ๋ฌ๋ฐ์ title๊ณผ links๋ฅผ <th:block th:replace="${links}" /> ๋ก ๋ฐ๊ฟ์ ์ฌ์ฉํ ์ ์๋ค.
- @GetMapping("layout") โ http://localhost:8080/template/layout ์ผ๋ก ๊ฐ๋ฉด layoutMain.html์ด ์ด๋ ค์ผ ํ๋ค.
- ํ
ํ๋ฆฟ ๋ ์ด์์ 2
- <html>ํ๊ทธ์ ํ์๋ฆฌํ ์์ฑ์ ๋ง๋ค์ด ํ์ด์ง ์์ฒด๋ฅผ ๊ต์ฒดํด ๋ฒ๋ฆฌ๋ ๊ฒฝ์ฐ. ์ค๋ณต ํ์ด์ง๊ฐ ๋ง์ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค.
- ํ๋ฉด
- <html th:fragment="layout (title, content)"
โ <html> ํ๊ทธ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ layout()์ด๋ ์ด๋ฆ์ผ๋ก ์ฌ์ฉํ ์ ์๊ฒ ํ๋ค. - <html th:replace="~{template/layoutExtend/layoutFile :: layout(~{::title},~{::section})}"
โ layoutFile์ ๊ฐ์ ธ์ ๊ต์ฒดํ๊ณ layout์ด๋ ์ด๋ฆ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ๋ค.
- <html>ํ๊ทธ์ ํ์๋ฆฌํ ์์ฑ์ ๋ง๋ค์ด ํ์ด์ง ์์ฒด๋ฅผ ๊ต์ฒดํด ๋ฒ๋ฆฌ๋ ๊ฒฝ์ฐ. ์ค๋ณต ํ์ด์ง๊ฐ ๋ง์ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค.
โป ์ฐธ์กฐ : https://www.inflearn.com/roadmaps/373E
๋ฐ์ํ
'โจ UI > ๐ค View Templates' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Thymeleaf][SpringBoot]์คํ๋ง์ด ์ง์ํ๋ ํ์๋ฆฌํ ๊ธฐ๋ฅ(์ ๋ ฅ์์ฃผ) (1) | 2025.03.11 |
---|---|
[Thymeleaf] ํ์๋ฆฌํ๋? (0) | 2025.03.07 |
[Thymeleaf]ํ์๋ฆฌํ ์ฌ์ฉ๋ฒ ๊ฐ๋จ์ ๋ฆฌ (0) | 2025.03.03 |
[JAVA]JSP๋ก ํ์๊ด๋ฆฌ ์น ์ ํ๋ฆฌ์ผ์ด์ ๋ง๋ค๊ธฐ (0) | 2025.02.28 |
[JSP] jsp๋? ๊ธฐ๋ณธ๊ตฌ์ฑ (0) | 2024.12.31 |