JavaRush /Java Blog /Random-KO /์ปจํ€˜์ŠคํŠธ ์Šคํ”„๋ง ๋ถ€์ธ 
Surplus
๋ ˆ๋ฒจ 37
ะœะพัะบะฒะฐ

์ปจํ€˜์ŠคํŠธ ์Šคํ”„๋ง ๋ถ€์ธ 

Random-KO ๊ทธ๋ฃน์— ๊ฒŒ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค
์ข‹์€ ํ•˜๋ฃจ ๋˜์„ธ์š”, ๋…์ž ์—ฌ๋Ÿฌ๋ถ„! ๊ทธ๋ฆฌ๊ณ  ๋น„๋ก ๊ฑฐ์ฐฝํ•œ ์ด๋ฆ„์ด Spring Boot ๊ฐœ๋ฐœ์— ๋Œ€ํ•œ ์ฒซ ๋งŒ๋‚จ์— ๋Œ€ํ•œ ์†Œ๋ฐ•ํ•œ ์ฃผ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ฒŒ ๋œ ์ฃผ๋œ ์ด์œ ์˜€์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋งŒ๋‚˜์„œ ๋ฐ˜๊ฐ‘์Šต๋‹ˆ๋‹ค. ์ €๋Š” JavaRush ํฌํ„ธ์—์„œ ์ธํ„ด์‹ญ ์ž…๋ฌธ ๊ณผ์ œ๋ฅผ ์™„๋ฃŒํ•œ ๊ฒฝํ—˜์„ ๊ณต์œ ํ•˜๊ณ , ์ถ•์ ๋œ ์ง€์‹์˜ ๊ฐ•์ ์„ ํ…Œ์ŠคํŠธํ•˜๋ ค๋Š” ์™„์ „ํžˆ ํ‰๋ฒ”ํ•œ ๊ธฐ์ˆ  ๋Œ€ํ•™์ƒ์˜ ์ž…์žฅ์—์„œ ๊ฐœ์š”๋ฅผ ์ œ์‹œํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ปจํ€˜์ŠคํŠธ ์Šคํ”„๋ง ๋ถ€์ธ  - 1์ €๋Š” ์ฒจ๋ถ€๋œ ์ฝ”๋“œ๋‚˜ ์‚ฌ๊ณ ๋ฐฉ์‹์— ๋ฌด๋ก€ํ•จ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ๊ฒฐ์ฝ” ๋ถ€์ •ํ•˜์ง€ ์•Š์œผ๋ฉฐ, ๊ฑด์„ค์ ์ธ ๋น„ํŒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด '๋ถ€๋‹ด'์ด ์žˆ๊ธฐ์— ์ „๋ฌธ์ ์ธ ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐœ์ „ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”์šฑ์ด ๋‚˜๋Š” ์ฃผ์–ด์ง„ ์กฐ๊ฑด์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ "๋งŒ๋ณ‘ ํ†ต์น˜์•ฝ"์ธ ์ฒ™ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์˜๋„์ ์œผ๋กœ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฐœ๋ณ„ ๋ถ€๋ถ„์„ ์ƒ๋žตํ•˜์—ฌ ์‹ ๊ฒฝ๊ณ„์— ์‚ฌ์†Œํ•œ ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š๊ณ  ๋น„๊ต์  ๋ณต์žกํ•œ ์ฃผ์ œ์— ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ž„์„ ๋‚จ๊ฒจ ๋‘ก๋‹ˆ๋‹ค. ๋‹น์—ฐํ•œ ์‚ฌ์‹ค์„ ๋ถ€์ •ํ•˜๋Š” ๊ฒƒ์€ ๋ฌด๋ชจํ•œ ์ผ์ž…๋‹ˆ๋‹ค. ๋‚˜์—๊ฒŒ๋Š” ํž˜๋“ค์—ˆ๊ณ  ์–ด๋Š โ€‹โ€‹์ˆœ๊ฐ„๊นŒ์ง€ ๋ช…ํ™•ํ•œ ๊ฒƒ์ด ์ „ํ˜€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ž‘์—…์— ๋Œ€ํ•œ ์ฒซ ๋งŒ๋‚จ์—์„œ ๋น„์Šทํ•œ ๊ฐ์ •์„ ๊ฒฝํ—˜ํ–ˆ๋‹ค๋ฉด "ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!" Thymeleafํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉ ํ•˜๊ณ  query๋“ค์–ด์˜ค๋Š” ์ •๋ณด ๋ฐฐ์—ด์„ ํ•„ํ„ฐ๋งํ•˜๊ธฐ ์œ„ํ•ด ๋กœ์ปฌ MySQL ์„œ๋ฒ„์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ธํ„ด์‹ญ ์ž…ํ•™ ํ…Œ์ŠคํŠธ์˜ ๊ฐ„๋‹จํ•œ ๋น„์œ ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Spring Boot์—์„œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ž‘์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค . ๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

์Šคํ”„๋ง ๋ถ€ํŠธ. ์–ด๋–ค ๋™๋ฌผ์ด๊ณ  ์–ด๋–ป๊ฒŒ ์š”๋ฆฌํ•˜๋‚˜์š”?

๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ, ์ด๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์—์„œ ๊ท€์ค‘ํ•œ ์‹œ๊ฐ„์„ ์ ˆ์•ฝํ•˜๊ณ , ํƒ€์‚ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ง์ ‘ ์—ฐ๊ฒฐํ•˜๊ณ , ์ธ์ƒ์ ์ธ ๋งคํ•‘ ์บ”๋ฒ„์Šค์™€ ์„œ๋ธ”๋ฆฟ์„ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก ํ•ด์ฃผ๋Š” Pivotel ์˜ ํƒ์›”ํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. IntelliJ IDEA Ultimate Edition (ํŒŒ์ผ - ์ƒˆ - ํ”„๋กœ์ ํŠธ... - Spring Initializr) ์— ํ†ตํ•ฉ๋˜๊ฑฐ๋‚˜ start.spring.io ์›น ์„œ๋น„์Šค ์— ์žˆ๋Š” Spring ์ดˆ๊ธฐํ™” ๋นŒ๋”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ๋ฒ”์œ„์—์„œ ํฌํ•จํ•  ํŒจํ‚ค์ง€๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.
์ปจํ€˜์ŠคํŠธ ์Šคํ”„๋ง ๋ถ€์ธ  - 2
์ œ์‹œ๋œ ๊ธฐ์ˆ  ์‚ฌ์–‘์— ๋”ฐ๋ผ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํ‘œ์ค€์ธ ์‹ ์‚ฌ ์„ธํŠธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค .
  • WEB ๋Š” ํ‘œ์ค€ ์ฃผ์†Œ localhost:8080์˜ ๋กœ์ปฌ Apache Tomcat ์„œ๋ฒ„์™€ ๋ฒ”์šฉ Spring MVC ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํฌํ•จํ•˜์—ฌ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค.

  • DevTools - ์ปดํŒŒ์ผ๋œ ์ฝ”๋“œ๋‚˜ ํ…œํ”Œ๋ฆฟ์—์„œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๊ฐ์ง€๋˜๋ฉด ํ•ซ JVM์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋น ๋ฅด๊ฒŒ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์„ ํƒํ•œ ์—”์ง„์ด ํ”„๋กœ์ ํŠธ์— ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉด Thymeleaf๊ฐ€ ์บ์‹œ๋ฅผ ์ง€์šฐ์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

  • JPA ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์— ํ•„์š”ํ•œ ๊ธฐ์ˆ ์ด๋ฉฐ Java ๊ฐ์ฒด์˜ ๊ฐ์ฒด ๊ด€๊ณ„ํ˜• ๋งคํ•‘์„ ์ œ๊ณตํ•˜๊ณ  ์—”ํ„ฐํ‹ฐ๋ฅผ ๊ด€๋ฆฌ, ์ €์žฅ ๋ฐ ๊ฒ€์ƒ‰ํ•˜๊ธฐ ์œ„ํ•œ API(์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ Hibernate )๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • Thymeleaf(Mustache, AngularJS, Vaadin ๋“ฑ) - ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ๊ฐํ™”๋ฅผ ์œ„ํ•œ ํ…œํ”Œ๋ฆฟ ์—”์ง„ HTML์˜ ์›๋ฆฌ์— ๋Œ€ํ•œ ์ƒ๋Œ€์ ์ธ ์นœ์ˆ™ํ•จ ๋•๋ถ„์— ๋‚˜๋Š” ์–ธ์–ด๋ฅผ ์„ธ๊ณ„์˜ ์ดˆ์„์œผ๋กœ ๋Œ์–ด์˜ฌ๋ฆฐ Thymeleaf๋ฅผ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

  • MySQL - Java ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•ด SQL ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ตœ์ข… ์„ ํƒํ•˜๊ณ  ์ƒ์„ฑํ•œ ํ›„์—๋Š” ์ถ”๊ฐ€ ์ฑ„์šฐ๊ธฐ๊ฐ€ ์ค€๋น„๋œ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์žˆ๋Š” ์ผ๋ฐ˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค. CSS ๊ทธ๋ž˜ํ”ฝ ์Šคํƒ€์ผ, ํ‘œ์ค€ HTML ํŽ˜์ด์ง€ ๋˜๋Š” JavaScript ๊ธฐ๋Šฅ ๋“ฑ ์‹œ๊ฐ์  ๋ถ€๋ถ„๊ณผ ์ƒํ˜ธ ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•œ ์กฐ๊ฐ์€ "๋ฆฌ์†Œ์Šค"์— ์žˆ์–ด์•ผ ํ•˜๋ฉฐ ๊ทธ์— ๋”ฐ๋ผ ๋ฐฑ์—”๋“œ ๊ตฌ์„ฑ ์š”์†Œ๋Š” "java"์— ๋ฐฐ์น˜๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ์™€ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์˜ ์ข…์†์„ฑ์„ ์ €์žฅํ•˜๋Š” ๋ฃจํŠธ ๋ฒ”์œ„์˜ pom.xml ํŒŒ์ผ์—๋„ ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ํŒจํ‚ค์ง€๋กœ ๊ธฐ๋Šฅ์„ ๋”์šฑ ํ™•์žฅํ•˜๊ณ  ์‹ถ๊ฑฐ๋‚˜, ๋ถˆํ•„์š”ํ•œ ๊ฒƒ์„ ์ œ๊ฑฐํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด <dependencies></dependencies>๋น„์Šทํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ํƒœ๊ทธ ๊ฐ„ ์กฐ์ž‘์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ปจํ€˜์ŠคํŠธ ์Šคํ”„๋ง ๋ถ€์ธ  - 3

์œ„๋Œ€ํ•œ ๋ฏธ๋ž˜๋ฅผ ํ–ฅํ•œ ์ฒซ ๊ฑธ์Œ

๋‹ค์Œ์œผ๋กœ ๋‹ค์†Œ ํฅ๋ฏธ๋กญ๊ณ  ์ƒ๋‹นํžˆ ๋…ผ๋ฆฌ์ ์ธ ์งˆ๋ฌธ์ด ์ œ๊ธฐ๋ฉ๋‹ˆ๋‹ค. โ€œ์ด์ œ ๋ฌด์—‡์„ ํ•ด์•ผ ํ• ๊นŒ์š”? ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋‚˜์š”? ์ด ํ”„๋กœ๊ทธ๋žจ์€ ๋ชจ๋ธ-๋ทฐ-์ปจํŠธ๋กค๋Ÿฌ์˜ ์›์น™์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์—ฐ๊ฒฐ๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(๋ชจ๋ธ)์—์„œ ์—”ํ„ฐํ‹ฐ ์ฝ๊ธฐ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ์ปจํŠธ๋กค(๋ทฐ)์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์˜ ํ†ต์‹ ๊ณผ ์ „์†ก๋œ ์š”์ฒญ์— ๋”ฐ๋ฅธ ์ž‘์—… ์‹คํ–‰์€ ์ปจํŠธ๋กค๋Ÿฌ ๋•๋ถ„์— ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ง€์†์ ์ธ ๋ฐœ์ „์„ ์œ„ํ•œ ๊ธฐ์ค€์ ์ด ๋˜๋Š” ํ•ต์‹ฌ ์š”์†Œ์˜ ์ฐฝ์ถœ์ž…๋‹ˆ๋‹ค. ๋ฏธ๋„๋Ÿฌ์šด ๊ฒฝ์‚ฌ๋ฅผ ํ”ผํ•˜๊ณ  ์ž‘์—… ํ˜„์žฅ์—์„œ ๋™๋ฃŒ๋“ค์˜ ์กด๊ฒฝ์‹ฌ์„ ์œ ์ง€ํ•˜๋ ค๋ฉด ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ ์ ˆํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋ฐฐ์น˜ํ•˜๊ณ (์˜ˆ: ์ปจํŠธ๋กค๋Ÿฌ ํŒŒ์ผ์„ "java" ๋ถ„๊ธฐ์˜ ์ปจํŠธ๋กค๋Ÿฌ ํด๋”์— ๋ฐฐ์น˜) ์กฐ์‹ฌ์Šค๋Ÿฝ๊ฒŒ ๋ณด๊ด€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ง์žฅ์—์„œ ์ฃผ๋ฌธํ•˜์‹ญ์‹œ์˜ค.

๋ณธ์งˆ์€ ํฐ ๋ฉ”์ปค๋‹ˆ์ฆ˜์˜ ์ž‘์€ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค

์ฆ‰, ๋ฌธ์ œ์— ์„ค์ •๋œ ์กฐ๊ฑด์— ๋”ฐ๋ฅธ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ๋…ผ์˜ ์ฃผ์ œ์—์„œ ๋ฒ—์–ด๋‚˜ ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ๋กœ ๋Œ์•„๊ฐ€์„œ, ์šฐ๋ฆฌ๋Š” ์ž‘์—…๋“ค ์‚ฌ์ด์— ์ตœ์†Œํ•œ์˜ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์ž์‹ ์žˆ๊ฒŒ ์ฃผ์žฅํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ถ”๊ฐ€ ๊ฒ€ํ† ์—์„œ๋Š” ํ‰๊ท ์ ์ธ ๊ฐœ๋…์„ ๊ณ ์ˆ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ํฌํ•จํ•˜์—ฌ ๋…ธํŠธ๋ถ์— ๋ฉ”๋ชจ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
  • ์ผ๋ฐ˜ ํ๋ฆ„์—์„œ ์œ„์น˜๋ฅผ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•œ ์‹๋ณ„ ๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค.
  • ํŠน์ • ๋ฌธ์ž ์ˆ˜๋กœ ๊ตฌ์„ฑ๋œ ๋ฌธ์ž ๋ฉ”์‹œ์ง€
  • ์‚ฌ์šฉ์ž๊ฐ€ ์ผ๋ฐ˜ ๋ชฉ๋ก์— ์ถ”๊ฐ€ํ•œ ๋‚ ์งœ์ž…๋‹ˆ๋‹ค.
  • "์™„๋ฃŒ ์—ฌ๋ถ€"("์ฝ๊ธฐ ์—ฌ๋ถ€")๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ถ€์šธ ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ "entity"๋ผ๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ์— Note ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์ ์ ˆํ•œ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
