[Spring boot] HTMX + Thymeleaf ์กฐํ•ฉ์œผ๋กœ ์›น ํŽ˜์ด์ง€ ๊ฐœ๋ฐœ ์‹œ์ž‘ํ•˜๊ธฐ

๋ฐ˜์‘ํ˜•
 

[Web] HTML ๋ง๊ณ  HTMX(HyperText Markup eXtension)

์›นํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“œ๋ ค๋ฉด ๋ฐ˜๋“œ์‹œ ๋ฐฐ์›Œ์•ผ ํ•˜๋Š” ์–ธ์–ด ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฐ”๋กœ HTML(HyperText Markup Language)์ž…๋‹ˆ๋‹ค. HTML์€ ํฐ ํ™”๋ฉด์— ํ…์ŠคํŠธ(๊ธ€์ž)๋ฅผ ํ‘œ๊ธฐํ•˜๋Š” ๋งˆํฌ์—… ์–ธ์–ด ์ค‘ ํ•˜๋‚˜๋กœ ๊ณผ๊ฑฐ HTTP ํ†ต์‹ ์„ ์ด์šฉํ•˜์—ฌ ํฐ ํ…

blog.neonkid.xyz

์ง€๋‚œ ํฌ์ŠคํŠธ์—์„œ ์šฐ๋ฆฌ๋Š” HTMX๋ผ๋Š” HTML ํ™•์žฅ ๊ฐœ๋…์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” Spring๊ณผ Spring์—์„œ ์ง€์›ํ•˜๋Š” ํ…œํ”Œ๋ฆฟ ์—”์ง„์ธ ํƒ€์ž„๋ฆฌํ”„(Thymeleaf) ์กฐํ•ฉ์œผ๋กœ ๊ฐ„๋‹จํ•œ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

์ดˆ๊ธฐ ๊ตฌ์„ฑ

Spring Initializer๋ฅผ ์ด์šฉํ•˜์—ฌ ๋จผ์ € ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœ์ ํŠธ ๊ตฌ์„ฑ์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•  ํŒจํ‚ค์ง€๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

  • Spring boot 3.2.0
  • Spring boot starter web
  • Spring boot starter thymeleaf

build.gradle ํ˜น์€ pom.xml์—์„œ ํ•ด๋‹น ํŒจํ‚ค์ง€๋ฅผ ์ถ”๊ฐ€ํ•œ ๋’ค ์•„๋ž˜์™€ ๊ฐ™์ด ํƒ€์ž„๋ฆฌํ”„ ๊ธฐ๋ณธ ์„ค์ •์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

๊ฐœ๋ฐœํ•œ ์ฝ”๋“œ๊ฐ€ ์ž˜ ์ ์šฉ๋˜์—ˆ๋Š”์ง€ ๋ณด๊ธฐ ์œ„ํ•ด ์บ์‹œ๋ฅผ ๋น„ํ™œ์„ฑํ™” ํ•ฉ๋‹ˆ๋‹ค. ์บ์‹œ๋ฅผ ํ™œ์„ฑํ™” ํ•˜๋Š” ๊ฒฝ์šฐ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๊ธฐ์กด์— ์„œ๋ฒ„๋กœ ๊ฐ€์ ธ์˜จ ๊ฒฐ๊ณผ๋ฌผ์„ ๋ฏธ๋ฆฌ ๋กœ๋“œํ•˜์—ฌ ๋ณด์—ฌ์ฃผ๋ฏ€๋กœ ๋ฐ”๋กœ ๋ณด์—ฌ์ง€์ง€ ์•Š๋Š” ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

