CodeStates 45th

[Spring MVC] API ๊ณ„์ธต

jeonniu 2023. 6. 19. 20:42

๐Ÿƒ Spring MVC

Spring์—์„œ ์ง€์›ํ•˜๋Š” ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ํฌํ•จํ•ด์„œ Spring Framework ๋ผ๊ณ  ํ•œ๋‹ค.

 

Spring์˜ ๋ชจ๋“ˆ ์ค‘์—์„œ๋Š” ์›น ๊ณ„์ธต์„ ๋‹ด๋‹นํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ชจ๋“ˆ์ด ์žˆ๋Š”๋ฐ, ๊ทธ ์ค‘์—์„œ ์„œ๋ธ”๋ฆฟ(Servlet) API๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ชจ๋“ˆ์ด ์žˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์„ spring-webmvc ๋ผ๊ณ  ํ•œ๋‹ค. ์ด๋Š” Spring Web MVC, Spring MVC, Spring MVC ํ”„๋ ˆ์ž„์›Œํฌ๋ผ๊ณ  ๋ถˆ๋ฆฌ๊ณ  ์žˆ๋‹ค.

 

๊ฐ„๋‹จํžˆ ์ •๋ฆฌํ•˜๋ฉด Spring MVC ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

โœ”๏ธ Spring MVC ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ด๋‹ค.

โœ”๏ธ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค๊ฒŒ ๋  ์ƒ˜ํ”Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ Spring MVC๊ฐ€ ์ œ๊ณตํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด์„œ ๋งŒ๋“ ๋‹ค.

 

 

์„œ๋ธ”๋ฆฟ(Servlet)์ด๋ž€?

- ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํŠน์ • ๊ทœ์•ฝ์— ๋งž์ถฐ Java ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๋Š” ํด๋ž˜์Šค ํŒŒ์ผ์ด๋‹ค.

- ์•„ํŒŒ์น˜ ํ†ฐ์บฃ (Apache Tomcat)์€ ์„œ๋ธ”๋ฆฟ๋“ค์ด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ์‹คํ–‰์ด ๋˜๋„๋ก ํ•ด์ฃผ๋Š” ์„œ๋ธ”๋ฆฟ ์ปจํ…Œ์ด๋„ˆ (Servlet Container) ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

 

 

Model

 

Model์€ Spring MVC์—์„œ M์— ํ•ด๋‹นํ•œ๋‹ค.

 

Spring MVC ๊ธฐ๋ฐ˜์˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ „๋‹ฌ ๋ฐ›์œผ๋ฉด ์š”์ฒญ ์‚ฌํ•ญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ž‘์—…์„ ํ•œ๋‹ค.

 

์ด๋ ‡๊ฒŒ ์ฒ˜๋ฆฌํ•œ ์ž‘์—…์˜ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‘๋‹ต์œผ๋กœ ๋Œ๋ ค์ค˜์•ผ ํ•˜๋Š”๋ฐ, ์ด ๋•Œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‘๋‹ต์œผ๋กœ ๋Œ๋ ค์ฃผ๋Š” ์ž‘์—…์˜ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ Model์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

ํด๋ผ์ด์–ธํŠธ์—์˜ ์š”์ฒญ ์‚ฌํ•ญ์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ์˜์—ญ์„ ์„œ๋น„์Šค ๊ณ„์ธต(Service Layer)์ด๋ผ๊ณ  ํ•˜๋ฉฐ,

์‹ค์ œ๋กœ ์š”์ฒญ ์‚ฌํ•ญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด Java ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•œ ๊ฒƒ์„ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง(Business Logic) ์ด๋ผ ํ•œ๋‹ค. 

 

 

View

Model์€ Spring MVC์—์„œ V์— ํ•ด๋‹นํ•œ๋‹ค.

 