@Entity
public class Note {

   @Id
   @GeneratedValue
   private int id;
   private String message;
   private Date date;
   private boolean done;

   public Note() {
   }

   public Note(String message) {
       this.message = message;
       this.date = new Date();
       this.done = false;
   }
}
์ด๋ก ์  ์ž…์žฅ์—์„œ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ ๋” ์ž˜ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ํ† ๋ก  ์ฃผ์ œ์—์„œ ๋˜ ๋‹ค๋ฅธ ์ผํƒˆ. Spring์˜ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์˜ ์—ฐ๊ฒฐ์€ ์ฃผ์„์œผ๋กœ ์ง€์ •๋ฉ๋‹ˆ๋‹ค . ๊ฐ ์ฃผ์„์€ ๋ฉ”์ปค๋‹ˆ์ฆ˜์—์„œ ํŠน์ • ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•˜๊ณ  "@" ๊ธฐํ˜ธ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฐ์ฒด ์•ž์˜ ํŠน์ˆ˜ ํฌ์ธํ„ฐ์ž…๋‹ˆ๋‹ค. @Entity ์ฃผ์„์€ Spring Boot์— ํ›„์† ํด๋ž˜์Šค ๋ฐ์ดํ„ฐ๊ฐ€ "Entity"์— ์†ํ•จ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ @Id ๋ฐ @GeneratedValue๋Š” ์ •๋ณด ๋ฐฐ์—ด์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋ฐ˜๋ณต์ž๊ฐ€ ์ž๋™ โ€‹โ€‹์ƒ์„ฑ๋˜๋Š” ์‹๋ณ„์ž๋กœ ์„ ํƒํ•œ ํ•„๋“œ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์‹œ๊ฐ์  ํ˜•์‹์˜ ๊ฐ„๊ฒฐ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด ํ‘œ์ค€ Getter ๋ฐ Setter ์ถ”๊ฐ€๋ฅผ ์˜๋„์ ์œผ๋กœ ์ƒ๋žตํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์œผ๋กœ ๋ ˆ์ฝ”๋“œ ์ €์žฅ์„ ์œ„ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์˜ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค. ๊ตํ™˜ ์ฒด์ธ์˜ ์—ฐ๊ฒฐ ์š”์†Œ์ธ "repository" ๋””๋ ‰ํ„ฐ๋ฆฌ์— NoteRepository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ฐ€์žฅ ๋งŽ์€ ๊ฒƒ์„ ์ƒ์†ํ•ฉ๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ์ž‘์—…์— ์ ํ•ฉํ•œ ์ €์žฅ์†Œ๋กœ, ์•ก์„ธ์Šคํ•  ์ €์žฅ๋œ ์—”ํ„ฐํ‹ฐ์™€ ์ •์ˆ˜ ๋ฐ˜๋ณต์ž๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
public interface NoteRepository extends JpaRepository<Note, Integer> {
}
์‚ฌ์‹ค ๊ทธ๊ฒŒ ์ „๋ถ€์ž…๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•˜๊ณ  ๊ฐ„๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ Spring Boot๋Š” ์ƒ์„ฑ๋œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์ƒํ˜ธ ์ž‘์šฉ์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์–‘ํ•œ ์‹คํ–‰ ๊ฐ€๋Šฅ์„ฑ์„ ์ง€๋‹Œ ๋ ˆ๊ฑฐ์‹œ ์ €์žฅ์†Œ ์œ ํ˜•์ด ์ƒ๋Œ€์ ์œผ๋กœ ๋งŽ์Šต๋‹ˆ๋‹ค. JpaRepository๋Š” ์‚ฌ๋‹ค๋ฆฌ์˜ ๋งจ ์œ„์— ์žˆ์œผ๋ฉฐ ๊ทธ ์•„๋ž˜์˜ CrudRepository ๋ฐ PageAndSortingRepository๋ฅผ ํฌํ•จํ•˜์—ฌ ๊ฐ€์žฅ ํฐ ์ž ์žฌ๋ ฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ์ด์ƒ ์ง„ํ–‰ํ•˜์ง€ ์•Š๊ณ  ์ฃผ์ œ์—์„œ ๋ฒ—์–ด๋‚˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ผ๋ถ€ ๋ฏธ๋ฌ˜ํ•จ์€ Pivotel ์›น ์‚ฌ์ดํŠธ์˜ ๊ธฐ์ˆ  ๋ฌธ์„œ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธก์—์„œ ๋ฐ์ดํ„ฐ ์ด๋ฏธ์ง€๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ํ†ต์‹  ๋ฐฉ๋ฒ•์„ ์ง€์ •ํ•œ ํ›„ ๊ณต์‹ ๊ฐœ๋ฐœ์ž๊ฐ€ ์–ด์…ˆ๋ธ”๋ฆฌ๋กœ ๋ฐ์Šคํฌํ†ฑ ํ”Œ๋žซํผ์— ๋ฏธ๋ฆฌ ์„ค์น˜๋œ ์ ์ ˆํ•œ ์™ธ๋ถ€ ํ™˜๊ฒฝ์ธ โ€œMySQL Workbenchโ€์—์„œ MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋กœ์ปฌ ์„œ๋ฒ„ ์ƒ์„ฑ์„ ์œ„ํ•œ ์ถ”๊ฐ€ ํŒจํ‚ค์ง€ ํฌํ•จ:
์ปจํ€˜์ŠคํŠธ ์Šคํ”„๋ง ๋ถ€์ธ  - 4
๋‹ค์Œ์œผ๋กœ ๋ฉ”์ธ ์ฐฝ์—์„œ ํ˜„์žฌ ๋กœ์ปฌ ์„œ๋ฒ„๊ฐ€ ์žˆ๋Š” ์•„์ด์ฝ˜์„ ํด๋ฆญํ•œ ํ›„ ํ™˜๊ฒฝ์˜ ์ง€์‹œ์— ๋”ฐ๋ผ ์—”ํ„ฐํ‹ฐ(์ฐธ๊ณ )์˜ ํ•„๋“œ์— ๋”ฐ๋ผ ํ…Œ์ด๋ธ” ๋‹ค์ด์–ด๊ทธ๋žจ์„ ์ƒ์„ฑํ•˜๊ณ  ์ ์ ˆํ•œ ๋ฐ์ดํ„ฐ๋กœ ์ฑ„์›๋‹ˆ๋‹ค. ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๋‹ฌ์„ฑํ•˜๋ ค๋ฉด ์‹œ๊ธ‰ํžˆ ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•œ MySQL ๋ฐฉ์–ธ์˜ ๋ฏธ๋ฌ˜ํ•จ์„ ๋ณ„๋„๋กœ ๋ช…ํ™•ํžˆ ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ณ„๋„์˜ ๋ถ€์šธ ์œ ํ˜•์€ ์—†์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์š”์ฒญ ์ฒ˜๋ฆฌ ์ž‘์—…์€ "true" ๋˜๋Š” "false"๋ฅผ ๊ฐ๊ฐ ๋น„ํŠธ ๊ฐ’ "1" ๋˜๋Š” "0"์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ๋‚ ์งœ๋Š” ์ „์ ์œผ๋กœ Timestamp ์œ ํ˜•์œผ๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ์ฝ”์–ด์— ์นœ์ˆ™ํ•œ Date๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๋‹ฌ๋ ฅ์—์„œ์˜ ์œ„์น˜์—๋งŒ ์ œํ•œํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์Šคํ”„๋ง ๋ถ€์ธ  ์ •๋ณต - 5
์ค€๋น„ ๋‹จ๊ณ„๋ฅผ ๋งˆ์ง€๋ง‰์œผ๋กœ ์™„๋ฃŒํ•œ ํ›„ ๋„๊ตฌ ๋ชจ์Œ์—์„œ "๋ฒˆ๊ฐœ" ์•„์ด์ฝ˜์„ ํด๋ฆญํ•˜์—ฌ ๋กœ์ปฌ ์„œ๋ฒ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” "MySQL Workbench"๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ์ •๋ณด ์ถ”๊ฐ€๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์™„๋ฃŒ๋˜๋ฉด ํ˜„์žฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌ์„ฑ์„ application.properties(์ผ๋ฐ˜์ ์œผ๋กœ "resources" ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์žˆ์Œ)์— ์ถ”๊ฐ€ํ•˜์—ฌ ์ž์‹  ์žˆ๊ฒŒ ๊ธฐ๋ณธ IDE๋กœ ๋Œ์•„๊ฐ€ ๊ฐœ๋ฐœ์„ ๊ณ„์†ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
๋งˆ์ง€๋ง‰์œผ๋กœ ์ฃผ์„์„ ์‚ฌ์šฉํ•˜์—ฌ Note ์—”ํ„ฐํ‹ฐ๋ฅผ MySQL์— ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค. @Table์€ ์„ ํƒํ•œ ์ด๋ฆ„๊ณผ ์Šคํ‚ค๋งˆ๋ฅผ ๊ฐ–๋Š” ํ…Œ์ด๋ธ”์˜ ์‚ฌ์šฉ์„ ๋‚˜ํƒ€๋‚ด๊ณ , @Column์€ ๋ณ€์ˆ˜๊ฐ€ ํŠน์ • ํ•„๋“œ์— ์†ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
@Entity
@Table(name = "test", schema = "test", catalog = "")
public class Note {