๊ทธ๋ฆฌ๊ณ  ์›น ํŽ˜์ด์ง€ ํŒŒ์ผ์€ ๋ชจ๋‘ resources/templates ํด๋”์— ๋„ฃ์–ด์„œ ๋ณด๋„๋ก ํ•  ๊ฒƒ์ด๋ฉฐ ์ •์  ํŒŒ์ผ(js, css ํŒŒ์ผ)์€ static ํด๋”์— ๋„ฃ์–ด์„œ ๋ณด๋Š” ๊ฒƒ์œผ๋กœ ์„ค์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์ด์ œ templates/index.html ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ , ์œ„ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•ด๋ณธ ๋‹ค์Œ ์Šคํ”„๋ง ๋ถ€ํŠธ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์œ„์™€ ๊ฐ™์ด It works ! ๋ผ๋Š” ํ™”๋ฉด์ด ๋ณด์ด๋ฉด thymeleaf๊ฐ€ ํฌํ•จ๋œ Spring boot ํ”„๋กœ์ ํŠธ๊ฐ€ ์ž˜ ์ƒ์„ฑ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ œ ๋‹ค์Œ์œผ๋กœ HTMX๋ฅผ ๊ตฌ์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

 

HTMX๋ฅผ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• 1

HTMX ํ™ˆํŽ˜์ด์ง€์—์„œ ๊ณต์‹์ ์œผ๋กœ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ HTML ํŒŒ์ผ์— htmx ์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

script ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•˜์—ฌ htmx ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์„ฑ๊ณต์ ์œผ๋กœ ์ ์šฉ์ด ์™„๋ฃŒ๋˜์—ˆ์œผ๋ฉฐ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์ƒ˜ํ”Œ API๋ฅผ ํ•œ ๊ฐœ ๋งŒ๋“ค๊ณ , ํ™”๋ฉด์— ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ, It works ! ํ™”๋ฉด์„ Hello htmx ! ๋ผ๋Š” ๋ฌธ๊ตฌ๋กœ ๋ฐ”๊พธ์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋จผ์ € ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. It works ! ๋ฉ”์‹œ์ง€๋ฅผ DOM์œผ๋กœ ๊ฐ์‹ธ๊ณ , ๊ทธ DOM์ด ๋ฐ”๋€” ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ID๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ , ๋ฐ”๋กœ ํ•˜๋‹จ์— ๋ฒ„ํŠผ์„ ๋งŒ๋“ค์–ด ๋ฒ„ํŠผ ํด๋ฆญ์‹œ It works ! ๋ฉ”์‹œ์ง€๊ฐ€ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋„๋ก hx-get์œผ๋กœ GET /hello ํ˜ธ์ถœ์‹œ outerHTML ํ•จ์ˆ˜๋กœ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฐ”๋€Œ๋„๋ก ํ•˜๊ณ  hx-target์œผ๋กœ ๋ฐ”๊ฟ€ DOM์˜ ID๋ฅผ ์ง€์ •ํ•ด์ค๋‹ˆ๋‹ค.

 

๋‹ค์Œ์œผ๋กœ /hello API๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. HTMX๋Š” ์„ ์–ธ์  ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— Hello htmx๋ผ๋Š” ๋‹จ์ˆœ ํ…์ŠคํŠธ๊ฐ€ ์•„๋‹Œ HTML ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค˜์•ผ ํ•˜๋ฉฐ ์ด ๋•Œ๋Š” Controller ์–ด๋…ธํ…Œ์ด์…˜์ด ์•„๋‹Œ RestController ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด View๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ณ , HTML ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค˜์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด์ฃ .

 

์ด์ œ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๋ฉด Click Me ๋ผ๋Š” ๋ฒ„ํŠผ์ด ๋งŒ๋“ค์–ด์ง€๊ณ  ์ด ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด๋ณด๋ฉด...

 

์ด๋ ‡๊ฒŒ ์œ„์™€ ๊ฐ™์ด Hello htmx ! ๋ฌธ๊ตฌ๋กœ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ HTMX๋Š” Javascript์™€ ๊ฐ™์€ ๋ช…๋ น ๊ตฌ๋ฌธ ์—†์ด๋„ ์„ ์–ธ์  HTML ์ฝ”๋“œ์™€ attribute๋งŒ์„ ์ด์šฉํ•˜์—ฌ ์‰ฝ๊ฒŒ ์›นํŽ˜์ด์ง€๋ฅผ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