View๋Š” Model ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•ด ์›น ๋ธŒ๋ผ์šฐ์ € ๊ฐ™์€ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ™”๋ฉด์— ๋ณด์ด๋Š” ๋ฆฌ์†Œ์Šค(Resource)๋ฅผ ์ œ๊ณตํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

Spring MVC ์—๋Š” ๋‹ค์–‘ํ•œ View ๊ธฐ์ˆ ์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”๋ฐ View์˜ ํ˜•ํƒœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

 

- HTML ํŽ˜์ด์ง€์˜ ์ถœ๋ ฅ

- PDF, Excel ๋“ฑ์˜ ๋ฌธ์„œ ํ˜•ํƒœ๋กœ ์ถœ๋ ฅ

- XML, JSON(JavaScript Object Natation) ๋“ฑ ํŠน์ • ํ˜•์‹์˜ ํฌ๋งท์œผ๋กœ์˜ ๋ณ€ํ™˜

 

 

Controller

Model์€ Spring MVC์—์„œ C์— ํ•ด๋‹นํ•œ๋‹ค.

 

Controller๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก์˜ ์š”์ฒญ์„ ์ง์ ‘์ ์œผ๋กœ ์ „๋‹ฌ๋ฐ›๋Š” ์—”๋“œํฌ์ธํŠธ(Endpoint)๋กœ์จ Model ๊ณผ View ์˜ ์ค‘๊ฐ„์—์„œ ์ƒํ˜ธ ์ž‘์šฉ์„ ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

ํด๋ผ์ด์–ธํŠธ ์ธก์˜ ์š”์ฒญ์„ ์ „๋‹ฌ ๋ฐ›์•„์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๊ฑฐ์นœ ํ›„ Model  ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋ฉด, ์ด Model ๋ฐ์ดํ„ฐ๋ฅผ View๋กœ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

 

 

Spring MVC ๋™์ž‘ ๋ฐฉ์‹๊ณผ ๊ตฌ์„ฑ ์š”์†Œ

 

Spring MVC์˜ ๋™์ž‘ ๋ฐฉ์‹ ๋ฐ ๊ตฌ์„ฑ ์š”์†Œ

(1) ๋จผ์ € ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญ์„ ์ „์†กํ•˜๋ฉด DispatcherServlet์ด๋ผ๋Š” ํด๋ž˜์Šค์— ์š”์ฒญ์ด ์ „๋‹ฌ๋œ๋‹ค.

 

(2) DispatcherServlet์€ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  Controller์— ๋Œ€ํ•œ ๊ฒ€์ƒ‰์„ HandlerMapping ์ธํ„ฐํŽ˜์ด์Šค์—๊ฒŒ ์š”์ฒญํ•œ๋‹ค.

 

(3) HandlerMapping์€ ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ๊ณผ ๋งคํ•‘๋˜๋Š” ํ•ธ๋“ค๋Ÿฌ ๊ฐ์ฒด๋ฅผ ๋‹ค์‹œ DispatcherServlet์—๊ฒŒ ๋ฆฌํ„ดํ•ด์ค€๋‹ค.

ํ•ธ๋“ค๋Ÿฌ ๊ฐ์ฒด๋Š” ํ•ด๋‹น ํ•ธ๋“ค๋Ÿฌ์˜ Handler ๋ฉ”์„œ๋“œ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค.
Handler ๋ฉ”์„œ๋“œ๋Š” Controller ํด๋ž˜์Šค ์•ˆ์— ๊ตฌํ˜„๋œ ์š”์ฒญ ์ฒ˜๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

(4) ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  Controller ํด๋ž˜์Šค๋ฅผ ์ฐพ์•˜์œผ๋‹ˆ ์ด์ œ๋Š” ์‹ค์ œ๋กœ ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  Handler ๋ฉ”์„œ๋“œ๋ฅผ ์ฐพ์•„์„œ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. DispatcherServlet์€ Handler ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ , HandlerAdpater์—๊ฒŒ Handler ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ์œ„์ž„ํ•œ๋‹ค.