   @Id
   @GeneratedValue
   private int id;
   @Column(name = "message")
   private String message;
   @Column(name = "date")
   private Date date;
   @Column(name = "done")
   private boolean done;

   public Note() {
   }

   public Note(String message) {
       this.message = message;
       this.date = new Date();
       this.done = false;
   }
}

๋ณด๊ธฐ ๋˜๋Š” ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค

์•„์•„, ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์•ˆ์ „ํ•˜๊ฒŒ ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. "์ด๋ก ์  ๋˜๋Š” ์‹ค๋ฌด์  ์ง€์‹์ด ์ „ํ˜€ ์—†์œผ๋ฉด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์‹œ๊ฐํ™”๊ฐ€ ์ฃผ์š” ๊ฑธ๋ฆผ๋Œ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค." ์†”์งํžˆ ๋งํ•ด์„œ ํ”„๋ก ํŠธ ์—”๋“œ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ „์ฒด ์ž‘์—…๋Ÿ‰์—์„œ ์—„์ฒญ๋‚œ ์–‘์„ ์ฐจ์ง€ํ–ˆ์œผ๋ฉฐ ์˜ค๋žœ ์‹œ๊ฐ„ ๋™์•ˆ ์ž์‹ ์žˆ๊ฒŒ ๋‚ด ์‹ ๊ฒฝ์„ ์‡ ์•ฝํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Thymeleaf์˜ ๋†€๋ผ์šด ๋‹จ์ˆœ์„ฑ ๋•๋ถ„์— ์ผ๋ จ์˜ ๋งคํ˜น์ ์ธ ํŒจ๋ฐฐ ํ›„์— ์ ์ ˆํ•œ ํƒ€ํ˜‘์ ์„ ์ฐพ๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ–ˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ๊ฐœ๋…์€ ๋น„์Šทํ•œ ์ž…์žฅ์„ ๊ณ ์ˆ˜ํ•˜์ง€๋งŒ ์„ ํƒ๋œ ์—”์ง„ ์‚ฌ์šฉ์˜ ๋ณต์žก์„ฑ์— ๋Œ€ํ•ด ์ถ”๊ฐ€ ๋…ผ์˜๊ฐ€ ์ด๋ฃจ์–ด์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฃผ์š” ๊ธฐ์ˆ ์€ ๊ฐ€์žฅ ์ˆœ์ˆ˜ํ•œ HTML์„ ์‚ฌ์šฉํ•˜๊ณ  ๊ฐœ๋ณ„ ์กฐ๊ฐ์—์„œ ์ตœ์ข… ๋””์Šคํ”Œ๋ ˆ์ด๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ๋™์ผํ•œ ์„น์…˜์ด ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐ˜๋ณต๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. UI ์•„ํ‚คํ…์ฒ˜๊ฐ€ ์ปจํŠธ๋กค(์ƒˆ ํ•ญ๋ชฉ ์ถ”๊ฐ€, ๊ธฐ๋ณธ ํŽ˜์ด์ง€๋กœ ๋Œ์•„๊ฐ€๊ธฐ)์ด ์žˆ๋Š” ํƒ์ƒ‰ ๋ชจ์Œ๊ณผ ๋ฉ”๋ชจ๊ฐ€ ์ถ”๊ฐ€๋œ ์‹œ๊ฐ„์„ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฆ„์ฐจ์ˆœ(ASC)์œผ๋กœ ์ •๋ ฌ๋œ ์—”ํ„ฐํ‹ฐ๋ฅผ ํ‘œ์‹œํ•˜๋Š” ๋™์  ํ…Œ์ด๋ธ”๋กœ ๊ตฌ์„ฑ๋œ ๊ธฐ๋ณธ ํŽ˜์ด์ง€๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ๊ฐ์†Œ(DESC) ๋ฐฉํ–ฅ. ๋ชจ๋“  ๊ธฐ๋ก์„ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์„ ํ‘œ์ค€ ์œ„์น˜๋กœ ์‚ผ๊ฒ ์Šต๋‹ˆ๋‹ค. ์„ ํƒํ•œ ํ…œํ”Œ๋ฆฟ ์—”์ง„์˜ ๊ณ„์ธต์  ์ •์ฑ…์— ๋”ฐ๋ผ ๊ตฌ์„ฑ ์š”์†Œ ์‹œ๊ฐํ™” ์š”์†Œ๋Š” "resources" ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ "templates" ๋ถ„๊ธฐ์— ์œ„์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€๋กœ ์กฐ์ž‘ํ•  ๋•Œ ์ œ์‹œ๋œ ์กฐ๊ฑด์ด ๊ณ ๋ ค๋ฉ๋‹ˆ๋‹ค. html5 ํ…œํ”Œ๋ฆฟ์— "index"(๋˜๋Š” ๊ฐœ์ธ ์ทจํ–ฅ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์ด๋ฆ„)๋ผ๋Š” ์ด๋ฆ„์˜ ๋ฉ”์ธ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/head :: head"></head>
<body>
<div class="container">
   <div th:replace="fragments/header :: header"></div>
   <div th:if="${not #lists.isEmpty(notes)}">
       <div th:replace="operations/list :: notebook"></div>
   </div>
   <div th:replace="fragments/footer :: footer"></div>
