๐ŸŒŸ ์Šคํ”„๋ง MVC ํŒจํ„ด์˜ ์„ธ๊ณ„๋กœ ๋– ๋‚˜๋Š” ์‹ ๋‚˜๋Š” ๋ชจํ—˜! ๐Ÿš€

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐ŸŒŸ ์Šคํ”„๋ง MVC ํŒจํ„ด์˜ ์„ธ๊ณ„๋กœ ๋– ๋‚˜๋Š” ์‹ ๋‚˜๋Š” ๋ชจํ—˜! ๐Ÿš€

 

 

์•ˆ๋…•ํ•˜์„ธ์š”, ์ฝ”๋”ฉ ํƒํ—˜๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜์€ ์ •๋ง ํฅ๋ฏธ์ง„์ง„ํ•œ ์—ฌํ–‰์„ ๋– ๋‚˜๋ณผ ๊ฑฐ์˜ˆ์š”. ์šฐ๋ฆฌ์˜ ๋ชฉ์ ์ง€๋Š” ๋ฐ”๋กœ ์Šคํ”„๋ง MVC ํŒจํ„ด์ด๋ผ๋Š” ์‹ ๋น„๋กœ์šด ๋‚˜๋ผ์ž…๋‹ˆ๋‹ค. ์ด ๋‚˜๋ผ๋Š” ์ž๋ฐ” ๊ฐœ๋ฐœ์ž๋“ค ์‚ฌ์ด์—์„œ ๊ต‰์žฅํžˆ ์ธ๊ธฐ ์žˆ๋Š” ์—ฌํ–‰์ง€์ธ๋ฐ์š”, ์™œ ๊ทธ๋Ÿฐ์ง€ ํ•จ๊ป˜ ์•Œ์•„๋ณด๋„๋ก ํ•ด์š”! ๐Ÿ•ต๏ธโ€โ™‚๏ธ

์—ฌ๋Ÿฌ๋ถ„, ํ˜น์‹œ ์žฌ๋Šฅ๋„ท์ด๋ผ๋Š” ์‚ฌ์ดํŠธ๋ฅผ ์•„์‹œ๋‚˜์š”? ์ด๊ณณ์€ ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ์„ ๊ฐ€์ง„ ์‚ฌ๋žŒ๋“ค์ด ๋ชจ์—ฌ ์„œ๋กœ์˜ ์ง€์‹๊ณผ ๊ธฐ์ˆ ์„ ๊ณต์œ ํ•˜๋Š” ๋ฉ‹์ง„ ํ”Œ๋žซํผ์ด์—์š”. ์šฐ๋ฆฌ๊ฐ€ ์˜ค๋Š˜ ๋ฐฐ์šธ ์Šคํ”„๋ง MVC ํŒจํ„ด๋„ ์ด๋Ÿฐ ์žฌ๋Šฅ ์ค‘ ํ•˜๋‚˜๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์ฃ . ๋ˆ„๊ตฐ๊ฐ€๋Š” ์ด ํŒจํ„ด์„ ๋งˆ์Šคํ„ฐํ•ด์„œ ์žฌ๋Šฅ๋„ท์—์„œ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๊ฐ€๋ฅด์น  ์ˆ˜๋„ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ์–ผ๋งˆ๋‚˜ ๋ฉ‹์ง„ ์ผ์ด์—์š”! ๐Ÿ˜Š

๐ŸŽ“ ํ•™์Šต ๋ชฉํ‘œ: ์ด ์—ฌํ–‰์ด ๋๋‚  ๋•Œ์ฏค, ์—ฌ๋Ÿฌ๋ถ„์€ ์Šคํ”„๋ง MVC ํŒจํ„ด์˜ ๊ธฐ๋ณธ ๊ฐœ๋…์„ ์ดํ•ดํ•˜๊ณ , ๊ฐ„๋‹จํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋  ๊ฑฐ์˜ˆ์š”. ๋งˆ์น˜ ๋ ˆ๊ณ  ๋ธ”๋ก์œผ๋กœ ๋ฉ‹์ง„ ์„ฑ์„ ์Œ“๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์ฃ !

์ž, ์ด์ œ ์šฐ๋ฆฌ์˜ ๋ชจํ—˜์„ ์‹œ์ž‘ํ•ด๋ณผ๊นŒ์š”? ์•ˆ์ „๋ฒจํŠธ๋ฅผ ๊ผญ ๋งค์‹œ๊ณ , ํ˜ธ๊ธฐ์‹ฌ ๊ฐ€๋“ํ•œ ๋งˆ์Œ์œผ๋กœ ์ถœ๋ฐœํ•ฉ๋‹ˆ๋‹ค! ๐Ÿš—๐Ÿ’จ

๐ŸŒˆ ์Šคํ”„๋ง MVC ํŒจํ„ด: ์›น ๊ฐœ๋ฐœ์˜ ๋งˆ๋ฒ• ์ง€ํŒก์ด

์—ฌ๋Ÿฌ๋ถ„, ํ˜น์‹œ ํ•ด๋ฆฌ ํฌํ„ฐ์˜ ๋งˆ๋ฒ• ์ง€ํŒก์ด๋ฅผ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? ๊ทธ ์ง€ํŒก์ด๋กœ ๋†€๋ผ์šด ๋งˆ๋ฒ•์„ ๋ถ€๋ฆด ์ˆ˜ ์žˆ์—ˆ์ฃ . ์›น ๊ฐœ๋ฐœ ์„ธ๊ณ„์—์„œ ์Šคํ”„๋ง MVC ํŒจํ„ด์€ ๋ฐ”๋กœ ๊ทธ๋Ÿฐ ์กด์žฌ์˜ˆ์š”. ์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด, ๋ณต์žกํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋„ ๋งˆ๋ฒ•์ฒ˜๋Ÿผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค! ๐Ÿง™โ€โ™‚๏ธโœจ