(5) HandlerAdapter๋Š” DispatcherServlet์œผ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ Controller ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด๋‹น Controller์˜ Handler ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

์ด์ œ ์ „์ฒด ์ฒ˜๋ฆฌ ํ๋ฆ„์˜ ๋ฐ˜ํ™˜์ ์„ ๋Œ์•˜๋‹ค. ์ด์ œ๋ถ€ํ„ฐ๋Š” ๋ฐ˜๋Œ€๋กœ ๋˜๋Œ์•„๊ฐ€๋ณด์ž.

(6) Controller์˜ Handler ๋ฉ”์„œ๋“œ๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ ํ›„ ๋ฆฌํ„ด ๋ฐ›์€ Model ๋ฐ์ดํ„ฐ๋ฅผ HandlerAdapter์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค.


(7) HandlerAdapter๋Š” ์ „๋‹ฌ๋ฐ›์€ Model ๋ฐ์ดํ„ฐ์™€ View ์ •๋ณด๋ฅผ ๋‹ค์‹œ DispatcherServlet์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค.


(8) DispatcherServlet์€ ์ „๋‹ฌ๋ฐ›์€ View ์ •๋ณด๋ฅผ ๋‹ค์‹œ ViewResolver์—๊ฒŒ ์ „๋‹ฌํ•ด์„œ View ๊ฒ€์ƒ‰์„ ์š”์ฒญํ•œ๋‹ค.


(9) ViewResolver๋Š” View ์ •๋ณด์— ํ•ด๋‹นํ•˜๋Š” View๋ฅผ ์ฐพ์•„์„œ View๋ฅผ ๋‹ค์‹œ ๋ฆฌํ„ดํ•ด์ค€๋‹ค.


(10) DispatcherServlet์€ ViewResolver๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ View ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด Model ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด์„œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌํ•  ์‘๋‹ต ๋ฐ์ดํ„ฐ ์ƒ์„ฑ์„ ์š”์ฒญํ•œ๋‹ค.


(11) View๋Š” ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋‹ค์‹œ DispatcherServlet์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค.


(12) DispatcherServlet์€ View๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ตœ์ข…์ ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค.

 

Front Controller Pattern

- DispatcherServlet์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฐ€์žฅ ์•ž๋‹จ์— ๋ฐฐ์น˜๋˜์–ด ๋‹ค๋ฅธ ๊ตฌ์„ฑ์š”์†Œ๋“ค๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋ฉด์„œ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํŒจํ„ด

 

 

 

Controller ํด๋ž˜์Šค ์„ค๊ณ„ ๋ฐ ๊ตฌ์กฐ ์ƒ์„ฑ 

 

 

API ๊ณ„์ธต (๊ณ„์ธตํ˜• ์•„ํ‚คํ…์ฒ˜)

 

API ๊ณ„์ธต์€ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ง์ ‘์ ์œผ๋กœ ์ „๋‹ฌ ๋ฐ›๋Š” ๊ณ„์ธต์ด๋‹ค

 

Spring MVC ๋™์ž‘ ๋ฐฉ์‹๊ณผ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ ํ๋ฆ„์˜ ๋์—๋Š” Controller๊ฐ€ ์žˆ๋‹ค.

์ด๊ณณ์ด ๋ฐ”๋กœ Spring MVC์—์„œ ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์˜ ์ตœ์ข… ๋ชฉ์ ์ง€๊ฐ€ ๋œ๋‹ค.

 

 

์ปคํ”ผ ์ฃผ๋ฌธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ , ํ•ด๋‹น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ Controller์„ ์„ค๊ณ„ํ•ด๋ณด์ž.

๋จผ์ € ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ธฐ๋Šฅ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ •๋ฆฌํ•ด๋ณด์ž.

 

 