</div>
</body>
</html>
์ด์ œ ์ตœ์ข… ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ถ„์„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. Thymeleaf๋Š” ํ”„๋กœ์‹œ์ €์˜ ์‚ฌ์šฉ์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๊ณ  "th:"๋ผ๋Š” ํ‚ค์›Œ๋“œ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ‚ค์›Œ๋“œ๋Š” ์—ฌ๋Š” <html> ํƒœ๊ทธ์— ๋ฐ˜๋“œ์‹œ ํฌํ•จ๋˜์–ด์•ผ ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋งํฌ์ž…๋‹ˆ๋‹ค.
<div th:if="${not #lists.isEmpty(notes)}">
"if" ์ž‘์—…์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•๊ณผ ์™„์ „ํžˆ ๋‹ค๋ฅด์ง€ ์•Š์œผ๋ฉฐ ์ถ”๊ฐ€ ํ‘œ์‹œ๋ฅผ ์œ„ํ•ด ๊ฐœ์ฒด๊ฐ€ ์žˆ๋Š”์ง€ ๋“ค์–ด์˜ค๋Š” "notes" ์†์„ฑ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋ธ๊ณผ ์‹œ๊ฐํ™”์˜ ์ƒํ˜ธ ์ž‘์šฉ์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜์—ฌ ์ปจํŠธ๋กค๋Ÿฌ ์‚ฌ์šฉ๊ณผ ์ฃผ์ œ์˜ ์ค‘๋ณต์„ ๋ณ„๋„๋กœ ์–ธ๊ธ‰ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์•ž์œผ๋กœ๋Š” ๋ชจํ˜ธํ•œ ์ˆœ๊ฐ„์ด ๋งŽ์ด ์ƒ๊ธธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์›ํ•˜์‹œ๋ฉด ๋Œ์•„๊ฐ€์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
<head th:replace="operations/list :: notebook"></head>
"๊ต์ฒด" ์ž‘์—…์€ "์Šคํ…" ๋˜๋Š” ํ™œ์„ฑ ๋ธ”๋ก์„ ํ˜„์žฌ ๋˜๋Š” ๋ณ„๋„ ํŽ˜์ด์ง€์—์„œ ์„ ํƒํ•œ ์กฐ๊ฐ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ํ›„์ž์˜ ๊ฒฝ์šฐ๋Š” ์˜ˆ์—์„œ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ด€์ฐฐ๋ฉ๋‹ˆ๋‹ค. โ€œOperationsโ€ ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ โ€œlist.htmlโ€์—์„œ โ€œnotebookโ€์ด๋ผ๋Š” ์กฐ๊ฐ์„ โ€œindexโ€ ํŒŒ์ผ์˜ <div></div>๋กœ ๋ณต์‚ฌํ•˜์—ฌ ์ตœ์ข… ๋Œ€์ƒ์˜ ์ฝ˜ํ…์ธ ๋ฅผ ์™„์ „ํžˆ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๊ฐ€๋Š” ๋‚ด์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
<!DOCTYPE html>
<!--suppress ALL -->
<html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:th="http://www.thymeleaf.org">

<div th:fragment="notebook">
   <table class="table table-bordered table-hover horizontal-align">
       <thead>
       <tr>
           <th style="width: 5%">#</th>
           <th style="width: 60%">Message</th>
           <th class="dropdown" style="width: 20%">Date
               <a th:href="@{'/sort/{sortDate}' (sortDate = 'ASC')}"><i class="fa fa-chevron-circle-up"></i></a>
               <a th:href="@{'/sort/{sortDate}' (sortDate = 'DESC')}"><i class="fa fa-chevron-circle-down"></i></a>
           </th>
           <th style="width: 5%">Done</th>
           <th style="width: 5%">Edit</th>
           <th style="width: 5%">Delete</th>
       </tr>
       </thead>
       <tbody>
       <tr th:each="note : ${notes}">
           <td th:text="${note.id}" style="text-align: center">#</td>
           <td th:text="${note.message}">Message</td>
           <td th:text="${#dates.format(note.date, 'EEE, d MMM yyyy HH:mm')}" style="text-align: center">Date</td>
           <td style="text-align: center">
               <i th:if="${note.done} == true" class="fa fa-plus-square-o" style="font-size:20px;color:#337ab7"></i>
               <i th:if="${note.done} == false" class="fa fa-minus-square-o" style="font-size:20px;color:#337ab7"></i>
           </td>
           <td style="text-align: center"><a th:href="@{'/edit/{id}'(id=${note.id})}"><i class="fa fa-edit" style="font-size:20px"></i></a></td>
           <td style="text-align: center"><a th:href="@{'/delete/{id}'(id=${note.id})}"><i class="fa fa-trash" style="font-size:20px"></i></a></td>
       </tr>
       </tbody>
   </table>