ํ•˜์ง€๋งŒ ์ž ๊น, MVC๊ฐ€ ๋ญ”์ง€ ๋ชจ๋ฅด๋Š” ์นœ๊ตฌ๋“ค๋„ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ๊ฑฑ์ • ๋งˆ์„ธ์š”. ์ง€๊ธˆ๋ถ€ํ„ฐ ์ฐจ๊ทผ์ฐจ๊ทผ ์„ค๋ช…ํ•ด ๋“œ๋ฆด๊ฒŒ์š”.

๐Ÿ“š MVC๋ž€?

  • Model: ๋ฐ์ดํ„ฐ์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ด๋‹นํ•ด์š”.
  • View: ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ง€๋Š” ๋ถ€๋ถ„์„ ๋งก์•„์š”.
  • Controller: Model๊ณผ View ์‚ฌ์ด์—์„œ ์ •๋ณด๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ์ค‘์žฌ์ž ์—ญํ• ์„ ํ•ด์š”.

์ดํ•ด๊ฐ€ ๋˜์‹œ๋‚˜์š”? MVC๋Š” ๋งˆ์น˜ ๋ ˆ์Šคํ† ๋ž‘๊ณผ ๋น„์Šทํ•ด์š”. Model์€ ์ฃผ๋ฐฉ(๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ), View๋Š” ์†๋‹˜์—๊ฒŒ ์„œ๋น™๋˜๋Š” ์Œ์‹(ํ™”๋ฉด), Controller๋Š” ์ฃผ๋ฌธ์„ ๋ฐ›๊ณ  ์Œ์‹์„ ์ „๋‹ฌํ•˜๋Š” ์›จ์ดํ„ฐ(์ค‘์žฌ์ž) ์—ญํ• ์„ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๐Ÿฝ๏ธ๐Ÿ‘จโ€๐Ÿณ๐Ÿ‘ฉโ€๐Ÿณ

๊ทธ๋Ÿผ ์ด์ œ ์Šคํ”„๋ง MVC ํŒจํ„ด์˜ ๋งˆ๋ฒ• ์„ธ๊ณ„๋กœ ๋“ค์–ด๊ฐ€ ๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? ์—ฌ๋Ÿฌ๋ถ„์˜ ๋งˆ๋ฒ• ์ง€ํŒก์ด(ํ‚ค๋ณด๋“œ)๋ฅผ ๊บผ๋‚ด์„ธ์š”! ๐Ÿช„

MVC ํŒจํ„ด ๋‹ค์ด์–ด๊ทธ๋žจ Model Controller View

์œ„์˜ ๊ทธ๋ฆผ์ด ๋ฐ”๋กœ MVC ํŒจํ„ด์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ์˜ˆ์š”. ์–ด๋•Œ์š”? ์ƒ๊ฐ๋ณด๋‹ค ๋ณต์žกํ•˜์ง€ ์•Š์ฃ ? ์ด์ œ ์ด ๊ตฌ์กฐ๋ฅผ ๊ธฐ์–ตํ•˜๋ฉด์„œ, ์Šคํ”„๋ง MVC์˜ ์„ธ๊ณ„๋ฅผ ๋” ๊นŠ์ด ํƒํ—˜ํ•ด ๋ด…์‹œ๋‹ค! ๐Ÿ•ต๏ธโ€โ™€๏ธ๐Ÿ”

๐Ÿ—๏ธ ์Šคํ”„๋ง MVC์˜ ๊ตฌ์กฐ: ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฒญ์‚ฌ์ง„

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

์Šคํ”„๋ง MVC์˜ ๊ตฌ์กฐ๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณผ๊นŒ์š”? ์ด ๊ตฌ์กฐ๋Š” ๋งˆ์น˜ ์ž˜ ์งœ์—ฌ์ง„ ์˜ค์ผ€์ŠคํŠธ๋ผ์™€ ๊ฐ™์•„์š”. ๊ฐ ๋ถ€๋ถ„์ด ์ž์‹ ์˜ ์—ญํ• ์„ ์™„๋ฒฝํ•˜๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋ฉด์„œ๋„, ์ „์ฒด์ ์œผ๋กœ ์กฐํ™”๋ฅผ ์ด๋ฃจ์ฃ . ๐ŸŽป๐ŸŽบ๐Ÿฅ

๐ŸŽญ ์Šคํ”„๋ง MVC์˜ ์ฃผ์š” ์ปดํฌ๋„ŒํŠธ:

  • DispatcherServlet: ํ”„๋ก ํŠธ ์ปจํŠธ๋กค๋Ÿฌ๋กœ, ๋ชจ๋“  ์š”์ฒญ์„ ๊ฐ€์žฅ ๋จผ์ € ๋ฐ›์•„ ์ ์ ˆํ•œ ์ปจํŠธ๋กค๋Ÿฌ์—๊ฒŒ ์ „๋‹ฌํ•ด์š”.
  • HandlerMapping: ์š”์ฒญ URL์„ ์–ด๋–ค ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์ฒ˜๋ฆฌํ• ์ง€ ๊ฒฐ์ •ํ•ด์š”.
  • Controller: ์‹ค์ œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฅผ ModelAndView ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜ํ•ด์š”.
  • ViewResolver: ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๋ทฐ ์ด๋ฆ„์„ ์‹ค์ œ ๋ทฐ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•ด์š”.
  • View: ์ตœ์ข…์ ์œผ๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์งˆ ํ™”๋ฉด์„ ๋ Œ๋”๋งํ•ด์š”.

