[Spring boot] Spring Data Rest๋ฅผ ์ด์šฉํ•œ REST API ๊ฐœ๋ฐœ 1

๋ฐ˜์‘ํ˜•

MVC ํŒจํ„ด์— ์ด์–ด์„œ, ์ด๋ฒˆ์—๋Š” Spring Data Rest๋ฅผ ์ด์šฉํ•˜์—ฌ REST API ์„œ๋ฒ„๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ ธ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 

MVC ํŒจํ„ด์—์„œ๋Š” Domain, Controller, Repository ์ด๋ ‡๊ฒŒ 3๊ฐ€์ง€๋ฅผ ์ด์šฉํ•˜์˜€๊ณ , ์ถ”๊ฐ€๋กœ Service ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ๋”์šฑ ์„ธ๋ถ€์ ์ธ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

Spring Data Rest๋Š” VC๋ฅผ ์ƒ๋žตํ•˜๊ณ , ์˜ค์ง Domain๊ณผ Repository๋งŒ์„ ๊ฐ€์ง€๊ณ  ์•„์ฃผ ์‰ฝ๊ฒŒ REST API ์„œ๋ฒ„๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ ์‹œ์ž‘ํ•ด๋ณด๋„๋ก ํ•˜์ฃ .

 

 

๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์ค€๋น„

๊ธฐ์กด์˜ MVC ํŒจํ„ด์„ ์‚ฌ์šฉํ–ˆ๋˜ ๋””ํŽœ๋˜์‹œ์—์„œ ์ผ๋ถ€ ๋ณ€๊ฒฝํ•˜์—ฌ, Rest Repositores ์„ ํƒํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

Spring Data Rest์—์„œ๋Š” base-path๋ฅผ ์ง€์ •ํ•˜์—ฌ ๋ชจ๋“  API ์š”์ฒญ์˜ ๊ธฐ๋ณธ ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ๊ฐ Controller์—์„œ ์ง์ ‘ api ํฌ์ธํŠธ๋ฅผ ์žก์•„์ฃผ์ง€ ์•Š์•„๋„ ๋˜๋Š” ํŽธ๋ฆฌํ•จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

default-page-size๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋”ฐ๋กœ ํŽ˜์ด์ง€ ํฌ๊ธฐ๋ฅผ ์š”์ฒญํ•˜์ง€ ์•Š์•˜์„ ๋•Œ, ์ ์šฉํ•  ๊ธฐ๋ณธ ํŽ˜์ด์ง€ ํฌ๊ธฐ๋ฅผ ์„ค์ •ํ•˜์˜€๊ณ , max-page-size๋ฅผ ํ†ตํ•ด ์ตœ๋Œ€ ํŽ˜์ด์ง€ ๊ฐฏ์ˆ˜๋ฅผ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์ด ์™ธ์—๋„ ๋‹ค์–‘ํ•œ ์˜ต์…˜๋“ค์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฆ„ ์„ค๋ช… ๊ธฐ๋ณธ๊ฐ’
page-param-name ํŽ˜์ด์ง€๋ฅผ ์„ ํƒํ•˜๋Š” ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋ช… ๋ณ€๊ฒฝ page
limit-param-name ํŽ˜์ด์ง€ ์•„์ดํ…œ ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋ช… ๋ณ€๊ฒฝ size
sort-param-name ํŽ˜์ด์ง€ ์ •๋ ฌ๊ฐ’์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋ช… ๋ณ€๊ฒฝ sort
default-media-type ๋ฏธ๋””์–ด ํƒ€์ž…์˜ ๊ธฐ๋ณธ ๊ฐ’ ์ง€์ • application/hal+json;charset=UTF-8
return-body-on-create POST ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•œ ์ƒˆ๋กœ์šด Entity ์ƒ์„ฑ ์ดํ›„ Response Body ๋ฐ˜ํ™˜ ์—ฌ๋ถ€ ์„ค์ • true
return-body-on-update PUT ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•œ Entity ์ˆ˜์ • ์ดํ›„, Response Body ๋ฐ˜ํ™˜ ์—ฌ๋ถ€ ์„ค์ • true
enable-enum-translation 'rest-message' ๋ผ๋Š” property ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์„œ ์ง€์ •ํ•œ enum ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ์„ค์ • ๊ฐ’.
์ ํ•ฉํ•œ enum ๊ฐ’ (DEFAULT, ALL, VISIBILITY, ANNOTATED)๋ฅผ ํ‚ค๋กœ ์‚ฌ์šฉ
 