</div>
</html>
๊ตฌ์„ฑ์ ์ธ ๊ฐœ์š”๋กœ ๋Œ์•„๊ฐ€์„œ ํ‘œ์ค€ HTML ๊ตฌ๋ฌธ์ด๋‚˜ ์‚ฌ์šฉ๋œ ๊ทธ๋ž˜ํ”ฝ ์Šคํƒ€์ผ์„ ์ƒ๋žตํ•˜๊ณ  ํŠนํžˆ ํ…œํ”Œ๋ฆฟ ์—”์ง„ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ์ค‘์ ์„ ๋‘๊ณ  ์‚ฌ์šฉ๋œ Thymeleaf ๊ธฐ๋Šฅ์„ ์ˆœ์„œ๋Œ€๋กœ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
<div th:fragment="notebook">
"์กฐ๊ฐ" ์ž‘์—…์€ ์กฐ๊ฐ์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๊ณ  "๊ต์ฒด" ๋ช…๋ น์— ๋ธ”๋ก์˜ ๋‚ด์šฉ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€! ๋‹จ์ผ ํŽ˜์ด์ง€ ๋‚ด์—์„œ์˜ ๋‹ค์ค‘ ์‚ฌ์šฉ์€ ๊ฒฐ์ฝ” ๋ฐฐ์ œ๋˜์ง€ ์•Š์œผ๋ฉฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ ํ”„๋กœ์‹œ์ € ๋˜๋Š” ๊ธฐ๋Šฅ๊ณผ์˜ ์œ ์‚ฌ์ ์„ ๋‹ค์‹œ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค.
<a th:href="@{'/sort/{sortDate}' (sortDate = 'ASC')}">
@PostMapping ์ฃผ์„์— ๋Œ€ํ•œ ํ˜ธ์ถœ์€ "/sort/{sortDate}" ๋งคํ•‘์ด ์žˆ๋Š” ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ {sortDate}๋Š” ๋‚˜๊ฐ€๋Š” ์ •๋ ฌ ๋ฐฉํ–ฅ ์†์„ฑ์ž…๋‹ˆ๋‹ค. ๋ฐ˜๋ณต ๋ฃจํ”„์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ์š”์†Œ์˜ ์œ„์น˜์— ๋”ฐ๋ผ ๋™์ ์ธ ๋ณ€๊ฒฝ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋‹ค์Œ ๋ธ”๋ก์—์„œ๋„ ๋น„์Šทํ•œ ๋‚ด์šฉ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
<a th:href="@{'/edit/{id}'(id=${note.id})}">
<tr th:each="note : ${notes}">
๊ฐ’์„ ์—ด๊ฑฐํ•˜๋Š” ๊ฒƒ์€ Java ๊ตฌ๋ฌธ์—์„œ for ๋ธ”๋ก์„ ์นœ์ˆ™ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋ณ€์ˆ˜ "note"๋Š” ์ž…๋ ฅ ์†์„ฑ ๋ฐฐ์—ด ${notes}(์—”ํ‹ฐํ‹ฐ ๋ฐฐ์—ด)์—์„œ ํ˜„์žฌ ์š”์†Œ๋ฅผ ๊ฐ€์ ธ์™€ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋‚˜์ค‘์—. ์†”์งํžˆ ๋งํ•ด์„œ, ์šฐ๋ฆฌ๋Š” ์‹ค์ œ ์ ์šฉ ์‚ฌ๋ก€์™€ ํ•จ๊ป˜ ๊ด‘๋ฒ”์œ„ํ•œ Thymeleaf ๊ธฐ๋Šฅ์„ ๋‚˜์—ดํ•˜๋Š” ๋ณ„๋„์˜ ๊ธฐ์‚ฌ๋ฅผ ํ• ์• ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ…œํ”Œ๋ฆฟ ์—”์ง„์€ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๋ฉฐ ์ถ”๊ฐ€ ๊ตฌ๋ฌธ์˜ ์ธ์ƒ์ ์ธ ์ˆ˜ํ•˜๋ฌผ์„ ์ „ํ˜€ ๋ฐฐ์šธ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์œ„์— ์„ค๋ช…๋œ ๊ธฐ๋Šฅ์€ ๊ฐœ๋ฐœ์ž ๊ณต์‹ ์›น์‚ฌ์ดํŠธ์˜ ๊ธฐ์ˆ  ๋ฌธ์„œ์— ์„ค๋ช…๋˜์–ด ์žˆ์œผ๋ฉฐ ๋ฐฑ์—”๋“œ์™€์˜ ํ†ต์‹ ์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ž์‹ ์žˆ๊ฒŒ ๋‹ค์Œ ๋ถ€๋ถ„๊ณผ ๋งˆ์ง€๋ง‰ ๋ถ€๋ถ„์œผ๋กœ ๋„˜์–ด๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ๊ธฐ์‚ฌ ๋งˆ์ง€๋ง‰ ๋ถ€๋ถ„์— ์žˆ๋Š” ์™„์„ฑ๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ ๋งํฌ์— ์‹œ๊ฐํ™”์˜ ๋‚˜๋จธ์ง€ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ฒจ๋ถ€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์†Œ๊ทœ๋ชจ ํšŒ์‚ฌ์˜ ์ปจํŠธ๋กค๋Ÿฌ, ๊ด€๋ฆฌ์ž

"์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜์˜ ์ดˆ์„" - ์•„๋งˆ๋„ ํ”„๋กœ๊ทธ๋žจ ์ž‘์—…์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ์žˆ์–ด ์ปจํŠธ๋กค๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ค‘์š”์„ฑ์— ๋Œ€ํ•œ ๋” ์ •ํ™•ํ•œ ์„ค๋ช…์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ์—†์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์ž‘์—…์€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐ„์˜ ์—ฐ๊ฒฐ ์š”์†Œ์— ์˜ํ•ด ์ •ํ™•ํ•˜๊ฒŒ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋ธ๊ณผ ๋ทฐ. Spring Boot์˜ ์•ก์…˜ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋•๋ถ„์— ์•„๋ฌด๋Ÿฐ ๋ฌธ์ œ ์—†์ด ๋งคํ•‘ ๋ฐ GET/POST ์š”์ฒญ ๋ฉ”์„œ๋“œ๋ฅผ ์ž์‹ ์žˆ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ๋ฅผ ์ž๋™์œผ๋กœ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ ์ ˆํ•œ ์ฃผ์„์˜ ์‚ฌ์šฉ์„ ๋‹ค์‹œ ์ฐธ์กฐํ•˜์—ฌ "controllers" ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ ๋ณ„๋„ ํŒŒ์ผ์— NoteController ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
@Controller
public class NoteController {

   private NoteService service;

   @Autowired
   public void setNoteService(NoteService service) {
       this.service = service;
   }

   @GetMapping("/")
   public String list(Model model) {
       return "index";
   }
}
์ฃผ์˜ ๊นŠ๊ฒŒ ์‚ดํŽด๋ณด๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ฆฌ ์„œ๋น„์Šค ์ž‘์—…์—์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์„œ๋น„์Šค ์ถ”๊ฐ€์™€ ๊ด€๋ จ๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„์˜ ์ค‘์š”ํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์™„๋ฃŒ๋œ ์ž‘์—…์€ ์™„์ œํ’ˆ์˜ ๋‹ค์–‘์„ฑ์„ ๋†’์ด๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ํ†ต์‹  ๋ฐฉ๋ฒ•์„ ๋ณ€๊ฒฝํ•  ํ•„์š” ์—†์ด ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ธฐ๋Šฅ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ๊ด‘๋ฒ”์œ„ํ•œ ๋ฒ”์œ„๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ํ‘œ์ค€ ํ‘œํ˜„์€ ์œ ์‚ฌํ•œ ํ‘œํ˜„ ์ค‘์—์„œ ๋ˆˆ์— ๋„์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ณ„๋„์˜ ๋””๋ ‰ํ† ๋ฆฌ์— ์žˆ์œผ๋ฉฐ Spring Boot ๊ฐ์ง€๋ฅผ ์œ„ํ•œ @Service ์ฃผ์„์ด ์žˆ๋Š” ํด๋ž˜์Šค์— ์˜ํ•ด ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค.
public interface NoteService {
   Note getNoteById(Integer id);
   void saveNote(Note note);
   void updateNote(Integer id, String message, boolean done);
   void deleteNote(Integer id);
   List<Note> findAll();
}

@Service
public class NoteServiceImpl implements NoteService{

   private NoteRepository repository;

   @Autowired
   public void setProductRepository(NoteRepository repository) {
       this.repository = repository;
   }

   @Override
   public Note getNoteById(Integer id) {
       return repository.findOne(id);
   }

   @Override
   public void saveNote(Note note) {
       repository.save(note);
   }

   @Override
   public void updateNote(Integer id, String message, boolean done) {
       Note updated = repository.findOne(id);
       updated.setDone(done);
       updated.setMessage(message);
       repository.save(updated);
   }

   @Override
   public void deleteNote(Integer id) {
       repository.delete(id);
   }