์ด ๊ตฌ์กฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์ข€ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ๊นŒ์š”? ๋งˆ์น˜ ์šฐ๋ฆฌ๊ฐ€ ์žฌ๋Šฅ๋„ท์—์„œ ์ƒˆ๋กœ์šด ์žฌ๋Šฅ์„ ์ฐพ์•„๋ณด๋Š” ๊ณผ์ •๊ณผ ๋น„์Šทํ•˜๋‹ต๋‹ˆ๋‹ค! ๐Ÿ˜Š

  1. ์‚ฌ์šฉ์ž ์š”์ฒญ: ์‚ฌ์šฉ์ž๊ฐ€ ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ URL์„ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด์š”. (์žฌ๋Šฅ๋„ท์—์„œ "์ž๋ฐ” ํ”„๋กœ๊ทธ๋ž˜๋ฐ" ๊ฒ€์ƒ‰ํ•˜๊ธฐ)
  2. DispatcherServlet: ์ด ์š”์ฒญ์„ ๊ฐ€์žฅ ๋จผ์ € ๋ฐ›์•„์š”. (์žฌ๋Šฅ๋„ท์˜ ์ ‘์ˆ˜ ๋‹ด๋‹น์ž)
  3. HandlerMapping: ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ฐพ์•„์š”. (์–ด๋–ค ๋ถ„์•ผ์˜ ์ „๋ฌธ๊ฐ€์—๊ฒŒ ์—ฐ๊ฒฐํ•ด์•ผ ํ• ์ง€ ๊ฒฐ์ •)
  4. Controller: ์‹ค์ œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•ด์š”. (์ž๋ฐ” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ „๋ฌธ๊ฐ€๊ฐ€ ์ •๋ณด ์ œ๊ณต)
  5. Model: ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„์š”. (์ „๋ฌธ๊ฐ€๊ฐ€ ์ œ๊ณตํ•œ ์ •๋ณด ์ •๋ฆฌ)
  6. ViewResolver: ์–ด๋–ค ๋ทฐ๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ค„์ง€ ๊ฒฐ์ •ํ•ด์š”. (์ •๋ณด๋ฅผ ์–ด๋–ค ํ˜•์‹์œผ๋กœ ๋ณด์—ฌ์ค„์ง€ ๊ฒฐ์ •)
  7. View: ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค˜์š”. (์ •๋ฆฌ๋œ ์ •๋ณด๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ฃผ๊ธฐ)

์ด ๊ณผ์ •์„ ๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์ด๋ ‡๋‹ต๋‹ˆ๋‹ค:

์Šคํ”„๋ง MVC ํ๋ฆ„๋„ ์‚ฌ์šฉ์ž ์š”์ฒญ DispatcherServlet HandlerMapping Controller Model ViewResolver View ์‚ฌ์šฉ์ž ์‘๋‹ต

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

์ด์ œ ์šฐ๋ฆฌ๋Š” ์Šคํ”„๋ง MVC์˜ ์ „์ฒด์ ์ธ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ–ˆ์–ด์š”. ๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ๊ฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ข€ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ณ , ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š”์ง€ ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ์ค€๋น„๋˜์…จ๋‚˜์š”? ์šฐ๋ฆฌ์˜ ์Šคํ”„๋ง MVC ์—ฌํ–‰์€ ๊ณ„์†๋ฉ๋‹ˆ๋‹ค! ๐Ÿš€

๐Ÿ” ์Šคํ”„๋ง MVC์˜ ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ ํƒ๊ตฌ

์ž, ์ด์ œ ์šฐ๋ฆฌ๋Š” ์Šคํ”„๋ง MVC์˜ ์ „์ฒด์ ์ธ ๊ตฌ์กฐ๋ฅผ ์•Œ๊ฒŒ ๋˜์—ˆ์–ด์š”. ํ•˜์ง€๋งŒ ์ง„์ •ํ•œ ๋งˆ๋ฒ•์‚ฌ๊ฐ€ ๋˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ฐ ์ปดํฌ๋„ŒํŠธ์˜ ๋น„๋ฐ€์„ ๋” ๊นŠ์ด ํŒŒํ—ค์ณ์•ผ ํ•ด์š”. ๋งˆ์น˜ ํ•ด๋ฆฌ ํฌํ„ฐ๊ฐ€ ํ˜ธ๊ทธ์™€ํŠธ์—์„œ ๊ฐ ๋งˆ๋ฒ• ๊ณผ๋ชฉ์„ ํ•˜๋‚˜์”ฉ ๋ฐฐ์šฐ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์ฃ ! ๐Ÿง™โ€โ™‚๏ธ๐Ÿ“š

1. DispatcherServlet: ๋ชจ๋“  ์š”์ฒญ์˜ ์‹œ์ž‘์  ๐Ÿšฆ

DispatcherServlet์€ ์Šคํ”„๋ง MVC์˜ ํ•ต์‹ฌ์ด์—์š”. ๋ชจ๋“  HTTP ์š”์ฒญ์„ ๊ฐ€์žฅ ๋จผ์ € ๋ฐ›์•„๋“ค์ด๋Š” ํ”„๋ก ํŠธ ์ปจํŠธ๋กค๋Ÿฌ๋ž๋‹ˆ๋‹ค. ๋งˆ์น˜ ํฐ ํšŒ์‚ฌ์˜ ์ ‘์ˆ˜์ฒ˜ ์ง์›๊ณผ ๊ฐ™์•„์š”. ๋ชจ๋“  ๋ฐฉ๋ฌธ๊ฐ(์š”์ฒญ)์„ ๋งž์ดํ•˜๊ณ , ์ ์ ˆํ•œ ๋ถ€์„œ(์ปจํŠธ๋กค๋Ÿฌ)๋กœ ์•ˆ๋‚ดํ•˜์ฃ .