detection-strategy Repository ๋…ธ์ถœ ์ „๋žต์„ ์„ค์ •ํ•˜๋Š” property ๊ฐ’
Repository Strategy ์ธํ„ฐํŽ˜์ด์Šค ๋‚ด๋ถ€์— ๊ตฌํ˜„๋œ enum ๊ฐ’์œผ๋กœ ์„ค์ •
default

detection-strategy ์˜ต์…˜์˜ ๊ฒฝ์šฐ API๋กœ ๋งŒ๋“ค์–ด์ค„ Repository๋ฅผ ์ฐพ๋Š” ์ „๋žต์ž…๋‹ˆ๋‹ค. Default ์„ค์ •์˜ ๊ฒฝ์šฐ, ๋ชจ๋“  public repository๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•˜๋˜, exported ์˜ต์…˜์ด false์ธ ๊ฒฝ์šฐ๋Š” ์˜ˆ์™ธ๋กœ ๋‘๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. 

Repository ์ „๋žต์„ ์ง€์›ํ•˜๋Š” ์ €์žฅ์†Œ๋Š” ์•„๋ž˜์˜ ๋ฆฌ์ŠคํŠธ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Spring Data JPA
  • Spring Data MongoDB
  • Spring Data Neo4j
  • Spring Data GemFire
  • Spring Data Cassandra

๊ทธ ์ค‘ ์—ฌ๊ธฐ์„œ๋Š” Spring Data JPA๋กœ ๋‹ค๋ฃจ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

 

REST API ๊ตฌํ˜„ํ•˜๊ธฐ

๊ฐœ๋ฐœ ์„ค์ •์ด ๋ชจ๋‘ ๋๋‚ฌ๋‹ค๋ฉด, ๋ฐ”๋กœ REST API๋ฅผ ๊ตฌํ˜„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. 

MVC ํŒจํ„ด ํฌ์ŠคํŠธ์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ๋„๋ฉ”์ธ์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ณ , ์œ„์™€ ๊ฐ™์ด ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— RepositoryRestResource ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€๋งŒ ํ•ด์ฃผ๋ฉด ๋ณ„๋„์˜ Controller, Service ์—†์ด ๋ฏธ๋ฆฌ ๋‚ด๋ถ€์ ์œผ๋กœ ์ •์˜๋˜์–ด ์žˆ๋Š” ๋กœ์ง์— ๋”ฐ๋ผ ์ฒ˜๋ฆฌ๋˜์–ด ๋”์šฑ ์‰ฝ๊ฒŒ REST API ์„œ๋ฒ„๋ฅผ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

Test

MVC ํŒจํ„ด์—์„œ ํ–ˆ๋˜ ๊ฒƒ๊ณผ ๋˜‘๊ฐ™์ด Curl ์ปค๋งจ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

$ curl http://localhost:8080/api/items

๊ธฐ์กด์˜ MVC ํŒจํ„ด์—์„œ ๊ตฌํ˜„ํ–ˆ๋˜ ๊ฒƒ๋ณด๋‹ค ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ๋ณด์ž…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์•„๋ฌด๋Ÿฐ ๋‚ด์šฉ์ด ์—†์œผ๋‹ˆ, content์—์„œ๋Š” target์˜ ํƒ€์ž…์ด ์–ด๋–ค ํŒจํ‚ค์ง€์— ์–ด๋–ค ํด๋ž˜์Šค์ธ์ง€์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋‚˜์˜ค๋Š”๊ตฐ์š”.

 

$ curl -X POST -H "Content-Type: application/json" --data '{ "name": "apple", "price": 3000 }' http://localhost:8080/api/items | json_pp