   @Override
   public List<Note> findAll() {
       return repository.findAll();
   }
}
์ปจํŠธ๋กค๋Ÿฌ ๊ฒ€ํ† ๋กœ ๋Œ์•„๊ฐ€์„œ Spring Boot ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ณต์žกํ•œ ๊ณผ์ •์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. @Autowired ์ฃผ์„์€ ์„œ๋น„์Šค๋ฅผ ์ ์ ˆํ•œ ์œ ํ˜•์˜ ์ง€์ •๋œ ๋ณ€์ˆ˜์— ์ž๋™์œผ๋กœ ๋ฐ”์ธ๋”ฉํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์—ฐ๊ฒฐ์„ ์„ค์ •ํ•ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. localhost:8080์— ๋Œ€ํ•œ ํ˜ธ์ถœ์„ ์ˆ˜์‹ ํ•  ๋•Œ "index"๋ผ๋Š” ํŽ˜์ด์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” @GetMapping("/") ์ฃผ์„์œผ๋กœ ํ‘œ์‹œ๋˜๋Š” ๋ทฐ์˜ ํ†ต์‹  ๋ฐฉ์‹์— ๋” ๋งŽ์€ ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ™•์žฅ๋œ ์„ค๋ช… @RequestMapping(value = "/", method = RequestMethod.GET)์„ ์ง€์ •ํ•˜๊ฑฐ๋‚˜ ๋ฐ˜ํ™˜ ์œ ํ˜•์„ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ง„ ModelAndView๋กœ ๋ฐ”๊พธ๋Š” ๋“ฑ ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ˜„์žฌ ์‹ค์ œ ์ ์šฉ ๊ฒฝํ—˜์— ๋”ฐ๋ฅด๋ฉด ์ตœ์ข… ๊ฒฐ๊ณผ์— ๊ทผ๋ณธ์ ์ธ ์ฐจ์ด์ ์„ ๋ฐœ๊ฒฌํ•˜์ง€ ๋ชปํ•˜๊ณ  ์ผ๋ฐ˜์ ์ธ ์˜ต์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ํƒญ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ™•์žฅํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ํƒ์ƒ‰ ๋ชจ์Œ ์š”์†Œ๋ฅผ ํด๋ฆญํ•˜๋ฉด @GetMapping("/new")์ด ํ˜ธ์ถœ๋˜์–ด "์ž‘์—…" ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ "์ƒˆ" ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋””๋ ‰์…˜๋˜๊ณ , ๋ฒ„ํŠผ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž…๋ ฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•  ๋•Œ "๋ฉ”์‹œ์ง€"๋ผ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ๋ฉ”์ธ ๋ธ”๋ก์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜๋ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅ ์ฐฝ์˜ ๋ณ€์ˆ˜ ์ด๋ฆ„๊ณผ ์ „์†ก๋œ ๊ฐ’์˜ ์ด๋ฆ„์ด ์™„์ „ํžˆ ์ผ์น˜ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํŠน๋ณ„ํ•œ ์–ธ๊ธ‰์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
<input type="text" class="form-control" id="message" th:name="message" placeholder="Enter your note." maxlength="100"/>
@GetMapping("/new")
public String newNote() {
   return "operations/new";
}

@PostMapping("/save")
public String updateNote(@RequestParam String message) {
   service.saveNote(new Note(message));
   return "redirect:/";
}
์œ ์‚ฌํ•œ ๊ธฐ์ˆ ์ด ๋ ˆ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ปจํŠธ๋กค์„ ํด๋ฆญํ•˜๋ฉด @GetMapping("/edit/{id}") ๋งคํ•‘์ด ํ˜ธ์ถœ๋˜๊ณ  URL ๋ฌธ์ž์—ด์˜ ์‹๋ณ„์ž๊ฐ€ ์ „์†ก๋˜๋ฉฐ ์ถ”๊ฐ€ ํŽธ์ง‘์„ ์œ„ํ•œ ํ•ญ๋ชฉ๊ณผ ํ•จ๊ป˜ "note" ์†์„ฑ์ด ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค. @RequestParam(value = "done", require = false) boolean done) ํŠน์ • ๊ฐ’์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์€ Thymeleaf ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•  ๋•Œ ์ฒดํฌ๋ฐ•์Šค ์‚ฌ์šฉ์— ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•˜๋ฉฐ ๊ธฐ๋ณธ์ ์œผ๋กœ "false"๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
@GetMapping("/edit/{id}")
public String edit(@PathVariable Integer id, Model model) {
   Note note = service.getNoteById(id);
   model.addAttribute("note", note);
   return "operations/edit";
}

@PostMapping("/update")
public String saveNote(@RequestParam Integer id, @RequestParam String message,
                      @RequestParam(value = "done", required = false) boolean done) {
   service.updateNote(id, message, done);
   return "redirect:/";
}
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ํ•ญ๋ชฉ์„ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๋ฉฐ ์ „๋‹ฌ๋œ ๊ฐ’์„ ์‚ฌ์šฉํ•˜์—ฌ ์ ์ ˆํ•œ ์„œ๋น„์Šค ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ค‘์š”ํ•œ ์กฐ์ž‘์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
@GetMapping("/delete/{id}")
public String delete(@PathVariable Integer id) {
   service.deleteNote(id);
   return "redirect:/";
}
์ด์ œ ์™„์„ฑ๋œ ์กฐ๊ฐ์„ ์•ฝ๊ฐ„ ์กฐ์ •ํ•˜๊ณ  Spring Data JPA์˜ ์ฟผ๋ฆฌ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ MySQL๊ณผ์˜ ํฅ๋ฏธ๋กœ์šด ํ†ต์‹ ์œผ๋กœ ๋„˜์–ด๊ฐ€๊ณ  ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋‹ซ๊ธฐ ์ „์— ๊ฐ„๋‹จํ•œ ํ•„ํ„ฐ๋ง์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๋ณ„๋„๋กœ ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
@Controller
public class NoteController {

   private String sortDateMethod = "ASC";

