ํ ํ๋ฆฟ ์กฐ๊ฐ(Template fragments)์ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR) ํ ํ๋ฆฟ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๋น๊ต์ ๋๋ฌธ ๊ธฐ๋ฅ์ผ๋ก, ์ ์ฒด ํ ํ๋ฆฟ์ด ์๋ ํ ํ๋ฆฟ ๋ด์ ์ผ๋ถ ์กฐ๊ฐ(fragment) ๋๋ ๋ถ๋ถ ์ฝํ ์ธ ๋ฅผ ๋ ๋๋งํ ์ ์๊ฒ ํด์ค๋๋ค. ์ด ๊ธฐ๋ฅ์ ํ์ดํผ๋ฏธ๋์ด ๊ตฌ๋ ์ ํ๋ฆฌ์ผ์ด์ (Hypermedia Driven Applications)์์ ๋งค์ฐ ์ ์ฉํฉ๋๋ค. ์๋ํ๋ฉด ํ ํ๋ฆฟ์ ์ผ๋ถ๋ฅผ ๋ ๋๋งํ๊ธฐ ์ํด ๋ณ๋์ ํ์ผ๋ก ๋ถ๋ฆฌํ์ง ์๊ณ , ํ ํ๋ฆฟ์ ๋ด๋ถ์ ์ผ๋ก ๋ถํดํ์ฌ ๋ถ๋ถ ์ ๋ฐ์ดํธ๋ฅผ ์ํํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ ๊ฐ๋ณ ํ ํ๋ฆฟ ํ์ผ์ ์๋ฅผ ์ค์ผ ์ ์์ต๋๋ค.
๋ชจ๋ HTML์ ํ๋์ ํ์ผ์ ์ ์งํจ์ผ๋ก์จ ๊ธฐ๋ฅ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ๋ ์ฝ๊ฒ ์ดํดํ ์ ์์ต๋๋ค. ์ด๋ ํ๋์ ์ง์ญ์ฑ(Locality of Behavior) ์ค๊ณ ์์น์ ๋ฐ๋ฅด๋ ๊ฒ์ ๋๋ค.
Java์ฉ์ผ๋ก ๋ง๋ค์ด์ง ์ ์๋ ค์ง์ง ์์ ํ ํ๋ฆฟ ์ธ์ด์ธ Chill Templates๋ฅผ ์ฌ์ฉํ์ฌ ํ ํ๋ฆฟ ์กฐ๊ฐ์ด HDA๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ์ด๋ป๊ฒ ๋์์ด ๋ ์ ์๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ฌ๊ธฐ ์ฐ๋ฝ์ฒ๋ฅผ ํ์ํ๋ ๊ฐ๋จํ Chill ํ
ํ๋ฆฟ /contacts/detail.html
์ด ์์ต๋๋ค:
<html>
<body>
<div hx-target="this">
#if contact.archived
<button hx-patch="/contacts/${contact.id}/unarchive">Unarchive</button>
#else
<button hx-delete="/contacts/${contact.id}">Archive</button>
#end
</div>
<h3>Contact</h3>
<p>${contact.email}</p>
</body>
</html>
์ด ํ ํ๋ฆฟ์๋ ์์นด์ด๋น ๊ธฐ๋ฅ์ด ์์ต๋๋ค. ์ฐ๋ฝ์ฒ์ ์์นด์ด๋ธ ์ํ์ ๋ฐ๋ผ โArchiveโ ๋๋ โUnarchiveโ ๋ฒํผ ์ค ํ๋๊ฐ ํ์๋ฉ๋๋ค. ์ด ๋ ๋ฒํผ์ ๋ชจ๋ htmx์ ์ํด ๊ตฌ๋๋๋ฉฐ, ์๋ก ๋ค๋ฅธ ์๋ํฌ์ธํธ์ HTTP ์์ฒญ์ ๋ณด๋ ๋๋ค.
์ฐ๋ฆฌ๋ ํ์๋ ๋ฒํผ์ ํด๋ฆญํ ๋, ํด๋น ๋ฒํผ์ ๋๋ฌ์ผ div
์ ์ฝํ
์ธ ๋ฅผ ์
๋ฐ์ดํธ๋ ๋ฒํผ์ผ๋ก ๊ต์ฒดํ๊ณ ์ถ์ต๋๋ค.
(div์ hx-target="this"
๋ฅผ ์ฃผ๋ชฉํ์ธ์. ์ด๋ ๊ทธ div์ innerHTML์ ๊ต์ฒด ๋์์ผ๋ก ์ง์ ํฉ๋๋ค.) ์ด๋ ๊ฒ ํ๋ฉด โArchiveโ์ โUnarchiveโ ์ฌ์ด๋ฅผ ๋ฒ๊ฐ์๊ฐ๋ฉฐ ์ ํํ ์ ์์ต๋๋ค.
ํ์ง๋ง ๋ถํํ๋, ์ด ํ ํ๋ฆฟ์ ๋๋จธ์ง ๋ถ๋ถ์ด ์๋ ๋ฒํผ๋ง ๋ ๋๋งํ๋ ค๋ฉด, ์ผ๋ฐ์ ์ผ๋ก ๋ฒํผ์ ๋ณ๋์ ํ ํ๋ฆฟ ํ์ผ๋ก ๋ถ๋ฆฌํ๊ณ ์ด ํ ํ๋ฆฟ์ ํฌํจ์์ผ์ผ ํฉ๋๋ค. ๋ค์๊ณผ ๊ฐ์ด ๋ง์ด์ฃ :
<html>
<body>
<div hx-target="this">
#include archive-ui.html
</div>
<h3>Contact</h3>
<p>${contact.email}</p>
</body>
</html>
#if contact.archived
<button hx-patch="/contacts/${contact.id}/unarchive">Unarchive</button>
#else
<button hx-delete="/contacts/${contact.id}">Archive</button>
#end
์ด์ ๋ ๊ฐ์ ํ
ํ๋ฆฟ์ด ์๊ฒผ์ต๋๋ค. ์ด์ archive-ui.html
ํ
ํ๋ฆฟ์ ๋ณ๋๋ก ๋ ๋๋งํ ์ ์์ง๋ง, ์ด๋ ๊ฒ ๋ถ๋ฆฌํ๋ฉด ์์นด์ด๋น ๊ธฐ๋ฅ์ ๊ฐ์์ฑ์ด ์ค์ด๋ญ๋๋ค.
detail.html
ํ
ํ๋ฆฟ๋ง ๋ณด๊ณ ์์ ๋ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ๋ ๋ช
ํํด์ง๋๋ค.
์ด๋ฌํ ๋ฐฉ์์ผ๋ก ํ ํ๋ฆฟ์ ๊ทน๋จ์ ์ผ๋ก ๋ถํดํ๋ฉด ๊ด๋ฆฌ ๋ฐ ์ดํดํ๊ธฐ ์ด๋ ค์ด ์์ ํ ํ๋ฆฟ ์กฐ๊ฐ๋ค์ด ๋ง์ด ์๊ธธ ์ ์์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด, Chill ํ
ํ๋ฆฟ์๋ #fragment
์ง์์ด๊ฐ ์์ต๋๋ค. ์ด ์ง์์ด๋ฅผ ์ฌ์ฉํ๋ฉด ํ
ํ๋ฆฟ ๋ด์์ ์ฝํ
์ธ ์ ์ผ๋ถ ๋ธ๋ก์ ์ง์ ํ๊ณ ๊ทธ ๋ถ๋ถ๋ง ๋ ๋๋งํ ์ ์์ต๋๋ค.
<html>
<body>
<div hx-target="this">
#fragment archive-ui
#if contact.archived
<button hx-patch="/contacts/${contact.id}/unarchive">Unarchive</button>
#else
<button hx-delete="/contacts/${contact.id}">Archive</button>
#end
#end
</div>
<h3>Contact</h3>
<p>${contact.email}</p>
</body>
</html>
์ด์ ํ ํ๋ฆฟ ๋ด์ ์ด ์กฐ๊ฐ์ด ์ ์๋์์ผ๋ฏ๋ก, ์ ์ฒด ํ ํ๋ฆฟ์ ๋ ๋๋งํ ์ ์์ ๋ฟ๋ง ์๋๋ผ:
Contact c = getContact();
ChillTemplates.render("/contacts/detail.html", "contact", c);
ํ
ํ๋ฆฟ์ archive-ui
์กฐ๊ฐ๋ง ๋ ๋๋งํ ์๋ ์์ต๋๋ค:
Contact c = getContact();
ChillTemplates.render("/contacts/detail.html#archive-ui", "contact", c);
์ฒซ ๋ฒ์งธ ์ต์ ์ ์ฐ๋ฝ์ฒ์ ์ ์ฒด ์์ธ ํ์ด์ง๋ฅผ ๋ ๋๋งํ๊ณ ์ ํ ๋ ์ฌ์ฉํฉ๋๋ค.
๋ ๋ฒ์งธ ์ต์ ์ ์์นด์ด๋ธ/์์นด์ด๋ธ ํด์ ์์ ์ ์ฒ๋ฆฌํ๊ณ ๋ฒํผ๋ง ๋ค์ ๋ ๋๋งํ๊ณ ์ ํ ๋ ์ฌ์ฉํฉ๋๋ค.
์กฐ๊ฐ์ ์ฌ์ฉํ๋ฉด, UI๋ฅผ ๋จ์ผ ํ์ผ์ ํตํฉํ์ฌ ์ด ๊ธฐ๋ฅ์ด ์ด๋ป๊ฒ ๋์ํ๋์ง ์ ํํ ํ์ ํ ์ ์์ผ๋ฉฐ, ์ฌ๋ฌ ํ ํ๋ฆฟ ํ์ผ์ ์ค๊ฐ๋ฉฐ ์์ ํ ํ์๊ฐ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๊ธฐ๋ฅ์ ๊ตฌํ์ด ๋ ๋ช ํํ๊ณ ๊นจ๋ํด์ง๋๋ค.
ํ ํ๋ฆฟ ์กฐ๊ฐ(๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ์ปจํธ๋กค๋ฌ์์ ์ง์ ๋ ๋๋งํ๋ ๊ธฐ๋ฅ)์ ํ ํ๋ฆฟ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ๋น๊ต์ ๋๋ฌธ ๊ธฐ๋ฅ์ด์ง๋ง, htmx์ ๊ฐ์ ํ์ดํผ๋ฏธ๋์ด ์งํฅ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์์ ํ ๋ ๊ฐ๋ฐ์ ๊ฒฝํ์ ํฌ๊ฒ ๊ฐ์ ํ ์ ์๋ ์ข์ ๊ธฐํ๋ฅผ ์ ๊ณตํฉ๋๋ค.
๋ค์์ ํ ํ๋ฆฟ ์กฐ๊ฐ ๊ฐ๋ ์ด ๊ตฌํ๋ ๊ฒ์ผ๋ก ์๋ ค์ง ๋ช ๊ฐ์ง ์์ ๋๋ค:
$Latte_Engine->render('path/to/template.latte', [ 'foo' => 'bar' ], 'content');
$template->renderBlock('block_name', ['the' => 'variables', 'go' => 'here']);
๋ค๋ฅธ ์๋ฅผ ์๊ณ ์๋ค๋ฉด, ์ฐ๋ฝํด ์ฃผ์ธ์. ๋ชฉ๋ก์ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.