์ฃผ์ธ์ด ์ปคํ”ผ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ
- ์ปคํ”ผ ์ •๋ณด ๋“ฑ๋ก ๊ธฐ๋Šฅ
- ๋“ฑ๋กํ•œ ์ปคํ”ผ ์ •๋ณด ์ˆ˜์ • ๊ธฐ๋Šฅ
- ๋“ฑ๋กํ•œ ์ปคํ”ผ ์ •๋ณด ์‚ญ์ œ ๊ธฐ๋Šฅ
- ๋“ฑ๋กํ•œ ์ปคํ”ผ ์ •๋ณด ์กฐํšŒ ๊ธฐ๋Šฅ

๊ณ ๊ฐ์ด ์ปคํ”ผ ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ
- ์ปคํ”ผ ์ •๋ณด ์กฐํšŒ ๊ธฐ๋Šฅ

๊ณ ๊ฐ์ด ์ปคํ”ผ๋ฅผ ์ฃผ๋ฌธํ•˜๋Š” ๊ธฐ๋Šฅ
- ์ปคํ”ผ ์ฃผ๋ฌธ ๋“ฑ๋ก ๊ธฐ๋Šฅ
- ์ปคํ”ผ ์ฃผ๋ฌธ ์ทจ์†Œ ๊ธฐ๋Šฅ
- ์ปคํ”ผ ์ฃผ๋ฌธ ์กฐํšŒ ๊ธฐ๋Šฅ

๊ณ ๊ฐ์ด ์ฃผ๋ฌธํ•œ ์ปคํ”ผ๋ฅผ ์ฃผ์ธ์ด ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ
- ์ปคํ”ผ ์ฃผ๋ฌธ ์กฐํšŒ ๊ธฐ๋Šฅ
- ๊ณ ๊ฐ์—๊ฒŒ ์ „๋‹ฌ ์™„๋ฃŒํ•œ ์ปคํ”ผ์— ๋Œ€ํ•œ ์ฃผ๋ฌธ ์™„๋ฃŒ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ

 

 

์ปคํ”ผ ์ฃผ๋ฌธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค

REST API ๊ธฐ๋ฐ˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ œ๊ณตํ•ด์•ผ ๋  ๊ธฐ๋Šฅ์„ ๋ฆฌ์†Œ์Šค(Resource, ์ž์›)์œผ๋กœ ๋ถ„๋ฅ˜ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฆฌ์†Œ์Šค๊ฐ€ ํ•„์š”ํ•œ ๊ฒƒ์„ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ปคํ”ผ ์ฃผ๋ฌธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•„์š”ํ•œ ๋ฆฌ์†Œ์Šค

 

์ปคํ”ผ ์ฃผ๋ฌธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ Controller ๊ตฌ์กฐ ์ž‘์„ฑ

 

MemberController ๊ตฌ์กฐ ์ž‘์„ฑ

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController   // (1)
@RequestMapping("/v1/members")   // (2)
public class MemberController {
}

โœ”๏ธ (1) @RestController

- Spring MVC์—์„œ ํŠน์ • ํด๋ž˜์Šค์— ํ•ด๋‹น ์• ๋…ธํ…Œ์ด์…˜์ด ์ถ”๊ฐ€๋˜๋ฉด, ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ REST API์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด API ์—”๋“œํฌ์ธํŠธ๋กœ ๋™์ž‘ํ•จ์„ ์ •์˜ํ•œ๋‹ค.

- @RestController ๊ฐ€ ์ถ”๊ฐ€๋œ ํด๋ž˜์Šค๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๋”ฉ ์‹œ, Spring Bean์œผ๋กœ ๋“ฑ๋กํ•œ๋‹ค.

 

โœ”๏ธ (2) @RequestMapping

- ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ๊ณผ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ (Handler Method)๋ฅผ ๋งคํ•‘ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

- ํด๋ž˜์Šค ์ „์ฒด์— ์‚ฌ์šฉํ•˜๋Š” ๊ณตํ†ต์˜ URL(Base URL) ์„ค์ •์„ ํ•œ๋‹ค.

 

 