์ƒํ’ˆ ํ•˜๋‚˜๋ฅผ ์ƒ์„ฑํ•˜๋‹ˆ, MVC ํŒจํ„ด์—์„œ๋Š” ๋ชจ๋ธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด์ค€ ๋ฐ˜๋ฉด, Data Rest์—์„œ๋Š” ๋ฐฉ๊ธˆ ์ƒ์„ฑํ•œ ๋ชจ๋ธ์˜ name๊ณผ price๋ฅผ ํ‘œ์‹œํ•ด์ฃผ๊ณ , ์ด๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ, ์œ„์˜ URI๋ฅผ ์ด์šฉํ•˜๋ผ๋Š” ์ง€์นจ์˜ ๋ฐ˜ํ™˜๊ฐ’์ด ๋‚˜์˜ต๋‹ˆ๋‹ค. MVC ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„ํ–ˆ์„ ๋•Œ๋ณด๋‹ค ๋” ์„ค๋ช…์ด ์ข‹๊ณ , ๊น”๋”ํ•œ ๋Š๋‚Œ์ž…๋‹ˆ๋‹ค.

์ƒํ’ˆ ํ•˜๋‚˜๋ฅผ ์ถ”๊ฐ€ํ•œ ๋’ค์— ๋‹ค์‹œ ๋ชฉ๋ก์„ ์กฐํšŒํ•˜๋ฉด, ํด๋ž˜์Šค์˜ ์ •๋ณด๋Š” ์‚ฌ๋ผ์ง€๊ณ  content ๋‚ด์— ์•„๊นŒ ๋ฐ˜ํ™˜ ๋ฐ›์€ ๋‚ด์šฉ์ด ๋“ค์–ด๊ฐ€ ์žˆ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฒˆ์—๋Š” ์ƒํ’ˆ 10๊ฐœ๋ฅผ ๋“ฑ๋กํ•˜๊ณ , GET ๋ฉ”์†Œ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

$ for i in {1..10}; do curl -X POST -H "Content-Type: application/json" --data '{ "name": "apple", "price": 3000 }' http://localhost:8080/api/items | json_pp; done

Shell script๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐ˜๋ณต๋ฌธ์„ ์ด์šฉํ•ด ์œ„์™€ ๊ฐ™์ด ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜๋ฉด ์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

10๊ฐœ๋ฅผ ๋“ฑ๋กํ•˜๋ฉด 11๊ฐœ๊ฐ€ ๋˜๋ฏ€๋กœ, ์ด์ œ links์—์„œ ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. 10๊ฐœ ์ด์ƒ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ณ ์ž ํ•  ๋•Œ, ์–ด๋–ค ํŽ˜์ด์ง€์˜ URI๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋˜๋Š”์ง€๋ฅผ ์„ค๋ช…ํ•ด์ฃผ๋ฉฐ ์ด๋Š” HATEOAS๋ฅผ ์•„์ฃผ ์ž˜์ง€ํ‚จ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ •๋ณด๋Š” Key-value ํ˜•์‹์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์–ด์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ‚ค๋ฅผ ์ฐธ์กฐํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์„ค์ •ํ•˜๋ฉด ์„œ๋ฒ„์—์„œ ์š”์ฒญ๋œ ๋ฐ์ดํ„ฐ ์ •๋ณด๊ฐ€ ๋ฐ”๋€Œ๋”๋ผ๋„ ํด๋ผ์ด์–ธํŠธ ์ž…์žฅ์—์„œ๋Š” ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†์–ด ๋งค์šฐ ์ข‹์ฃ .

 

 

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

์—ฌ๊ธฐ๊นŒ์ง€ Spring Data Rest๋ฅผ ์ด์šฉํ•˜์—ฌ REST API๋ฅผ ๋งŒ๋“ค์–ด๋ดค์Šต๋‹ˆ๋‹ค. ์•ž์„œ ๋ง์”€๋“œ๋ ธ๋‹ค์‹œํ”ผ Spring Data Rest๋ฅผ ์ด์šฉํ•˜๊ฒŒ ๋˜๋ฉด VC๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•„๋„ Repository์™€ Domain ๋งŒ์œผ๋กœ๋„ ์‰ฝ๊ฒŒ REST API๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์—ˆ๋Š”๋ฐ์š”.

๊ทธ๋ ‡์ง€๋งŒ ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๋“ค์ด ์ด๋Ÿฌํ•œ ํ˜•ํƒœ๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ์›์น˜ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ Spring Data Rest์—์„œ๋„ ๊ฐœ๋ณ„์ ์œผ๋กœ Controller, Service๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ๋Š”๋ฐ์š”. ์ด ๋ถ€๋ถ„์€ ๋‹ค์Œ ํฌ์ŠคํŠธ์—์„œ ๋‹ค๋ค„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•
TAGS.

Tistory Comments