HTMX ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์™ธ๋ถ€ CDN ๋“ฑ์— ๋ฏธ๋ฆฌ ์ €์žฅ๋œ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜๋„ ์žˆ์ง€๋งŒ Spring์˜ ๊ฒฝ์šฐ๋Š” Maven์—์„œ npm ํŒจํ‚ค์ง€๋ฅผ ์ผ๋ถ€ ์ง€์›ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ํŒจํ‚ค์ง€ ์ €์žฅ์†Œ์—์„œ ์ง์ ‘ ๋ฐ›์•„ HTMX๋ฅผ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

HTMX๋ฅผ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• 2

1์—์„œ๋Š” ํ…œํ”Œ๋ฆฟ ์—”์ง„ ์—†์ด ์ˆœ์ˆ˜ HTML ํŒŒ์ผ์—์„œ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ ์ด๋ฒˆ์—๋Š” ํ…œํ”Œ๋ฆฟ ์—”์ง„์ธ ํƒ€์ž„๋ฆฌํ”„(thymeleaf)๋ฅผ ์ด์šฉํ•˜์—ฌ Maven์—์„œ ์›ํ•˜๋Š” HTMX ๋ฒ„์ „์— ๋งž์ถฐ ์ž๋™์œผ๋กœ ์ •์  ํŒŒ์ผ์— ์ ์šฉ๋  ์ˆ˜ ์žˆ๋„๋ก ์ ์šฉํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋จผ์ € ์•ž์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ web.resources.static-locations๋ฅผ ๊ธฐ์กด์œผ๋กœ ๋กค๋ฐฑํ•˜๊ณ , thymeleaf์˜ prefix๋ฅผ templates ํ•˜์œ„๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ templates ํ•˜์œ„์— ์žˆ๋Š” html ํŒŒ์ผ์„ ์ˆœ์ˆ˜ HTML ํŒŒ์ผ์ด ์•„๋‹Œ ํ…œํ”Œ๋ฆฟ ์—”์ง„์œผ๋กœ ์ฝ์–ด์„œ HTML๋กœ ๋ณ€ํ™˜ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฐ ๋‹ค์Œ ์œ„์™€ ๊ฐ™์ด webjars htmx์™€ webjars-locator๋ฅผ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค. webjars๋Š” ์›น ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ jar๋กœ ํŒจํ‚ค์ง•ํ•˜์—ฌ Maven ๋“ฑ์˜ ์ €์žฅ์†Œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“  ๋ ˆํฌ์ง€ํ„ฐ๋ฆฌ์ด๋ฉฐ webjars-locator๋Š” ์ •์  ๊ฒฝ๋กœ ์ง€์ •์‹œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฒ„์ „์„ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ , ๋™์ ์œผ๋กœ ์ปดํŒŒ์ผ์‹œ ์ ์šฉํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.

 

์ด์ œ index.html์„ ํ…œํ”Œ๋ฆฟ ์—”์ง„์— ๋งž๊ฒŒ ๋ณ€ํ™˜ํ•ด์ค๋‹ˆ๋‹ค. ๋ˆˆ์— ๋„๊ฒŒ ๋ฐ”๋€ ๊ฒƒ์€ ๊ธฐ์กด์˜ script ํƒœ๊ทธ์˜ src ์†์„ฑ์ด ์•„๋‹Œ th:src๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์ฃผ์†Œํ˜•์‹์ด ํ…œํ”Œ๋ฆฟ ์—”์ง„์—์„œ ์ง€์›ํ•˜๋Š” ํ‘œํ˜„์‹(expression)์„ ์‚ฌ์šฉํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด HTMX ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ฒ„์ „์ด ๋ฐ”๋€Œ์–ด๋„ ์ˆ˜์‹œ๋กœ index.html ํŒŒ์ผ์—์„œ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ž˜ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ฒ˜๋Ÿผ HTMX๋Š” ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์ด์šฉํ•˜์ง€ ์•Š๊ณ ๋„ ์ผ๋ฐ˜์ ์ธ MVC ๊ฐœ๋ฐœ ๋ฐฉ์‹๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๋ฐ˜๋Œ€๋กœ ํ…œํ”Œ๋ฆฟ ์—”์ง„๊ณผ ํ•จ๊ป˜ HTMX๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

