ํ์ดํผ๋ฏธ๋์ด API๋ ํ์ดํผ๋ฏธ๋์ด๋ฅผ ๋ฐํํ๋ API๋ก, ์ผ๋ฐ์ ์ผ๋ก HTML์ HTTP๋ฅผ ํตํด ์ ์กํฉ๋๋ค. ์ด๋ฌํ ์คํ์ผ์ API๋ ํ์ดํผ๋ฏธ๋์ด๋ฅผ ๋ฐํํ์ง ์๋ ๋ฐ์ดํฐ API์ ๊ตฌ๋ณ๋ฉ๋๋ค. ์ค๋๋ ์ด ํ์์ ์คํ์ผ์ ์ผ๋ฐ์ ์ผ๋ก JSON API๋ก ์๋ ค์ ธ ์์ต๋๋ค.
์ด ๋ ๊ฐ์ง ์ ํ์ API๋ ๊ฐ๊ฐ ๊ณ ์ ํ ์ค๊ณ ์๊ตฌ ์ฌํญ์ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก, ์๋ก ๋ค๋ฅธ ์ค๊ณ ์ ์ฝ ์กฐ๊ฑด๊ณผ ๋ชฉํ๋ฅผ ์ฑํํด์ผ ํฉ๋๋ค.
์ค๋๋ API๋ ์ผ๋ฐ์ ์ผ๋ก HTTP๋ฅผ ํตํ JSON์ผ๋ก ์๊ฐ๋ฉ๋๋ค. ์ด๋ฌํ API๋ ๊ฑฐ์ ํญ์ ํ์ดํผ๋ฏธ๋์ด API๋ณด๋ค๋ ๋ฐ์ดํฐ ์งํฅ API์ด์ง๋ง, ๋๋ก๋ ํ์ดํผ๋ฏธ๋์ด ๊ฐ๋ ์ด ํตํฉ๋๊ธฐ๋ ํฉ๋๋ค(๋๋ถ๋ถ ์ต์ข ์ฌ์ฉ์์๊ฒ ํฐ ์ด์ ์ ์ฃผ์ง ๋ชปํฉ๋๋ค). ์ ๊ณ๋ REST-ful API์์ ๋ฒ์ด๋ ๋ฐ์ดํฐ API๋ฅผ REST-ful ๋ชจ๋ธ์ ๋ง์ถ๋ ๋ฐ์ ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ์ธ์ํ๊ธฐ ์์ํ์ต๋๋ค.
์ด๊ฒ์ ์ข์ ์ผ์ ๋๋ค. ์ ๊ณ๋ ๋ฐ์ดํฐ API ๋ถ์ผ์์ REST-ful ์์ด๋์ด์ ๋ํด ์๋ฌธ์ ์ ๊ธฐํ๊ณ , REST๊ฐ ์ค๋ช ํ๋ ค ํ๋ ๋คํธ์ํฌ ์ํคํ ์ฒ ๋์ , ํด๋น ํน์ ๋คํธ์ํฌ ์ํคํ ์ฒ๋ฅผ ๋ ์ ์๋น์คํ ์ด์ ์ ํด๋ผ์ด์ธํธ-์๋ฒ ๊ธฐ์ ์ ์ดํด๋ณด๊ธฐ ์์ํด์ผ ํฉ๋๋ค.
ํ์ดํผ๋ฏธ๋์ด API๊ฐ ๋ฐ์ดํฐ API์ ๋ค๋ฅด๊ฒ ์ค๊ณ๋ ์ ์๋ ๋ฐฉ์์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด, ์ต๊ทผ htmx ๋์ค์ฝ๋์์ ์ ๊ธฐ๋ ๋ค์ ์ํฉ์ ๊ณ ๋ คํด ๋ณด๊ฒ ์ต๋๋ค:
์ ๋ ํผ๊ณผ ํ ์ด๋ธ์ด ์๋ ํ์ด์ง๋ฅผ ์ํฉ๋๋ค. ์ด ํผ์ ํ ์ด๋ธ์ ์ ์์๋ฅผ ์ถ๊ฐํ ๊ฒ์ด๋ฉฐ, ํ ์ด๋ธ์ 30์ด๋ง๋ค ํด๋งํ์ฌ ๋ค๋ฅธ ์ฌ์ฉ์์ ์ ๋ฐ์ดํธ๋ฅผ ํ์ํ ๊ฒ์ ๋๋ค.
์ด UI๋ฅผ ๊ธฐ๋ณธ URL /contacts
๋ก ๊ณ ๋ คํด ๋ณด๊ฒ ์ต๋๋ค.
์ฒซ ๋ฒ์งธ๋ก ํ์ํ ๊ฒ์ ํผ๊ณผ ํ์ฌ ์ฐ๋ฝ์ฒ ํ
์ด๋ธ์ ๊ฐ์ ธ์ค๋ ์๋ํฌ์ธํธ์
๋๋ค. ์ด ์๋ํฌ์ธํธ๋ /contacts
์ ์์นํ๋ฉฐ ๋ค์๊ณผ ๊ฐ์ด ์๋ํฉ๋๋ค:
GET /contacts -> ํผ ๋ฐ ์ฐ๋ฝ์ฒ ํ
์ด๋ธ ๋ ๋๋ง
๋ค์์ผ๋ก, ์ฐ๋ฝ์ฒ๋ฅผ ์์ฑํ ์ ์์ด์ผ ํฉ๋๋ค. ์ด๋ ๋์ผํ URL๋ก POST ์์ฒญ์ ํตํด ์ํ๋ฉ๋๋ค:
GET /contacts -> ํผ ๋ฐ ์ฐ๋ฝ์ฒ ํ
์ด๋ธ ๋ ๋๋ง
POST /contacts -> ์ ์ฐ๋ฝ์ฒ ์์ฑ, GET /contacts๋ก ๋ฆฌ๋๋ ์
๊ทธ๋ฆฌ๊ณ HTML์ ๋ค์๊ณผ ๊ฐ์ด ์๊ฒผ์ ๊ฒ์ ๋๋ค:
<div>
<form action='/contacts' method="post">
<!-- ์ฐ๋ฝ์ฒ ์ถ๊ฐ๋ฅผ ์ํ ํผ -->
</form>
<table>
<!-- ์ฐ๋ฝ์ฒ ํ
์ด๋ธ -->
</table>
</div>
์ง๊ธ๊น์ง๋ ๋งค์ฐ ์ ํ์ ์ธ ์น 1.0 ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๋ค. ์ด ์์ ๊น์ง๋ ๋ฐ์ดํฐ API์ ํ์ดํผ๋ฏธ๋์ด API์ ์๊ตฌ ์ฌํญ์ด ํฌ๊ฒ ๋ค๋ฅด์ง ์์ง๋ง, ํ์ดํผ๋ฏธ๋์ด API๊ฐ ์๊ธฐ ์ค๋ช ์ ์ด๋ฉฐ URL์ ๋ณ๊ฒฝํด๋ ํ์ดํผ๋ฏธ๋์ด ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์๋์ง ์๋๋ค๋ ์ ์ ์ฃผ๋ชฉํ ๋งํฉ๋๋ค.
์ด์ htmx๊ฐ ํ์ํ ๋ถ๋ถ์ ๋๋ฌํ์ต๋๋ค. ํ
์ด๋ธ ์
๋ฐ์ดํธ๋ฅผ ์ํด ์ฃผ๊ธฐ์ ์ผ๋ก ์๋ฒ๋ฅผ ํด๋งํด์ผ ํฉ๋๋ค.
์ด๋ฅผ ์ํด /contacts/table
์ด๋ผ๋ ์ ์๋ํฌ์ธํธ๋ฅผ ์ถ๊ฐํ์ฌ ์ฐ๋ฝ์ฒ ํ
์ด๋ธ๋ง ๋ ๋๋งํ๋๋ก ํฉ๋๋ค:
GET /contacts -> ํผ ๋ฐ ์ฐ๋ฝ์ฒ ํ
์ด๋ธ ๋ ๋๋ง
POST /contacts -> ์ ์ฐ๋ฝ์ฒ ์์ฑ, GET /contacts๋ก ๋ฆฌ๋๋ ์
GET /contacts/table -> ์ฐ๋ฝ์ฒ ํ
์ด๋ธ ๋ ๋๋ง
๊ทธ๋ฆฌ๊ณ ํ ์ด๋ธ์ ํด ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ถ๊ฐํฉ๋๋ค:
<div>
<form action='/contacts' method="post">
<!-- ์ฐ๋ฝ์ฒ ์ถ๊ฐ๋ฅผ ์ํ ํผ -->
</form>
<table hx-trigger="every 30s" hx-get="/contacts/table" hx-swap="outerHTML">
<!-- ์ฐ๋ฝ์ฒ ํ
์ด๋ธ -->
</table>
</div>
์ฌ๊ธฐ์ ํ์ดํผ๋ฏธ๋์ด API์ ๋ฐ์ดํฐ API์ ์ฐจ์ด๊ฐ ๋ํ๋๊ธฐ ์์ํฉ๋๋ค. ์ด ์ ์๋ํฌ์ธํธ๋ ๋ฐ์ดํฐ ๋ชจ๋ธ์ ํ์๊ฐ ์๋๋ผ ํ์ดํผ๋ฏธ๋์ด์ ํ์์ ์ํด ์์ ํ ๊ตฌ๋๋ฉ๋๋ค. ์ด ์๋ํฌ์ธํธ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์ดํผ๋ฏธ๋์ด ์๊ตฌ ์ฌํญ์ด ๋ณ๊ฒฝ๋๋ฉด ์ฌ๋ผ์ง ์ ์์ผ๋ฉฐ, ๊ทธ ํํ๊ฐ ํฌ๊ฒ ๋ฐ๋ ์ ์์ต๋๋ค. ์ด๋ ์์คํ ์ด ์๊ธฐ ์ค๋ช ์ ์ด๊ธฐ ๋๋ฌธ์ ์ ์ ์ผ๋ก ํ์ฉ๋ฉ๋๋ค.
HTML์ htmx๋ฅผ ์ฌ์ฉํ์ฌ ํด๋งํ๋๋ก ์ ๋ฐ์ดํธํ์ผ๋ฏ๋ก, ๋ ๋์ ์ฌ์ฉ์ ๊ฒฝํ(UX)์ ์ํด ํผ์์๋ htmx๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค:
<div>
<form action='/contacts' method="post" hx-boost="true">
<!-- ์ฐ๋ฝ์ฒ ์ถ๊ฐ๋ฅผ ์ํ ํผ -->
</form>
<table hx-trigger="every 30s" hx-get="/contacts/table" hx-swap="outerHTML">
<!-- ์ฐ๋ฝ์ฒ ํ
์ด๋ธ -->
</table>
</div>
ํ์์ ๋ฐ๋ผ ์ ๋ ฅ์ ์๋ฒ ์ธก ๊ฒ์ฆ, ๋์ ํผ ๋ฑ์ ์ํ ์ถ๊ฐ ์๋ํฌ์ธํธ๋ฅผ ์ถ๊ฐํ ์๋ ์์ต๋๋ค. ์ด๋ฌํ ์๋ํฌ์ธํธ๋ ๋ฐ์ดํฐ ๋ชจ๋ธ ๊ณ ๋ ค ์ฌํญ์ด ์๋ ํ์ดํผ๋ฏธ๋์ด์ ํ์์ ๋ฐ๋ผ ๊ตฌ๋๋ฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ฌ์ฑํ๋ ค๋ ๋ชฉํ๋ฅผ ๊ธฐ์ค์ผ๋ก ์๊ฐํฉ๋๋ค.
์ด ์งง์ ๊ธ์ ํต์ฌ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค: ํ์ดํผ๋ฏธ๋์ด ์์คํ ์์๋ ํ์ดํผ๋ฏธ๋์ด ์์คํ ์ ๋ฉ์์ง๊ฐ ์๊ธฐ ์ค๋ช ์ ์ด๊ธฐ ๋๋ฌธ์ API ๋ณ๊ฒฝ์ด ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค. API๋ฅผ ์ฌ๋ฌ ๋ฒ ๋ณ๊ฒฝํด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๊นจ์ง์ง ์์ต๋๋ค. ์ธ๊ฐ ์ฌ์ฉ์๋ ์๋ก์ด ํ์ดํผ๋ฏธ๋์ด(HTML)๋ฅผ ๋ณด๊ณ ์ํ๋ ์์ ์ ์ ํํ ์ ์์ต๋๋ค.
์ปดํจํฐ์ ๋น๊ตํ ๋ ์ธ๊ฐ์ ๋ฌด์์ ํด์ผ ํ ์ง ๊ฒฐ์ ํ๋ ๋ฐ ๋ฐ์ด๋๋ฉฐ, ๋ณํ์ ๋น๊ต์ ์ ์ ์ํฉ๋๋ค.
์ด๋ ๋ฐ์ดํฐ API์๋ ๋์กฐ์ ์ ๋๋ค. ๋ฐ์ดํฐ API๋ ํด๋ผ์ด์ธํธ ์ฝ๋๋ฅผ ๊นจ๋จ๋ฆฌ์ง ์๊ณ ๋ ์์ ํ ์ ์์ผ๋ฏ๋ก, ๋ณ๊ฒฝ์ ์์ด ํจ์ฌ ๋ ์ ์คํด์ผ ํฉ๋๋ค. ๋ฐ์ดํฐ API๋ ๋ ๋ง์ ํด๋ผ์ด์ธํธ ์๊ตฌ๋ฅผ ์์ ์์ด ์ถฉ์กฑ์ํฌ ์ ์๋๋ก ํํ๋ ฅ์ ๋์ด๊ธฐ ์ํ ์๋ฐ์ ๋ฐ์ต๋๋ค.
ํ์ดํผ๋ฏธ๋์ด API๋ฅผ ์ค๊ณํ ๋๋ ๋ฐ์ดํฐ API๋ฅผ ์ค๊ณํ ๋์ ๋ค๋ฅธ ์ฌ๊ณ ๋ฐฉ์์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๋ณ๊ฒฝ์ด ํฐ ๋ฌธ์ ๊ฐ ๋์ง ์์ผ๋ฉฐ, ์ข์ ํ์ดํผ๋ฏธ๋์ด ๊ฒฝํ์ ์ ๊ณตํ๊ธฐ ์ํด ํ์ํ ์๋ํฌ์ธํธ๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ์ฃผ์ ๋ชฉํ๊ฐ ๋์ด์ผ ํฉ๋๋ค.