CoffeeController ๊ตฌ์กฐ ์ž‘์„ฑ

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/v1/coffees")
public class CoffeeController {
}

 

 

OrderController ๊ตฌ์กฐ ์ž‘์„ฑ

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/v1/orders")
public class OrderController {
}

 

 

ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ (Handler Method)

ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋ž€ ์šฐ๋ฆฌ๊ฐ€ ์œ„์—์„œ ์ž‘์„ฑํ•œ Controller ํด๋ž˜์Šค์— ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋งํ•œ๋‹ค.

์œ„์—์„œ ๊ตฌํ˜„ํ•œ ๊ฐ Controller์— ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์ž.

 

 

MemberController ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ 

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/v1/members") // (1) produces ์„ค์ • ์ œ๊ฑฐ๋จ
public class MemberController {
    @PostMapping
    public ResponseEntity postMember(@RequestParam("email") String email,
                                     @RequestParam("name") String name,
                                     @RequestParam("phone") String phone) {
        // (2) JSON ๋ฌธ์ž์—ด ์ˆ˜์ž‘์—…์„ Map ๊ฐ์ฒด๋กœ ๋Œ€์ฒด
        Map<String, String> map = new HashMap<>();
        map.put("email", email);
        map.put("name", name);
        map.put("phone", phone);

        // (3) ๋ฆฌํ„ด ๊ฐ’์„ ResponseEntity ๊ฐ์ฒด๋กœ ๋ณ€๊ฒฝ
        return new ResponseEntity<>(map, HttpStatus.CREATED);
    }

    @GetMapping("/{member-id}")
    public ResponseEntity getMember(@PathVariable("member-id") long memberId) {
        System.out.println("# memberId: " + memberId);

        // not implementation

        // (4) ๋ฆฌํ„ด ๊ฐ’์„ ResponseEntity ๊ฐ์ฒด๋กœ ๋ณ€๊ฒฝ
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @GetMapping
    public ResponseEntity getMembers() {
        System.out.println("# get Members");

        // not implementation

        // (5) ๋ฆฌํ„ด ๊ฐ’์„ ResponseEntity ๊ฐ์ฒด๋กœ ๋ณ€๊ฒฝ
        return new ResponseEntity<>(HttpStatus.OK);
    }
}

 

โœ”๏ธ (2) ์šฐ๋ฆฌ๋Š” JSON ๋ฌธ์ž์—ด์„ ์ˆ˜์ž‘์—…์œผ๋กœ ์ž‘์„ฑํ•  ํ•„์š” ์—†์ด Map ๊ฐ์ฒด๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ๋‹ค.

- Map<String, String>์˜ ๊ฒฝ์šฐ key์™€ value๊ฐ€ ๋ชจ๋‘ String ์ด์–ด์•ผ ํ•œ๋‹ค.

- key๊ฐ€ String์ด๊ณ , ๋‹ค๋ฅธ ํƒ€์ž…์˜ ๋ฐ์ดํ„ฐ๋ฅผ map์— ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” value ํƒ€์ž…์„ Object๋กœ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค.

 

โœ”๏ธ (3) ๋ฆฌํ„ด ๊ฐ’์œผ๋กœ JSON ๋ฌธ์ž์—ด์„ ์ฒ˜๋ฆฌํ•˜๋˜ ๋ถ€๋ถ„์ด ResponseEntity ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

- return new ResponseEntity<>(map, HttpStatus.CREATED);

- ์ด๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด์„œ ์ƒ์„ฑ์ž ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์‘๋‹ต ๋ฐ์ดํ„ฐ(map)๊ณผ HTTP ์‘๋‹ต ์ƒํƒœ๋ฅผ ํ•จ๊ป˜ ์ „๋‹ฌํ•˜๊ณ  ์žˆ๋‹ค.

 

 

 

ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„์˜ ๊ด€๊ณ„

์›น ๋ธŒ๋ผ์šฐ์ €์™€ ์›น ์„œ๋ฒ„

์›น ๋ธŒ๋ผ์šฐ์ €๋Š” ์›น ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต์œผ๋กœ ์ „๋‹ฌํ•ด์ฃผ๋Š” HTML ์ฝ˜ํ…์ธ ๋ฅผ ์ „๋‹ฌ ๋ฐ›์•„, ๋ธŒ๋ผ์šฐ์ € ๋‚ด์— ๋ณด์—ฌ์ค€๋‹ค.

์—ฌ๊ธฐ์„œ ์„œ๋ฒ„ ์ชฝ ๋ฆฌ์†Œ์Šค๋ฅผ ์ด์šฉํ•˜๋Š” ์ธก์ด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋œ๋‹ค.

 

ํ•˜์ง€๋งŒ ์„œ๋ฒ„๋Š” ํ•ญ์ƒ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, ์„œ๋ฒ„๋„ ๋‹ค๋ฅธ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณต๋ฐ›์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ Frontend์™€ Backend์˜ ๊ด€๊ณ„๋ฅผ ์‚ดํŽด๋ณผ ์ˆ˜๊ฐ€ ์žˆ๋‹ค.

 

 

์—ฌ๊ธฐ์„œ ์›น ๋ธŒ๋ผ์šฐ์ €์˜ ์ž…์žฅ์—์„œ๋Š” Frontend์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณต๋ฐ›์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋œ๋‹ค.

Frontend์˜ ๊ฒฝ์šฐ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ž…์žฅ์ด๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„๊ฐ€ ๋งž์ง€๋งŒ, Frontend๊ฐ€ Backend์˜ ๋™์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ฒŒ ๋˜๋ฉด, ์ด๋•Œ๋Š” Backend์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์ด์šฉํ•˜๋Š”ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 

 

๊ฒฐ๋ก ์€ ์–ด๋–ค ์„œ๋ฒ„๊ฐ€ HTTP ํ†ต์‹ ์„ ํ†ตํ•ด ๋‹ค๋ฅธ ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์ด์šฉํ•˜๊ฒŒ ๋˜๋ฉด, ๊ทธ ๋•Œ๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์—ญํ• ์„ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

 

 

 

 

DTO(Data Transfer Object)๋ž€?

 

DTO๋Š” ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์˜ ํ•˜๋‚˜๋กœ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์˜ ํ•˜๋‚˜ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„ ์ชฝ์œผ๋กœ ์ „์†กํ•˜๋Š” ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ๋ฐ›์„ ๋•Œ, ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ ์ชฝ์œผ๋กœ ์ „์†กํ•˜๋Š” ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ ์šฉ๋„๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

 

์šฐ๋ฆฌ๊ฐ€ DTO๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

- ํด๋ผ์ด์–ธํŠธ์˜ RequestBody๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ๋ชจ๋‘ ์ „๋‹ฌ๋ฐ›์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ ์ž์ฒด๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง„๋‹ค.

- RequsetBody์˜ ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์ด ๋‹จ์ˆœํ•ด์ง„๋‹ค.

 

 

 

DTO ํด๋ž˜์Šค ์ ์šฉ ์ „ MemberController ์ฝ”๋“œ

@RestController
@RequestMapping("/v1/members")
public class MemberController {
    @PostMapping
    public ResponseEntity postMember(@RequestParam("email") String email,
                                     @RequestParam("name") String name,
                                     @RequestParam("phone") String phone) {
        Map<String, String> map = new HashMap<>();
        map.put("email", email);
        map.put("name", name);
        map.put("phone", phone);

        return new ResponseEntity<Map>(map, HttpStatus.CREATED);
    }

		...
		...
}

 

 

DTO ํด๋ž˜์Šค ์ ์šฉ ํ›„ MemberController ์ฝ”๋“œ

@RestController
@RequestMapping("/v1/members")
public class MemberController {
    @PostMapping
    public ResponseEntity postMember(MemberDto memberDto) {
        return new ResponseEntity<MemberDto>(memberDto, HttpStatus.CREATED);
    }

		...
		...
}

 

์œ ํšจ์„ฑ ๊ฒ€์ฆ ๋กœ์ง์ด ์ถ”๊ฐ€๋œ MemberDto ํด๋ž˜์Šค

public class MemberDto {
    @Email
    private String email;
    private String name;
    private String phone;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

 

- MemberDto ํด๋ž˜์Šค์—์„œ ์ด๋ฉ”์ผ์— ๋Œ€ํ•œ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์„ ์ง„ํ–‰ํ–ˆ๋‹ค.

 

 

 

์œ ํšจ์„ฑ ๊ฒ€์ฆ์ด ์ ์šฉ๋œ MemberController ์ฝ”๋“œ

@RestController
@RequestMapping("/v1/members")
public class MemberController {
    @PostMapping
    public ResponseEntity postMember(@Valid MemberDto memberDto) {
        return new ResponseEntity<MemberDto>(memberDto, HttpStatus.CREATED);
    }

		...
		...
}

 

 

 

์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ Dto ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ด๋ณด๊ณ , MemberController์— ์ ์šฉํ•ด๋ณด์ž.

 

 

ํšŒ์› ์ •๋ณด ๋“ฑ๋ก์— ์‚ฌ์šฉ๋˜๋Š” MemberPostDto ํด๋ž˜์Šค

public class MemberPostDto {
    private String email;
    private String name;
    private String phone;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

 

 

ํšŒ์› ์ •๋ณด ์ˆ˜์ •์— ์‚ฌ์šฉ๋˜๋Š” MemberPatchDto ํด๋ž˜์Šค

public class MemberPatchDto {
    private long memberId;
    private String name;
    private String phone;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public long getMemberId() {
        return memberId;
    }

    public void setMemberId(long memberId) {
        this.memberId = memberId;
    }
}

 

 

Dto๊ฐ€ ์ ์šฉ๋œ MemberController

import com.codestates.member.MemberPatchDto;
import com.codestates.member.MemberPostDto;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/v1/members")
public class MemberController {
    // ํšŒ์› ์ •๋ณด ๋“ฑ๋ก
    @PostMapping
    public ResponseEntity postMember(@RequestBody MemberPostDto memberPostDto) {
        return new ResponseEntity<>(memberPostDto, HttpStatus.CREATED);
    }

    // ํšŒ์› ์ •๋ณด ์ˆ˜์ •
    @PatchMapping("/{member-id}")
    public ResponseEntity patchMember(@PathVariable("member-id") long memberId,
                                      @RequestBody MemberPatchDto memberPatchDto) {
        memberPatchDto.setMemberId(memberId);
        memberPatchDto.setName("ํ™๊ธธ๋™");

        // No need Business logic

        return new ResponseEntity<>(memberPatchDto, HttpStatus.OK);
    }

    // ํ•œ๋ช…์˜ ํšŒ์› ์ •๋ณด ์กฐํšŒ
    @GetMapping("/{member-id}")
    public ResponseEntity getMember(@PathVariable("member-id") long memberId) {
        System.out.println("# memberId: " + memberId);

        // not implementation
        return new ResponseEntity<>(HttpStatus.OK);
    }

    // ๋ชจ๋“  ํšŒ์› ์ •๋ณด ์กฐํšŒ
    @GetMapping
    public ResponseEntity getMembers() {
        System.out.println("# get Members");

        // not implementation

        return new ResponseEntity<>(HttpStatus.OK);
    }

    // ํšŒ์› ์ •๋ณด ์‚ญ์ œ
    @DeleteMapping("/{member-id}")
    public ResponseEntity deleteMember(@PathVariable("member-id") long memberId) {
        // No need business logic

        return new ResponseEntity(HttpStatus.NO_CONTENT);
    }
}

 

 

 

โœ”๏ธ @RequestBody ์• ๋„ˆํ…Œ์ด์…˜

์ฝ”๋“œ 3-32์—์„œ MemberPostDto ํด๋ž˜์Šค ์•ž์— ๋ถ™์€ @RequestBody ์• ๋„ˆํ…Œ์ด์…˜์€ JSON ํ˜•์‹์˜ Request Body๋ฅผ MemberPostDto ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜์„ ์‹œ์ผœ์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

์ด ๋ง์˜ ์˜๋ฏธ๋Š” ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ ์ „์†กํ•˜๋Š” Request Body๊ฐ€ JSON ํ˜•์‹์ด์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ง๊ณผ ๊ฐ™๋‹ค.

๋งŒ์ผ JSON ํ˜•์‹์ด ์•„๋‹Œ ๋‹ค๋ฅธ ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•œ๋‹ค๋ฉด, Spring ๋‚ด๋ถ€์—์„œ ‘Unsupported Media Type’๊ณผ ๊ฐ™์€ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํฌํ•จํ•œ ์‘๋‹ต์„ ์ „๋‹ฌํ•œ๋‹ค.

 

 



โœ”๏ธ @ResponseBody ์• ๋„ˆํ…Œ์ด์…˜

@RequestBody์˜ ์—ญํ• ์ด ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ ์ „์†กํ•œ JSON ํ˜•์‹์˜ Request Body๋ฅผ DTO ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์ด๋ผ๋ฉด, @ResponseBody๋Š” JSON ํ˜•์‹์˜ Response Body๋ฅผ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด DTO ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ Response Body๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ @ResponseBody๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ์ด ์—†๋Š” ์ด์œ ๋Š” postMember(), patchMember() ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์˜ ๋ฆฌํ„ด ๊ฐ’์ด ResponseEntity ํด๋ž˜์Šค์˜ ๊ฐ์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Spring MVC์—์„œ๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์— @ResponseBody ์• ๋„ˆํ…Œ์ด์…˜์ด ๋ถ™๊ฑฐ๋‚˜ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์˜ ๋ฆฌํ„ด ๊ฐ’์ด ResponseEntity์ผ ๊ฒฝ์šฐ, ๋‚ด๋ถ€์ ์œผ๋กœ HttpMessageConverter๊ฐ€ ๋™์ž‘ํ•˜๊ฒŒ ๋˜์–ด ์‘๋‹ต ๊ฐ์ฒด(์—ฌ๊ธฐ์„œ๋Š” DTO ํด๋ž˜์Šค์˜ ๊ฐ์ฒด)๋ฅผ JSON ํ˜•์‹์œผ๋กœ๋ฐ”๊ฟ”์ค€๋‹ค.

 

 

 


โœ”๏ธ JSON ์ง๋ ฌํ™”(Serialization)์™€ ์—ญ์ง๋ ฌํ™”(Deserialization)

ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„ ์ชฝ์œผ๋กœ ์ „์†กํ•˜๋ฉด ์„œ๋ฒ„ ์ชฝ์˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ „๋‹ฌ๋ฐ›์€ JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ DTO ๊ฐ™์€ Java์˜ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๋Š”๋ฐ ์ด๋ฅผ ์—ญ์ง๋ ฌํ™”(Deserialization)์ด๋ผ๊ณ  ํ•œ๋‹ค.

๋ฐ˜๋ฉด์— ์„œ๋ฒ„ ์ชฝ์—์„œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด์„œ DTO ๊ฐ™์€ Java์˜ ๊ฐ์ฒด๋ฅผ JSON ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์ง๋ ฌํ™”(Serialization)๋ผ๊ณ  ํ•œ๋‹ค.

JSON ์ง๋ ฌํ™”(Serialization): Java ๊ฐ์ฒด → JSON
JSON ์—ญ์ง๋ ฌํ™”(Deserialization): JSON → Java ๊ฐ์ฒด