Tailwind CSS ์ ์šฉํ•ด๋ณด๊ธฐ

ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ๋‚˜๋‹ˆ CSS ์ ์šฉ์ด ์—ฌ์ „ํžˆ ๋‚œ์ œ์ž…๋‹ˆ๋‹ค. webjars์—์„œ bootstrap ๋“ฑ ๋‹ค์–‘ํ•œ CSS๋ฅผ ์ง€์›ํ•ด์ฃผ๊ณค ์žˆ์ง€๋งŒ ์ข€ ๋” ๋‚˜๋งŒ์˜ ์Šคํƒ€์ผ์„ ๋งŒ๋“ค์–ด๋ณด๊ธฐ ์œ„ํ•ด tailwind CSS๋ฅผ ์ ์šฉํ•ด๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์Šต๋‹ˆ๋‹ค.

 

HTMX + Thymeleaf ์กฐํ•ฉ์œผ๋กœ tailwind CSS ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Node.js๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ tailwind ๋””ํŽœ๋˜์‹œ๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์ง„ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ํŒŒ์ผ ์ƒ์„ฑ์„ ์œ„ํ•ด ๋ณ„๋„์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ๋‚ด๋ถ€์— ๋ชจ๋“ˆ์ฒ˜๋Ÿผ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

main ํ•˜์œ„์— frontend๋ผ๋Š” ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ , ํ„ฐ๋ฏธ๋„์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

$ npm init

 

์œ„ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์ดˆ๊ธฐ Node.js ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

 

{
  "name": "frontend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Neon K.I.D",
  "license": "MIT"
}

 

๊ทธ๋Ÿฌ๋ฉด ์œ„์™€ ๊ฐ™์ด package.json ํŒŒ์ผ์ด ๋งŒ๋“ค์–ด์ง€๋Š”๋ฐ, ์—ฌ๊ธฐ์— ์šฐ๋ฆฌ๋Š” tailwindcss๋ฅผ ๋””ํŽœ๋˜์‹œ๋กœ ์ถ”๊ฐ€ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

$ yarn add tailwindcss --devโ€‹

 

yarn ํ˜น์€ npm ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์—ฌ tailwindcss๋ฅผ ๋””ํŽœ๋˜์‹œ๋กœ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค. 

 

๊ทธ๋Ÿฌ๋ฉด ์œ„์™€ ๊ฐ™์ด devDependencies์— tailwindcss๊ฐ€ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ , scripts ํ•˜์œ„์— build ๋ช…๋ น์–ด๋ฅผ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค. npm, yarn ๋“ฑ์œผ๋กœ build ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ–ˆ์„ ๋•Œ ์ตœ์ข… CSS ๊ฒฐ๊ณผ๋ฌผ์ด Spring MVC์˜ ์ •์  ํŒŒ์ผ์— ์ €์žฅ๋˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.

 

$ tailwindcss init

 

tailwindcss init ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์—ฌ tailwind.config.js ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ content์— ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๋ฉด tailwindcss๊ฐ€ ์ ์šฉ๋  ๊ฒฝ๋กœ๊ฐ€ thymeleaf ํ…œํ”Œ๋ฆฟ ์—”์ง„์— ๋งž์ถฐ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

 

์‚ฌ์šฉํ•  CSS ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‚˜์—ดํ•ด์ค๋‹ˆ๋‹ค.

 

$ yarn buildโ€‹

 

์ด์ œ build ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜๋ฉด resources/static/css/main.css ํŒŒ์ผ์ด ์ƒ์„ฑ๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

index.html์— ํ…œํ”Œ๋ฆฟ ์—”์ง„ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ link ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑ๋œ CSS๋ฅผ ์ ์šฉํ•˜๋ฉด Tailwind CSS๋„ ์ž…๋งž๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์ด๋ฅผ Spring boot ์ „์ฒด ํ”„๋กœ์ ํŠธ ๋นŒ๋“œ์‹œ ๊ฐ™์ด ์ ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์˜ ๋งํฌ๋ฅผ ํ†ตํ•ด Gradle์— node ํ™˜๊ฒฝ์„ ๊ตฌ์„ฑํ•˜๊ณ , ๋นŒ๋“œํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