๐Ÿ”‘ DispatcherServlet์˜ ์ฃผ์š” ์—ญํ• :

  • ๋ชจ๋“  ์š”์ฒญ์„ ๋ฐ›์•„๋“ค์ž„
  • HandlerMapping์„ ํ†ตํ•ด ์ ์ ˆํ•œ ์ปจํŠธ๋กค๋Ÿฌ ์ฐพ๊ธฐ
  • ์š”์ฒญ์„ ์ปจํŠธ๋กค๋Ÿฌ์— ์ „๋‹ฌํ•˜๊ณ  ๊ฒฐ๊ณผ ๋ฐ›๊ธฐ
  • ViewResolver๋ฅผ ํ†ตํ•ด ์ ์ ˆํ•œ ๋ทฐ ์ฐพ๊ธฐ
  • ์ตœ์ข… ์‘๋‹ต์„ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „์†ก

DispatcherServlet์€ web.xml ํŒŒ์ผ์ด๋‚˜ Java ์„ค์ •์„ ํ†ตํ•ด ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, Java ์„ค์ •์œผ๋กœ DispatcherServlet์„ ๋“ฑ๋กํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ต๋‹ˆ๋‹ค:


public class WebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(WebConfig.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
            "dispatcher", new DispatcherServlet(context));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
}
  

์ด ์ฝ”๋“œ๋Š” DispatcherServlet์„ ์ƒ์„ฑํ•˜๊ณ , ๋ชจ๋“  URL("/")์— ๋Œ€ํ•ด ๋งคํ•‘ํ•˜๊ณ  ์žˆ์–ด์š”. ๋งˆ์น˜ ํšŒ์‚ฌ์˜ ๋ชจ๋“  ์ „ํ™”๋ฅผ ์ ‘์ˆ˜์ฒ˜๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ฃ !

2. HandlerMapping: ๊ธธ์žก์ด ์—ญํ•  ๐Ÿ—บ๏ธ

HandlerMapping์€ ๋“ค์–ด์˜จ ์š”์ฒญ์„ ์–ด๋–ค ํ•ธ๋“ค๋Ÿฌ(๋ณดํ†ต ์ปจํŠธ๋กค๋Ÿฌ)๊ฐ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ• ์ง€ ๊ฒฐ์ •ํ•ด์š”. ๋งˆ์น˜ ์šฐ๋ฆฌ๊ฐ€ ์žฌ๋Šฅ๋„ท์—์„œ ์›ํ•˜๋Š” ์žฌ๋Šฅ์„ ์ฐพ์„ ๋•Œ, ์–ด๋–ค ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ๊ฐ€์•ผ ํ• ์ง€ ์•ˆ๋‚ดํ•ด์ฃผ๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜์ฃ .

๐Ÿ” HandlerMapping์˜ ์ฃผ์š” ๊ตฌํ˜„์ฒด:

  • RequestMappingHandlerMapping: @RequestMapping ์–ด๋…ธํ…Œ์ด์…˜์„ ์ฒ˜๋ฆฌ
  • SimpleUrlHandlerMapping: URL ํŒจํ„ด๊ณผ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ง์ ‘ ๋งคํ•‘
  • BeanNameUrlHandlerMapping: ๋นˆ ์ด๋ฆ„์„ URL๋กœ ์‚ฌ์šฉ

๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์€ RequestMappingHandlerMapping์ด์—์š”. ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ฃ :


@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String hello() {
        return "hello";
    }
}
  

์ด ์ฝ”๋“œ๋Š” "/hello" URL๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ HelloController์˜ hello() ๋ฉ”์†Œ๋“œ๊ฐ€ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๋งคํ•‘ํ•ด์š”. ๋งˆ์น˜ "ํ”„๋กœ๊ทธ๋ž˜๋ฐ" ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ๊ฐ€๋ฉด ์ž๋ฐ” ์ „๋ฌธ๊ฐ€๋ฅผ ๋งŒ๋‚  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”!

3. Controller: ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ์ค‘์‹ฌ ๐Ÿง 

์ปจํŠธ๋กค๋Ÿฌ๋Š” ์‹ค์ œ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ณณ์ด์—์š”. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฅผ Model์— ๋‹ด์•„ View์— ์ „๋‹ฌํ•˜์ฃ . ์žฌ๋Šฅ๋„ท์˜ ์ „๋ฌธ๊ฐ€๊ฐ€ ์—ฌ๋Ÿฌ๋ถ„์˜ ์งˆ๋ฌธ์— ๋‹ต๋ณ€์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”.

๐Ÿ› ๏ธ ์ปจํŠธ๋กค๋Ÿฌ์˜ ์ฃผ์š” ํŠน์ง•:

  • @Controller ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด ์„ ์–ธ
  • @RequestMapping ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ URL ๋งคํ•‘
  • ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌ
  • Model ๊ฐ์ฒด์— ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„ View์— ์ „๋‹ฌ

๋‹ค์Œ์€ ๊ฐ„๋‹จํ•œ ์ปจํŠธ๋กค๋Ÿฌ์˜ ์˜ˆ์‹œ์—์š”:


@Controller
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public String getUser(@PathVariable Long id, Model model) {
        User user = userService.getUser(id);
        model.addAttribute("user", user);
        return "userDetails";
    }
}
  