   @GetMapping("/")
   public String list(Model model) {
       List<Note> notebook = filterAndSort();
       model.addAttribute("notes", notebook);
       model.addAttribute("sort", sortDateMethod);
       return "index";
   }

private List<Note> filterAndSort() {
   List<Note> notebook = null;
   switch (sortDateMethod) {
       case "ASC":
           notebook = service.findAllByOrderByDateAsc();
           break;
       case "DESC":
           notebook = service.findAllByOrderByDateDesc();
           break;
   }
   return notebook;
}

์•„์ฃผ ์ž‘์ง€๋งŒ ์ค‘์š”ํ•œ ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.

๊ธฐ๋Œ€์™€๋Š” ๋‹ฌ๋ฆฌ ๊ฐ’์„ ํ•„ํ„ฐ๋งํ•˜๋Š” ๊ฒƒ์ด ๊ธฐ์ˆ  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ๋˜ ๋‹ค๋ฅธ ๊ฑธ๋ฆผ๋Œ๋กœ ํŒ๋ช…๋˜์—ˆ์œผ๋ฉฐ ํŽ˜์ด์ง€ ๋งค๊น€์œผ๋กœ ์„ค์ •๋œ ๋ณต์žก์„ฑ ์ž„๊ณ„๊ฐ’์„ ์ž์‹  ์žˆ๊ฒŒ ๊ทน๋ณตํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์ถ”๊ฐ€ ํ‘œ์‹œ๋ฅผ ์œ„ํ•ด ๋ฐ์ดํ„ฐ ๋ฐฐ์—ด์„ ํŠน์ • ํฌ๊ธฐ์˜ ๋ณ„๋„ ํŽ˜์ด์ง€๋กœ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ๋ˆ„์ ๋œ ํ”ผ๋กœ๊ฐ€ ํฐ ํƒ€๊ฒฉ์„ ์ž…์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ... ์™„์ „ํžˆ ์šฐ์—ฐํ•œ ์ฟผ๋ฆฌ ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋‚œ ํ›„์— ์˜๊ฐ์ด ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค.
public interface NoteRepository extends JpaRepository<Note, Integer> {
   List<Note> findAllByOrderByDateAsc();
   List<Note> findAllByOrderByDateDesc();
}
Spring Data JPA๋Š” ์ •๋ณด๊ฐ€ ์ˆ˜์‹ ๋˜๋ฉด ์ •๋ ฌํ•  ํ•„์š”๊ฐ€ ์—†๊ณ  ๊ด‘๋ฒ”์œ„ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž ์žฌ๋ ฅ์„ ๊ฐ–๋Š” ๊ณ ๋„๋กœ ์„ธ๋ถ„ํ™”๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:
List<Note> findAllByOrderByDateAsc();
์ด ๋ฉ”์†Œ๋“œ๋Š” SQL ์ฟผ๋ฆฌ๋กœ ๋ณ€ํ™˜๋˜์–ด ๋ชจ๋“  ๋ ˆ์ฝ”๋“œ(findAll)๋ฅผ ๋‚ ์งœ(byDate) ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฆ„์ฐจ์ˆœ(Asc)์œผ๋กœ ์ •๋ ฌ(byOrder)ํ•˜์—ฌ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋‹จ์ผ ์š”๊ตฌ ์‚ฌํ•ญ์œผ๋กœ ์—ฌ๋Ÿฌ ๋ถ„์•ผ์— ๊ฑธ์ณ ๋ณต์žกํ•œ ์กฐํ•ฉ๊ณผ ์ƒ˜ํ”Œ๋ง์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‚ ์งœ ๊ฐ’(byDate)๋ณ„๋กœ ๊ฐ์†Œ(Decs)ํ•˜๋Š” ์ˆœ์„œ(byOrder)๋กœ ์™„๋ฃŒ๋œ(byDoneTrue) ๋ชจ๋“ (findAll) ๋ ˆ์ฝ”๋“œ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
Page<Note> findAllByDoneTrueOrderByDateDesc(Pageable pageable);

์ดˆ๋ณด ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ๊ฒฐ๋ก ์ด๋‚˜ ๋˜ ๋‹ค๋ฅธ ๊ณ ๋ฐฑ

๋ชจ๋‘! Shift+F10 ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ํ•ด๋‹น ์•„์ด์ฝ˜์„ ํด๋ฆญํ•˜์—ฌ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์•ˆ์ „ํ•˜๊ฒŒ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Spring Boot๋Š” Apache Maven์—์„œ ํ”„๋กœ๊ทธ๋žจ์„ ๋นŒ๋“œํ•˜๊ณ  localhost:8080์— ๋กœ์ปฌ Apache Tomcat ์„œ๋ฒ„๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ์–ด๋–ค ๋ธŒ๋ผ์šฐ์ €์—์„œ๋“  ๋งํฌ๋ฅผ ๋”ฐ๋ผ๊ฐ€๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
์ปจํ€˜์ŠคํŠธ ์Šคํ”„๋ง ๋ถ€์ธ  - 6
๋ฌผ๋ก , ๋‹ค๋ฅธ ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•๋ก ๋„ ๊ฐœ๋ฐœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ž ์žฌ๋ ฅ์€ ๊ฐœ๋ฐœ์ž์˜ ๋…ธ๋ ฅ, ์ง€๋žต, ์ƒ์ƒ๋ ฅ์— ์˜ํ•ด ์ œํ•œ๋ฉ๋‹ˆ๋‹ค.
์ปจํ€˜์ŠคํŠธ ์Šคํ”„๋ง ๋ถ€์ธ  - 7
์†”์งํ•˜๊ณ  ๋‚ด๊ฐ€ ๊ฑธ์–ด์˜จ ๊ธธ์— ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์ด๋ฉด์„œ ๋‚˜๋Š” ์„ ํƒํ•œ ๋ฐฉํ–ฅ์ด ์ •ํ™•ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๊ณ„์†ํ•ด์„œ ํ™•์‹ ํ•˜๊ณ  JavaRush ๊ต์œก ํฌํ„ธ์—์„œ ๊ณต๋ถ€ํ•˜๋Š” ๊ฒƒ์˜ ์ด์ ์„ ๊นจ๋‹ซ์Šต๋‹ˆ๋‹ค. ๋‹ค์–‘ํ•œ ์‹ค๋ฌด ์ž‘์—… ๋•๋ถ„์— ๋น„์Šทํ•œ ๋ฐฉํ–ฅ์˜ ๊ณ ๋“ฑ ๊ต์œก ๊ธฐ๊ด€์˜ ๋‚ก๊ณ  ๋†€๋ผ์šธ ์ •๋„๋กœ ์ง€๋ฃจํ•œ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์™„์ „ํžˆ ์–ต์••๋˜์—ˆ๋˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ•™์Šต์— ๋Œ€ํ•œ ๋งคํ˜น์ ์ธ ๊ด€์‹ฌ์„ ๋˜๋Œ๋ฆด ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐฑ์—”๋“œ ๊ธฐ์ˆ  ์Šคํƒ์˜ ์ž๋ฃŒ๋ฅผ 4๊ฐœ์›” ๋™์•ˆ ์ ๊ทน์ ์œผ๋กœ ๊ณต๋ถ€ํ•œ ๊ฒƒ์€ ์ˆ˜๋…„ ๋™์•ˆ ๊ฐ•์˜์™€ ์‹คํ—˜์‹ค ์ˆ˜์—…์„ ๋“ค์—ˆ๋˜ ๊ฒƒ์— ๋น„ํ•ด ํ›จ์”ฌ ๋” ๋งŽ์€ ์ง€์‹์„ ํˆฌ์žํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฏฟ๊ฑฐ ๋‚˜ ๋ง๊ฑฐ๋‚˜. ๋ณต์žกํ•œ ์žฌ๋ฃŒ์— ๋“ค์–ด๊ฐ€๋Š” ์–ด๋ ค์›€์— ๊ตด๋ณตํ•˜์ง€ ์•Š๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์žฅ์• ๋ฌผ์„ ๊ทน๋ณตํ•จ์œผ๋กœ์จ ์šฐ๋ฆฌ๊ฐ€ ๋” ๋‚˜์•„์ง€๊ณ  ์ง์—…์ ์œผ๋กœ๋‚˜ ๊ฐœ์ธ์ ์œผ๋กœ ๋ฐœ์ „ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด ์ž‘์€ ์ด์•ผ๊ธฐ๊ฐ€ SpringBoot๋ผ๋Š” ๋†€๋ผ์šด ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ์•„์ด๋””์–ด๋ฅผ ๋ฐœ๊ฒฌํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. PS Github .
์ฝ”๋ฉ˜ํŠธ
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION