IT/development

[Spring] spring REST API ๊ณต๋ถ€(feat. @RestController)

์•Œ ์ˆ˜ ์—†๋Š” ์‚ฌ์šฉ์ž 2022. 11. 22.

๋ชฉ์ฐจ

     

    REST๋ž€? ๐Ÿ˜Ž

    REST๋ž€ "Representational State Transfer"์˜ ์•ฝ์ž์ด๊ณ  ์ง์—ญํ•˜๋ฉด ๋Œ€ํ‘œ์ƒํƒœ ์ „์†ก์ด๋‹ค.

    ํ•˜๋‚˜์˜ URI๋Š” ๊ณ ์œ ํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ๋Œ€ํ‘œํ•˜๋„๋ก ์„ค๊ณ„๋œ๋‹ค๋Š” ๊ฐœ๋…์ธ๋ฐ ์†”์งํžˆ ์•„์ง ์ •ํ™•ํžˆ ์ดํ•ดํ•˜์ง€๋Š” ๋ชปํ–ˆ๋‹ค.

    ์›น์˜ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค์— ๊ณ ์œ ํ•œ URI๋กœ ์˜๋ฏธ๋ถ€์—ฌ ํ•œ ๋’ค HTTP Method๋ฅผ ํ†ตํ•ด ์ƒํƒœ๋ฅผ ์ฃผ๊ณ  ๋ฐ›์œผ๋ฉฐ ํ†ต์‹ ํ•˜๋Š” ๋ฐฉ์‹์ด๋ผ๊ณ  ์ดํ•ด ํ–ˆ๋‹ค.

    ๊ทธ๋ฆฌ๊ณ  ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์ด ์ˆœ์ˆ˜ํ•œ ๋ฐ์ดํ„ฐ๋ผ๋Š” ์ 

    ํด๋ผ์ด์–ธํŠธ๊ฐ€ URI๋งŒ ๋ด๋„ ์ด๊ฒŒ ๋ฌด์Šจ ์ž‘์—…์„ ์˜๋ฏธํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ•ด์•ผ ํ•œ๋‹ค.

    ex)localhost:8080/user๊ฐ€ URI์ด๊ณ  POST์œผ๋กœ ์„œ๋ฒ„์— ์ „์†กํ•œ๋‹ค๊ณ  ํ•˜๋ฉด ์‚ฌ์šฉ์ž ๋“ฑ๋ก์ด๋ผ๊ณ  ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ๋‹ค.

    REST ๋ฐฉ์‹์—์„œ๋Š” HTTP Method๊ฐ€ CRUD๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์œ„ URI์—์„œ ๊ตณ์ด /user ๋’ค์— insert ์ด๋Ÿฐ ์ฃผ์†Œ๋ฅผ ๋” ๋ถ™์ผ ํ•„์š”๊ฐ€ ์—†๋‹ค.

    C(create): POST

    R(Read): GET

    U(Update): Put

    D(Delete): Delete

    ๋˜ ๋ฐฑ์—”๋“œ ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ๊ตฌ๋ถ„๋œ๋‹ค.

    ์ฆ‰ REST API ๊ฐœ๋ฐœ์ž๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹๊ณผ ๊ทœ์น™๋งŒ ์ž˜ ์ •ํ•ด์„œ ์•ฝ์†๋œ ๋ฐ์ดํ„ฐ๋งŒ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.


    ์ด์ œ ์Šคํ”„๋ง์—์„œ REST API ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒƒ ๊ด€๋ จํ•ด์„œ ์ •๋ฆฌํ•œ๋‹ค. ์‹œ๊ฐ„ ์ƒ ๋„ˆ๋ฌด ๊นŠ๊ฒŒ ์ •๋ฆฌ๋Š” ๋ชปํ•œ๋‹ค.

    ๊ณต๋ถ€ํ•  ๊ฒŒ ๋„ˆ๋ฌด ๋งŽ๋‹คใ… ใ… 

     

    @RestController ๐Ÿ˜‹

    ๊ฐ„๋‹จํžˆ ์ •๋ฆฌํ•œ๋‹ค.

    @Controller์™€ @ResponseBody๋ฅผ ํ•ฉ์นœ ์–ด๋…ธํ…Œ์ด์…˜์„ ์˜๋ฏธํ•œ๋‹ค.

    ์ฆ‰ @RestController ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ์ˆœ์ˆ˜ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „์†กํ•œ๋‹ค.

    REST ๋ฐฉ์‹์—์„œ ํด๋ผ์ด์–ธํŠธ๋Š” HTTP BODY์— ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„์„œ(์ฃผ๋กœ JSON ํฌ๋งท) ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๊ณ 

    ์„œ๋ฒ„์—์„œ๋Š” ์ด๋ฅผ JAVA๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ(๋‚ด๋ถ€์ ์œผ๋กœ HttpMessageConverter๊ฐ€ ์ฒ˜๋ฆฌ) ์‚ฌ์šฉํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด @RequestBody์ž„(ํด๋ผ์ด์–ธํŠธ์—์„œ JSONํ˜•์‹์œผ๋กœ ๋ณด๋‚ด๋ฉด ์„œ๋ฒ„์—์„œ๋Š” ๋ฐ˜๋“œ์‹œ ์ด๋ ‡๊ฒŒ ๋ฐ›์•„์•ผ ํ•จ, ์•„๋‹ˆ๋ฉด ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์ด ์•ˆ๋จ)

    ์‚ฝ์งˆ์„ ์ข€ ํ–ˆ๋˜ ์ด์œ ๊ฐ€ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ @ModelAttribute MemberVO memberVO๋กœ ๋ฐ›๊ณ  ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” JSONํ˜•์‹์œผ๋กœ ๋ณด๋ƒˆ๋”๋‹ˆ parameter๊ฐ’์ด null๋กœ ์„ธํŒ…์ด ๋˜์—ˆ์—ˆ๋‹ค.

    ๋” ์ฐพ์•„๋ณด๋‹ˆ @ModelAttribute๋ฅผ ํ†ตํ•ด HTTP BODY๊ฐ’์„ ๋ฐ›์œผ๋ ค๋ฉด Content-Type์„ application/json์ด ์•„๋‹Œ multipart/form-dataํ˜•ํƒœ๋กœ ์ „์†กํ•ด์•ผ๋งŒ ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

     

    ํด๋ผ์ด์–ธํŠธ์—์„œ JSON์œผ๋กœ ๋ณด๋‚ด๋Š” ๊ฑด ๋ฐ˜๋“œ์‹œ @RequestBody๋กœ ๋ฐ›์•„์•ผ ๋œ๋‹ค.(์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด ํ˜•์‹์„ ๋งž์ถฐ์ค˜์•ผ ํ•œ๋‹ค.)

    ๊ทธ๋ฆฌ๊ณ  ๋ณด๋‚ผ ๋•Œ๋„ @ResponseBody๋กœ ๋ณด๋‚ด์•ผ ๋œ๋‹ค.

    ์„œ๋ฒ„์—์„œ ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง ์ˆ˜ํ–‰ ํ›„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ ์—ญ์‹œ HTTP BODY ํ˜•์‹์— ๋งž์ถฐ์„œ ๋ฐ˜ํ™˜ํ•ด์ค˜์•ผ ํ•˜๋Š”๋ฐ

    ์ด ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด @ResponseBody์ด๋‹ค.

    ์ฆ‰, @RestController๊ฐ€ ๋ถ™์€ ์ปจํŠธ๋กค๋Ÿฌ๋Š” @ResponseBodyํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.


     

    ์Šคํ”„๋ง์—์„œ parameter๊ฐ’ ๋ฐ”์ธ๋”ฉ ๋ฐฉ๋ฒ• ๐Ÿ˜Ž

    @RequestParam 

    ์„œ๋ฒ„์—์„œ parameter๋ฅผ ๋ฐ›์„ ๋•Œ ๊ฐ์ฒด๋กœ ๋ฐ›๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ์ •๋ง ๋‹จ์ผ์˜ parameter๊ฐ’๋งŒ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉ๋จ, ๋˜ํ•œ ํ•„์ˆ˜ parameter๊ฐ’๋„ ์ด ๋ฐฉ๋ฒ•์œผ๋กœ ๋งŽ์ด ๋ฐ›๋Š”๋‹ค.(@RequestParam ์ƒ๋žต๋„ ๊ฐ€๋Šฅํ•จ)

    ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ์˜ parameter 1:1๋งคํ•‘

    ex) localhost:8080/user?id=test

    ์œ„์ฒ˜๋Ÿผ ํด๋ผ์ด์–ธํŠธ์—์„œ Get๋ฐฉ์‹์œผ๋กœ id๋ฅผ ์„œ๋ฒ„๋กœ ๋„˜๊ธธ ๋•Œ ์„œ๋ฒ„์—์„œ๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ๋ฐ›์œผ๋ฉด ๋œ๋‹ค.

    ์•„๋ž˜๋Š” localhost:8080/test/requestParam?id=test๋กœ ํ˜ธ์ถœํ•˜๋ฉด ResponseEntity๋กœ status 200๊ณผ parameter๊ฐ’์œผ๋กœ ๋ฐ›์€ id๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

     

    ์•„๋ž˜๋Š” ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ…Œ์ŠคํŠธ ํ•œ ๊ฒฐ๊ณผ์ด๋‹ค. ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์œผ๋กœ id๋ฅผ lsy๋กœ ์„œ๋ฒ„๋กœ ๋˜์กŒ๊ณ  ์˜ˆ์ƒ๋Œ€๋กœ ์ƒํƒœ์ฝ”๋“œ๋Š” 200์ด ๋ฐ˜ํ™˜๋˜์—ˆ์œผ๋ฉฐ Response๋ฅผ ๋ณด๋ฉด requestParam : id๊ฐ€ ๋‹ด๊ฒจ์ ธ ์žˆ๋‹ค.

    @RestContrller๋Š” ๋ฐ˜ํ™˜๊ฐ’์„ HTTP BODY๋กœ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์„ค๊ณ„๋˜์–ด ์žˆ๋‹ค.

    ์ด๋ ‡๊ฒŒ ๊ทธ๋ƒฅ ๋‹จ๊ฑด์˜ parameter๊ฐ’์„ ์ฃผ๊ณ  ๋ฐ›์„ ๋•Œ๋Š” @RequestParam์„ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋Š”๋ฐ ์—ฌ๋Ÿฌ๊ฑด์„ ์ฃผ๊ณ  ๋ฐ›์„ ๋•Œ๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ @RequestParam์„ ์—ฌ๋Ÿฌ๋ฒˆ ์ž‘์„ฑํ•ด์•ผ ๋˜๋Š” ๋ถˆํŽธํ•จ์ด ๋ฐœ์ƒํ•œ๋‹ค.

    ์ด๋ ‡๊ฒŒ ์—ฌ๋Ÿฌ๊ฑด์˜ parameter๊ฐ’์„ ๋ฐ›์„ ๋•Œ๋Š” @RequestParam์„ ์ž‘์„ฑํ•˜๋Š” ๊ฑด ๋งค์šฐ ๋น„ํšจ์œจ์ ์ด๋‹ค.

     

    @ModelAttribute

    ์œ„์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ๊ฐœ์˜ parameter๊ฐ’์„ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉ๋˜๋ฉฐ ์ฃผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด๋กœ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.(dto, vo ๋“ฑ)

    dto๋‚˜ vo๋ฅผ ์•„๋ž˜์ฒ˜๋Ÿผ ์ƒ์„ฑํ•ด ๋†“๊ณ  ์ด์— ๋งž์ถฐ์„œ ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉ๋จ

    ๋ฐ์ดํ„ฐ ๋ฐ›๋Š” ๊ฐ์ฒด์— Setter๊ฐ€ ๋ฐ˜๋“œ์‹œ ์„ค์ •๋˜์–ด ์žˆ์–ด์•ผ ํ•จ

     

    ์•„๋ž˜๋Š” localhost:8080/model?id=id&name=name์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฉด MainVO์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

     

    ์•„๋ž˜๋Š” ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ…Œ์ŠคํŠธํ•œ ๊ฒฐ๊ณผ์ด๋‹ค.

    ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์œผ๋กœ id์™€ name์„ ์„œ๋ฒ„๋กœ ๋˜์กŒ๊ณ  MainVO์™€ ๋งคํ•‘๋˜์–ด ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ๋ฐ˜ํ™˜๋˜์—ˆ๋‹ค.

     

    ๋งŒ์ผ ์„œ๋ฒ„์˜ VO์— ์—†๋Š” ๊ฐ’์„ ์ถ”๊ฐ€๋กœ ๋˜์ง€๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ๐Ÿ™„

    VO์—๋Š” ํ˜„์žฌ id์™€ name๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ๋˜์–ด ์žˆ๋‹ค.

    VO์— ์—†๋Š” email์„ ์ถ”๊ฐ€ํ•ด์„œ ์ „์†กํ•ด๋ดค๋‹ค. ์•„๋ž˜์ฒ˜๋Ÿผ email๊ฐ’์€ ๋ฐ˜ํ™˜๋˜์ง€ ์•Š๋Š”๋‹ค.

     

    @RequestBody

    ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„๋กœ ์ „์†กํ•˜๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹์ด form-data๊ฐ€ ์•„๋‹ˆ๋ผ HTTP BODY์— JSONํ˜•์‹์œผ๋กœ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์ด๋ผ๋ฉด ๋ฐ˜๋“œ์‹œ ์„œ๋ฒ„์—์„œ๋„ @RequestBody๋กœ ๋ฐ›์•„์•ผ ์ œ๋Œ€๋กœ ๊ฐ์ฒด์— ๋ฐ”์ธ๋”ฉ์ด ๋œ๋‹ค.

    ์•„๋ž˜์ฝ”๋“œ๋Š” localhost:8080/test/json์œผ๋กœ post๋ฐฉ์‹์œผ๋กœ ํ˜ธ์ถœ(JSONํ˜•์‹)ํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์„œ @RestponseBodyํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

    JSON ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ ์œ„ํ•ด์„œ postman์œผ๋กœ ๋‚ด ๋กœ์ปฌํ˜ธ์ŠคํŠธ๋กœ ์ „์†ก์„ ํ•ด์„œ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”๋‹ค.

    ์ •์ƒ์ ์œผ๋กœ ๊ฐ’์ด ๋ฐ˜ํ™˜๋˜์—ˆ๋‹ค.

    ํด๋ผ์ด์–ธํŠธ์—์„œ POST๋ฐฉ์‹์œผ๋กœ JSONํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ HTTPBODY์— ๋‹ด์•„์„œ ์ „์†กํ•˜๋Š” ์ด ๊ฒฝ์šฐ์— 

    ์„œ๋ฒ„์—์„œ @RequestBody๊ฐ€ ์•„๋‹ˆ๋ผ @ModelAttribute๋กœ ๋ฐ›๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

     

    postman์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๋ฉด JSONํ˜•์‹์œผ๋กœ ๋ณด๋‚ธ id์™€name์ด ์„œ๋ฒ„์—์„œ ๋ฐ”์ธ๋”ฉ์ด ์ œ๋Œ€๋กœ ์•ˆ๋˜์–ด null๊ฐ’์ด ๋ฐ˜ํ™˜๋˜์—ˆ๋‹ค.

     

    ์„œ๋ฒ„์—์„œ @ModelAttribute๋กœ ๋ฐ›๋Š” ๊ฒฝ์šฐ๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ํด๋ผ์ด์–ธํŠธ์˜ ๋ฐ์ดํ„ฐ ์ „์†กํ˜•์‹์„ form-data๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ๋ฐ”์ธ๋”ฉ์ด ์ œ๋Œ€๋กœ ๋œ๋‹ค.

     

    @PathVariable

    url์˜ ์ผ๋ถ€๋ฅผ parameter๊ฐ’์œผ๋กœ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉ๋จ(์ฃผ๋กœ idx์™€ ๊ฐ™์ด ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ํ™œ์šฉ๋˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉ๋จ)

    localhost:9090/user/{idx}

    ์ด๋Ÿฐ์‹์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„๋กœ ์ „์†กํ•˜๋ฉด ์„œ๋ฒ„์—์„œ๋Š” ํ•ด๋‹น idx๋ฅผ ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    @PathVariable("idx") String idx ์ด๋ ‡๊ฒŒ ํ•˜๊ณ  @RequestMapping("/{idx}") ์ด๋Ÿฐ์‹์œผ๋กœ ๋ฐ›์•„์„œ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

    ์•„๋ž˜์ฝ”๋“œ๋Š” url์˜ idx๋ฅผ parameter๊ฐ’์œผ๋กœ ๋˜์ ธ์„œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ ๋’ค ๋ฐ˜ํ™˜ํ•˜๋Š” ์˜ˆ์ œ์ฝ”๋“œ์ด๋‹ค.

    localhost:8080/user/{idx}์—์„œ idx๋ฅผ parameter๊ฐ’์œผ๋กœ ์ถ”์ถœํ•ด์„œ MainService์˜ selectMemberByIdx์— ์ „๋‹ฌ

     

    ๋ธŒ๋ผ์šฐ์ €์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๋ฉด ์•„๋ž˜์ฒ˜๋Ÿผ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

    {idx}๊ฐ’์œผ๋กœ 9999๋ฅผ ์ „๋‹ฌํ–ˆ๊ณ  9999์— ํ•ด๋‹น๋˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜ํ™˜๋˜์—ˆ๋‹ค.

     

    ๊ฐœ์ธ์ ์œผ๋กœ ๊ณต๋ถ€ํ•œ ๋‚ด์šฉ์„ ์ž‘์„ฑํ•˜๋Š”๊ฑฐ๋ผ ํ‹€๋ฆฐ ๋ถ€๋ถ„์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ํ‹€๋ฆฐ ๋‚ด์šฉ์ด ์žˆ์„ ๊ฒฝ์šฐ ๋Œ“๊ธ€๋กœ ํ”ผ๋“œ๋ฐฑ ๋ถ€ํƒ ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๐Ÿ˜…

    ๋Œ“๊ธ€