์ด ์ปจํŠธ๋กค๋Ÿฌ๋Š” "/users/{id}" URL๋กœ ๋“ค์–ด์˜ค๋Š” GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ด์š”. ์‚ฌ์šฉ์ž ID๋ฅผ ๋ฐ›์•„ ํ•ด๋‹น ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ Model์— ๋‹ด์•„ "userDetails"๋ผ๋Š” ์ด๋ฆ„์˜ ๋ทฐ๋กœ ์ „๋‹ฌํ•˜์ฃ . ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ํŠน์ • ์ „๋ฌธ๊ฐ€์˜ ํ”„๋กœํ•„์„ ์กฐํšŒํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•ด์š”!

4. Model: ๋ฐ์ดํ„ฐ์˜ ๋ณด๊ด€์†Œ ๐Ÿ“ฆ

Model์€ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ทฐ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ์‚ฌ์šฉ๋ผ์š”. ๋งˆ์น˜ ์„œ๋ฅ˜ ๊ฐ€๋ฐฉ ๊ฐ™์€ ์—ญํ• ์„ ํ•œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์ฃ . ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์ฒ˜๋ฆฌํ•œ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์ด ๊ฐ€๋ฐฉ์— ๋„ฃ์–ด ๋ทฐ์—๊ฒŒ ์ „๋‹ฌํ•˜๋Š” ๊ฑฐ์˜ˆ์š”.

๐Ÿ“Š Model ์‚ฌ์šฉ์˜ ์žฅ์ :

  • ์ปจํŠธ๋กค๋Ÿฌ์™€ ๋ทฐ ์‚ฌ์ด์˜ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์„ ๋‹จ์ˆœํ™”
  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ๋กœ์ง์˜ ๋ถ„๋ฆฌ ์ด‰์ง„
  • ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ ์ฆ๊ฐ€

Model ์‚ฌ์šฉ ์˜ˆ์‹œ๋ฅผ ๋ณผ๊นŒ์š”?


@GetMapping("/greeting")
public String greeting(@RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
    model.addAttribute("name", name);
    return "greeting";
}
  

์ด ์˜ˆ์ œ์—์„œ๋Š” name ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ›์•„ Model์— ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ์–ด์š”. ๋ทฐ์—์„œ๋Š” ์ด name ๊ฐ’์„ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์ธ์‚ฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ . ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ์‚ฌ์šฉ์ž์˜ ์ด๋ฆ„์„ ๋ฐ›์•„ ๋งž์ถคํ˜• ํ™˜์˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”!

5. ViewResolver: ๋ทฐ ์ฐพ๊ธฐ์˜ ๋‹ฌ์ธ ๐Ÿ”Ž

ViewResolver๋Š” ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๋ทฐ ์ด๋ฆ„์„ ์‹ค์ œ ๋ทฐ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•ด์š”. ๋งˆ์น˜ ๋„์„œ๊ด€์—์„œ ์ฑ… ์ œ๋ชฉ์„ ์•Œ๋ ค์ฃผ๋ฉด ๊ทธ ์ฑ…์ด ์žˆ๋Š” ์ •ํ™•ํ•œ ์œ„์น˜๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ์‚ฌ์„œ์™€ ๊ฐ™์ฃ .

๐Ÿท๏ธ ViewResolver์˜ ์ฃผ์š” ๊ตฌํ˜„์ฒด:

  • InternalResourceViewResolver: JSP ํŒŒ์ผ์„ ์ฐพ์„ ๋•Œ ์‚ฌ์šฉ
  • ThymeleafViewResolver: Thymeleaf ํ…œํ”Œ๋ฆฟ์„ ์ฐพ์„ ๋•Œ ์‚ฌ์šฉ
  • FreeMarkerViewResolver: FreeMarker ํ…œํ”Œ๋ฆฟ์„ ์ฐพ์„ ๋•Œ ์‚ฌ์šฉ

ViewResolver ์„ค์ • ์˜ˆ์‹œ๋ฅผ ๋ณผ๊นŒ์š”?


@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}
  

์ด ์„ค์ •์€ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ "hello"๋ผ๋Š” ๋ทฐ ์ด๋ฆ„์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด, ViewResolver๊ฐ€ "/WEB-INF/views/hello.jsp" ํŒŒ์ผ์„ ์ฐพ๋„๋ก ํ•ด์š”. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ "์ž๋ฐ” ํ”„๋กœ๊ทธ๋ž˜๋ฐ"์ด๋ผ๊ณ  ๊ฒ€์ƒ‰ํ•˜๋ฉด ์ž๋™์œผ๋กœ ๊ด€๋ จ ์นดํ…Œ๊ณ ๋ฆฌ๋กœ ์•ˆ๋‚ดํ•ด์ฃผ๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜์ฃ !

6. View: ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ง€๋Š” ์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ ๐Ÿ–ผ๏ธ

View๋Š” ๋ชจ๋ธ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ์‹ค์ œ๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์งˆ ํ™”๋ฉด์„ ๋งŒ๋“ค์–ด๋‚ด์š”. HTML, PDF, JSON ๋“ฑ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๊ฐ€ ๋  ์ˆ˜ ์žˆ์ฃ . ์žฌ๋Šฅ๋„ท์—์„œ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ํŽ˜์ด์ง€๋‚˜ ํ”„๋กœํ•„ ํŽ˜์ด์ง€๊ฐ€ ๋ฐ”๋กœ View์˜ ์˜ˆ์‹œ๋ž๋‹ˆ๋‹ค.

๐ŸŽจ View์˜ ์ฃผ์š” ํŠน์ง•:

  • Model์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„
  • ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ๋กœ์ง ํฌํ•จ
  • ๋‹ค์–‘ํ•œ ํ…œํ”Œ๋ฆฟ ์—”์ง„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ (JSP, Thymeleaf, FreeMarker ๋“ฑ)
  • ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ตฌ์„ฑ ๊ฐ€๋Šฅ

JSP๋ฅผ ์‚ฌ์šฉํ•œ ๊ฐ„๋‹จํ•œ View ์˜ˆ์‹œ๋ฅผ ๋ณผ๊นŒ์š”?


<!-- hello.jsp -->
<html>
<body>
    <h1>Hello, ${name}!</h1>
    <p>Welcome to Spring MVC world!</p>
</body>
</html>
  

์ด JSP ํŒŒ์ผ์€ Model์—์„œ ์ „๋‹ฌ๋ฐ›์€ 'name' ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋™์ ์œผ๋กœ ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•ด์š”. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ์ด๋ฆ„์„ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ฃ !

์ž, ์ด์ œ ์šฐ๋ฆฌ๋Š” ์Šคํ”„๋ง MVC์˜ ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ž์„ธํžˆ ์‚ดํŽด๋ดค์–ด์š”. ๊ฐ ๋ถ€๋ถ„์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€, ์–ด๋–ป๊ฒŒ ์„œ๋กœ ํ˜‘๋ ฅํ•˜๋Š”์ง€ ์ดํ•ดํ•˜์…จ๋‚˜์š”? ์ด ์ง€์‹์„ ๋ฐ”ํƒ•์œผ๋กœ ์ด์ œ ์šฐ๋ฆฌ๋งŒ์˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ค€๋น„๊ฐ€ ๋˜์—ˆ์–ด์š”! ๐Ÿš€

๐Ÿ› ๏ธ ์‹ค์ „! ์Šคํ”„๋ง MVC๋กœ ๊ฐ„๋‹จํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋งŒ๋“ค๊ธฐ

์ž, ์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ๋ฐฐ์šด ์ง€์‹์„ ํ™œ์šฉํ•ด ๊ฐ„๋‹จํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค์–ด๋ณผ ๊ฑฐ์˜ˆ์š”. ์šฐ๋ฆฌ์˜ ๋ชฉํ‘œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜๋ฉด ์ธ์‚ฌ๋ง์„ ๋ณด์—ฌ์ฃผ๋Š” ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“œ๋Š” ๊ฑฐ์˜ˆ์š”. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์— ์ฒ˜์Œ ๊ฐ€์ž…ํ–ˆ์„ ๋•Œ ํ™˜์˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”! ๐Ÿ˜Š

1๋‹จ๊ณ„: ํ”„๋กœ์ ํŠธ ์„ค์ •

๋จผ์ €, ์Šคํ”„๋ง ๋ถ€ํŠธ๋ฅผ ์‚ฌ์šฉํ•ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ด๋ณผ๊ฒŒ์š”. ์Šคํ”„๋ง ๋ถ€ํŠธ๋Š” ์Šคํ”„๋ง MVC ์„ค์ •์„ ์ž๋™์œผ๋กœ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ดˆ๋ณด์ž์—๊ฒŒ ์•„์ฃผ ์ข‹๋‹ต๋‹ˆ๋‹ค!


// build.gradle
plugins {
    id 'org.springframework.boot' version '2.5.0'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
}
  

์ด ์„ค์ •์œผ๋กœ ์Šคํ”„๋ง ๋ถ€ํŠธ์™€ Thymeleaf ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.

2๋‹จ๊ณ„: ์ปจํŠธ๋กค๋Ÿฌ ๋งŒ๋“ค๊ธฐ

์ด์ œ ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ์š”.


// src/main/java/com/example/demo/GreetingController.java
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class GreetingController {

    @GetMapping("/greeting")
    public String greeting(@RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
        model.addAttribute("name", name);
        return "greeting";
    }
}
  

์ด ์ปจํŠธ๋กค๋Ÿฌ๋Š” "/greeting" URL๋กœ ๋“ค์–ด์˜ค๋Š” GET ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ด์š”. ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜๋ฉด ๊ทธ ์ด๋ฆ„์„, ์ž…๋ ฅํ•˜์ง€ ์•Š์œผ๋ฉด "World"๋ฅผ Model์— ์ถ”๊ฐ€ํ•˜๊ณ  "greeting" ๋ทฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ฃ .

3๋‹จ๊ณ„: ๋ทฐ ๋งŒ๋“ค๊ธฐ

์ด์ œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์งˆ ํ™”๋ฉด์„ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ์š”. Thymeleaf ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•  ๊ฑฐ์˜ˆ์š”.


<!-- src/main/resources/templates/greeting.html -->
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Getting Started: Serving Web Content</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h1 th:text="'Hello, ' + ${name} + '!'"></h1>
    <p>Welcome to our amazing Spring MVC application!</p>
</body>
</html>
  

์ด HTML ํŒŒ์ผ์€ Thymeleaf ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•ด ๋™์ ์œผ๋กœ ์ด๋ฆ„์„ ํ‘œ์‹œํ•ด์š”. ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ „๋‹ฌ๋ฐ›์€ 'name' ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฑฐ์ฃ .

4๋‹จ๊ณ„: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰

์ด์ œ ๋ชจ๋“  ์ค€๋น„๊ฐ€ ๋๋‚ฌ์–ด์š”! ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•ด๋ณผ๊นŒ์š”?


// src/main/java/com/example/demo/DemoApplication.java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
  

์ด ํด๋ž˜์Šค๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ๋‚ด์žฅ ํ†ฐ์บฃ ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์šฐ๋ฆฌ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•ด์š”.

์ด์ œ ๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:8080/greeting๋กœ ์ ‘์†ํ•ด๋ณด์„ธ์š”. "Hello, World!"๋ผ๋Š” ๋ฉ”์‹œ์ง€๊ฐ€ ๋ณด์ผ ๊ฑฐ์˜ˆ์š”. URL์— ์ด๋ฆ„์„ ์ถ”๊ฐ€ํ•ด๋ณผ๊นŒ์š”? http://localhost:8080/greeting?name=SpringMaster ์ด๋ ‡๊ฒŒ์š”. ์ด๋ฒˆ์—” "Hello, SpringMaster!"๋ผ๊ณ  ๋‚˜์˜ฌ ๊ฑฐ์˜ˆ์š”!

๐ŸŽ‰ ์ถ•ํ•˜ํ•ด์š”! ๋ฐฉ๊ธˆ ์—ฌ๋Ÿฌ๋ถ„์€ ์ฒซ ๋ฒˆ์งธ ์Šคํ”„๋ง MVC ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค์—ˆ์–ด์š”. ์ด ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์—์„œ ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์Šคํ”„๋ง MVC์˜ ํ•ต์‹ฌ ๊ฐœ๋…๋“ค์„ ์‚ฌ์šฉํ–ˆ๋‹ต๋‹ˆ๋‹ค:

  • Controller: ์‚ฌ์šฉ์ž ์š”์ฒญ์„ ์ฒ˜๋ฆฌ
  • Model: ๋ทฐ์— ์ „๋‹ฌํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์Œ
  • View: ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์งˆ ํ™”๋ฉด์„ ์ƒ์„ฑ
  • @RequestParam: URL ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ›์•„์˜ด
  • Thymeleaf: ๋™์ ์œผ๋กœ HTML์„ ์ƒ์„ฑ

์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ์Šคํ”„๋ง MVC์˜ ๊ธฐ๋ณธ์„ ๋งˆ์Šคํ„ฐํ–ˆ์–ด์š”! ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋” ๋ณต์žกํ•˜๊ณ  ๋ฉ‹์ง„ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์ฒ˜๋Ÿผ ์‚ฌ์šฉ์ž๋“ค์ด ์ž์‹ ์˜ ์žฌ๋Šฅ์„ ๊ณต์œ ํ•˜๊ณ  ๊ฑฐ๋ž˜ํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋žซํผ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ต๋‹ˆ๋‹ค. ์ƒ์ƒ๋ ฅ์„ ๋ฐœํœ˜ํ•ด๋ณด์„ธ์š”! ๐Ÿš€โœจ

๐ŸŒŸ ์Šคํ”„๋ง MVC์˜ ๋” ๊นŠ์€ ์„ธ๊ณ„๋กœ

์šฐ๋ฆฌ๋Š” ์ง€๊ธˆ๊นŒ์ง€ ์Šคํ”„๋ง MVC์˜ ๊ธฐ๋ณธ์ ์ธ ๊ฐœ๋…๊ณผ ๊ฐ„๋‹จํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋งŒ๋“ค๊ธฐ๋ฅผ ๋ฐฐ์› ์–ด์š”. ํ•˜์ง€๋งŒ ์Šคํ”„๋ง MVC์˜ ์„ธ๊ณ„๋Š” ์ด๋ณด๋‹ค ํ›จ์”ฌ ๋” ๋„“๊ณ  ๊นŠ๋‹ต๋‹ˆ๋‹ค. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ์ฒ˜์Œ์—๋Š” ๊ฐ„๋‹จํ•œ ์žฌ๋Šฅ ๊ฑฐ๋ž˜๋กœ ์‹œ์ž‘ํ–ˆ์ง€๋งŒ, ์ ์  ๋” ๋‹ค์–‘ํ•˜๊ณ  ๋ณต์žกํ•œ ๊ธฐ๋Šฅ๋“ค์„ ์ถ”๊ฐ€ํ•ด ๋‚˜๊ฐ€๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ง์ด์—์š”. ๐Ÿ˜Š

์—ฌ๋Ÿฌ๋ถ„์˜ ์Šคํ”„๋ง MVC ์—ฌํ–‰์„ ๋”์šฑ ํ’์„ฑํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ค„ ๋ช‡ ๊ฐ€์ง€ ๊ณ ๊ธ‰ ์ฃผ์ œ๋“ค์„ ์†Œ๊ฐœํ•ด๋“œ๋ฆด๊ฒŒ์š”:

1. RESTful ์›น ์„œ๋น„์Šค ๊ตฌํ˜„ํ•˜๊ธฐ

RESTful API๋Š” ํ˜„๋Œ€ ์›น ๊ฐœ๋ฐœ์—์„œ ๋งค์šฐ ์ค‘์š”ํ•œ ๊ฐœ๋…์ด์—์š”. ์Šคํ”„๋ง MVC๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‰ฝ๊ฒŒ RESTful ์›น ์„œ๋น„์Šค๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.


@RestController
@RequestMapping("/api/users")
public class UserController {
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        // ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๋Š” ๋กœ์ง
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        // ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋กœ์ง
    }
}
  

์ด๋Ÿฐ ์‹์œผ๋กœ RESTful API๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ๋„ ์ด๋Ÿฐ API๋ฅผ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์žฌ๋Šฅ ๊ฑฐ๋ž˜๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ?

2. ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ ์ ์šฉํ•˜๊ธฐ

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ณด์•ˆ์€ ๋งค์šฐ ์ค‘์š”ํ•ด์š”. ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ธ์ฆ๊ณผ ๊ถŒํ•œ ๋ถ€์—ฌ๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.


@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }
}
  

์ด๋ ‡๊ฒŒ ์„ค์ •ํ•˜๋ฉด ํŠน์ • ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์ ‘๊ทผ ์ œ์–ด๋ฅผ ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ๋„ ์ด๋Ÿฐ ๋ณด์•ˆ ์„ค์ •์œผ๋กœ ์‚ฌ์šฉ์ž์˜ ๊ฐœ์ธ ์ •๋ณด๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณดํ˜ธํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ?

3. ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA ์‚ฌ์šฉํ•˜๊ธฐ

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๋Š” ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA๋„ ์•Œ์•„๋ณผ ๊ฐ€์น˜๊ฐ€ ์žˆ์–ด์š”.


@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private String email;
    // getters and setters
}

@Repository
public interface UserRepository extends JpaRepository<user long> {
    List<user> findByName(String name);
}
  </user></user>

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ณต์žกํ•œ SQL ์ฟผ๋ฆฌ ์—†์ด๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์˜ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์ด๋Ÿฐ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒ ๋„ค์š”!

4. ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์™€ ์›น์†Œ์ผ“

์‹ค์‹œ๊ฐ„ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ์Šคํ”„๋ง์˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ๊ณผ ์›น์†Œ์ผ“์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.


@Controller
public class ChatController {
    @MessageMapping("/chat")
    @SendTo("/topic/messages")
    public OutputMessage send(Message message) throws Exception {
        return new OutputMessage(message.getFrom(), message.getText(), new SimpleDateFormat("HH:mm").format(new Date()));
    }
}
  

์ด๋Ÿฐ ์‹์œผ๋กœ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ ์‚ฌ์šฉ์ž๋“ค์ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ์†Œํ†ตํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค ๋•Œ ์œ ์šฉํ•˜๊ฒ ์ฃ ?

5. ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ (TDD)

๋งˆ์ง€๋ง‰์œผ๋กœ, ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ์€ ์ฝ”๋“œ์˜ ํ’ˆ์งˆ์„ ๋†’์ด๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ด์—์š”. ์Šคํ”„๋ง์€ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ํ›Œ๋ฅญํ•œ ๋„๊ตฌ๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.


@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testGetUser() throws Exception {
        mockMvc.perform(get("/api/users/1"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$.name", is("John Doe")));
    }
}
  

์ด๋Ÿฐ ์‹์œผ๋กœ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์ด๋Ÿฐ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋ฉด, ๋ฒ„๊ทธ ์—†๋Š” ์•ˆ์ •์ ์ธ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ?

๐Ÿš€ ์—ฌ๋Ÿฌ๋ถ„์˜ ๋‹ค์Œ ๋‹จ๊ณ„: ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ์Šคํ”„๋ง MVC์˜ ๊ธฐ๋ณธ๋ถ€ํ„ฐ ๊ณ ๊ธ‰ ์ฃผ์ œ๊นŒ์ง€ ์‚ดํŽด๋ดค์–ด์š”. ๋‹ค์Œ ๋‹จ๊ณ„๋กœ๋Š” ์ด๋Ÿฐ ๊ฒƒ๋“ค์„ ํ•ด๋ณด๋Š” ๊ฒŒ ์–ด๋–จ๊นŒ์š”?

  • ์žฌ๋Šฅ๋„ท๊ณผ ๋น„์Šทํ•œ ๊ฐ„๋‹จํ•œ ์žฌ๋Šฅ ๊ฑฐ๋ž˜ ํ”Œ๋žซํผ์„ ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณด๊ธฐ
  • ์Šคํ”„๋ง์˜ ๋‹ค์–‘ํ•œ ํ”„๋กœ์ ํŠธ๋“ค (Spring Boot, Spring Cloud ๋“ฑ) ํƒ๊ตฌํ•˜๊ธฐ
  • ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ฐธ์—ฌํ•˜๊ฑฐ๋‚˜ ์˜คํ”ˆ ์†Œ์Šค ํ”„๋กœ์ ํŠธ์— ๊ธฐ์—ฌํ•˜๊ธฐ
  • ์Šคํ”„๋ง ๊ด€๋ จ ์ปจํผ๋Ÿฐ์Šค๋‚˜ ๋ฐ‹์—…์— ์ฐธ๊ฐ€ํ•˜๊ธฐ

์—ฌ๋Ÿฌ๋ถ„์˜ ์Šคํ”„๋ง MVC ์—ฌํ–‰์ด ์—ฌ๊ธฐ์„œ ๋๋‚˜์ง€ ์•Š๊ธฐ๋ฅผ ๋ฐ”๋ผ์š”. ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ์›น ๊ฐœ๋ฐœ์˜ ๋ฌดํ•œํ•œ ๊ฐ€๋Šฅ์„ฑ์„ ๊ฐ€์ง„ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๋ฅผ ์†์— ๋„ฃ์—ˆ์–ด์š”. ๋งˆ์น˜ ์žฌ๋Šฅ๋„ท์—์„œ ์ƒˆ๋กœ์šด ์žฌ๋Šฅ์„ ๋ฐฐ์šฐ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ์Šคํ”„๋ง MVC๋ฅผ ํ†ตํ•ด ๊ณ„์†ํ•ด์„œ ์ƒˆ๋กœ์šด ๊ฒƒ์„ ๋ฐฐ์šฐ๊ณ  ์„ฑ์žฅํ•ด ๋‚˜๊ฐ€์„ธ์š”. ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ์ƒ๋ ฅ์ด ๊ณง ํ•œ๊ณ„๋ž๋‹ˆ๋‹ค. ํ™”์ดํŒ…! ๐ŸŒŸ๐Ÿš€