[Spring boot] Node Gradle์„ ์ด์šฉํ•˜์—ฌ Spring ํ”„๋กœ์ ํŠธ์™€ Node ํ”„๋กœ์ ํŠธ ๋ถ™์ด๊ธฐ

Spring boot๋ฅผ ์ด์šฉํ•˜์—ฌ ์›น ํŽ˜์ด์ง€๋ฅผ ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” REST API ์„œ๋ฒ„๋กœ ๋ฐฑ์—”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , ํŽ˜์ด์ง€๋Š” ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง(SSR)์„ ์ด์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ์ˆ ์€ ์•„๋ž˜์˜ 2๊ฐ€์ง€ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•ฉ

blog.neonkid.xyz

 

 

 

๋งˆ์น˜๋ฉฐ...

์•„์ฃผ ๊ฐ„๋‹จํ•˜๊ฒŒ ํƒ€์ž„๋ฆฌํ”„์™€ HTMX๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค. Spring ํ”„๋กœ์ ํŠธ๋กœ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ์–ด๋Š ์ •๋„ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์—ญ๋Ÿ‰์ด ๋˜์‹œ๋Š” ๋ถ„๋“ค์ผํ…Œ๋‹ˆ HTMX๋ฅผ ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ๋งŒ ๊ฐ„๋‹จํžˆ ์•ˆ๋‹ค๋ฉด ์‰ฝ๊ฒŒ ๋ฐฑ์˜คํ”ผ์Šค์™€ ์›นํŽ˜์ด์ง€๋ฅผ ๊ฐœ๋ฐœํ•ด ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๊ฐœ์ธ์ ์œผ๋กœ HTMX๋ฅผ ์‚ฌ์šฉํ•ด ๋ณธ ๊ฒฐ๊ณผ ๋ณต์žกํ•œ SPA๋ฅผ ์ด์šฉํ–ˆ์„ ๋•Œ๋ณด๋‹ค ๊ฐ„๋‹จํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“œ๋Š” ๋ฐ ๊ฐœ๋ฐœ์˜ ์‹œ๊ฐ„์  ๋น„์šฉ์„ 1.5๋ฐฐ ์ •๋„ ๊ฐ์†Œ์‹œํ‚ฌ ์ˆ˜ ์žˆ์—ˆ์œผ๋ฉฐ ํŠนํžˆ webpack ๋“ฑ์˜ ๋นŒ๋“œ ๋„๊ตฌ ์—†์ด ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— CI/CD๋กœ ๊ฒ€์ฆ์ด๋‚˜ ๋ฐฐํฌ๋ฅผ ํ•˜๋Š” ๋ฐ ์žˆ์–ด์„œ๋„ ์‹œ๊ฐ„ ๋น„์šฉ์ด ๊ฝค ๋‹จ์ถ•๋  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ, webpack, vite ๋“ฑ์˜ ๋นŒ๋“œ ๋„๊ตฌ๋กœ ์›น ํŽ˜์ด์ง€๋ฅผ ๋นŒ๋“œํ•˜๋Š” ๋ฐ ๋„ˆ๋ฌด ๋งŽ์€ ์‹œ๊ฐ„์ด ์†Œ๋ชจ๋˜๊ณ , ๊ฒŒ๋‹ค๊ฐ€ ๊ทธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ฐฑ์˜คํ”ผ์Šค ๋‚ด์ง€ ๊ฐ„๋‹จํ•œ ์›นํŽ˜์ด์ง€๋ผ๋ฉด HTMX๋Š” ์ตœ๊ณ ์˜ ์„ ํƒ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ์–ด ๋ณด์ž…๋‹ˆ๋‹ค.

 

๋ฐ˜์‘ํ˜•
TAGS.

Tistory Comments