Kind of Magic

이전에 DAO λŒ€μ‹  Spring Data JPA 의 JpaRepository λ₯Ό μ‚¬μš©ν•˜μ—¬ DAO λ₯Ό μ‚¬μš©ν•¨μ— 따라 λ°œμƒν•˜λŠ” boiler-plate code 의 문제λ₯Ό ν•΄κ²°ν–ˆλ‹€. 그런데, μ—¬κΈ°μ„œ 더 큰 λ§ˆλ²•μ„ μˆ˜ν–‰ν•  수 μžˆλ‹€.

REST Controller 도 Spring Data REST 에 μ˜ν•˜μ—¬ λŒ€μ²΄λ  수 μžˆλ‹€.

Spring Data REST

Spring Data REST λŠ” μ•„λž˜μ˜ endpoints λ₯Ό μžλ™μœΌλ‘œ expose ν•΄μ€€λ‹€.

HTTP MethodURICRUD Action
POST/employeesCreate a new employee
GET/employeesRead a list of employees
GET/employees/{employeeId}Read a single employee
PUT/employees/{employeeId}Update an existing employee
PATCH/employees/{employeeId}Partially update an employee
DELETE/employees/{employeeId}Delete an existing employee

Spring Data REST λŠ” 기본적으둜 simple plurailized form, 즉 entity type 의 λ³΅μˆ˜ν˜•μ˜ ν˜•νƒœλ‘œ endpoints λ₯Ό expose ν•œλ‹€.

Spring Boot κ°€ μ‹€ν–‰λ˜λ©΄, Spring Data REST κ°€ JPA Repository interface λ₯Ό μŠ€μΊ”ν•˜μ—¬ μžλ™μœΌλ‘œ REST Controller λ₯Ό Proxy ν˜•νƒœλ‘œ μƒμ„±ν•œλ‹€.

μ‚¬μš© 방법은 더 κ°„λ‹¨ν•˜λ‹€. λ‹¨μˆœνžˆ Maven POM file 에 spring-boot-starter-data-rest λ₯Ό μΆ”κ°€ν•΄μ£Όλ©΄ 끝이닀. 더 μ΄μƒμ˜ code λŠ” ν•„μš”ν•˜μ§€ μ•Šλ‹€.

결과적으둜 ν‘œλ©΄μ μΈ Application Architecture κ°€ λ‹€μŒκ³Ό 같이 간단해진닀.

HATEOAS

Spring Data REST μ—μ„œ μžλ™μœΌλ‘œ μƒμ„±λ˜λŠ” endpoints(REST API) λŠ” HATEOAS 원칙을 μ€€μˆ˜ν•œλ‹€.

HATEOAS(Hypermedia As The Engine Of Application State) λŠ” REST API 의 ν•œ ꡬ성 μš”μ†Œλ‘œ,Β Server κ°€ Client μ—κ²Œ data 뿐만 μ•„λ‹ˆλΌ κ·Έ data 와 κ΄€λ ¨λœ 좔가적인 행동(λ‹€μŒμ— ν˜ΈμΆœν•  수 μžˆλŠ” API link λ“±)에 λŒ€ν•œ 정보λ₯Ό Hypermedia(link) ν˜•νƒœλ‘œ ν•¨κ»˜ μ œκ³΅ν•˜λŠ” κ°œλ…μ΄λ‹€.

즉, Client κ°€ Server 의 response λ₯Ό 받을 λ•Œ, λ‹¨μˆœνžˆ data 만 λ°›λŠ” 것이 μ•„λ‹ˆλΌ κ·Έ μƒνƒœμ—μ„œ μ·¨ν•  수 μžˆλŠ” λ‹€λ₯Έ 행동(예: update, delete, λ‹€μŒ νŽ˜μ΄μ§€ 이동 λ“±)에 λŒ€ν•œ URI link 도 ν•¨κ»˜ λ°›μ•„, Client κ°€ λ³„λ„μ˜ API document λ₯Ό λ³΄μ§€μ•Šκ³ λ„ Server 와 dynamic ν•˜κ²Œ μƒν˜Έμž‘μš©ν•  수 있게 ν•΄μ€€λ‹€.

예λ₯Ό λ“€μ–΄, 기쑴의 REST reqest κ°€ λ‹€μŒκ³Ό κ°™λ‹€λ©΄,

{
  "id": 10,
  "subject": "κ²Œμ‹œκΈ€ 10",
  "content": "λ‚΄μš©"
}

HATEOAS κ°€ 적용된 request λŠ”

{
  "id": 100,
  "subject": "κ²Œμ‹œκΈ€ 10",
  "content": "λ‚΄μš©",
  "_links": {
    "self": { "href": "https://api.example.com/articles/10" },
    "next": { "href": "https://api.example.com/articles/11" },
    "comment": { "href": "https://api.example.com/articles/10/comments"}
  }
}
 

κ³Ό κ°™κΈ° λ•Œλ¬Έμ—, 이처럼 request 에 ν¬ν•¨λœ link λ₯Ό 따라 Client κ°€ μ‰½κ²Œ State Transition, 즉 νŽ˜μ΄μ§€ λ‚΄μ—μ„œ λ‹€λ₯Έ 행동을 ν•˜λ„λ‘ 도와쀀닀.

Redirection ν•˜κ³ λŠ” λ‹€λ₯Έ 것이, Redirection 은 Server κ°€ Client λ₯Ό μžλ™μœΌλ‘œ λ‹€λ₯Έ URL 둜 μ΄λ™μ‹œν‚€λ‚˜, HATEOAS λŠ” response 에 link(href) λ₯Ό ν¬ν•¨μ‹œμΌœ Client κ°€ 직접 μ΄λ™ν•˜κ²Œ ν•˜λŠ” 것이닀.

λ§Œμ•½ GET /employees 와 같이 collection, 즉 μ—¬λŸ¬ 개의 data λ₯Ό request ν•˜λŠ” 것에 λŒ€ν•œ response μ—λŠ” 기쑴의 data 뿐만 μ•„λ‹ˆλΌ, page size, total elements, totalPages λ“±μ˜ meta-data 도 response 에 ν¬ν•¨λœλ‹€. μ΄λŠ” Pagination(page 이동, λ‹€μŒ/이전 νŽ˜μ΄μ§€) 을 κ΅¬ν˜„ν•˜κ±°λ‚˜, 전체 data 양을 νŒŒμ•…ν•˜λŠ” 데 도움이 λœλ‹€.

Advanced Features

Spring Data REST 의 advanced features λŠ” λ‹€μŒκ³Ό κ°™λ‹€.

  1. Pagination, sorting and searching
  2. Extending and adding custom quries with JPQL
  3. Query Domain Specific Language (Query DSL)
Spring Data REST - Test

μœ„μ™€ 같이 GET /employees endpoint κ°€ expose 된 것을 λ³Ό 수 μžˆλ‹€.

application.properties 에 λ‹€μŒ property λ₯Ό μΆ”κ°€ν•˜μ—¬ base path 도 λ³€κ²½ κ°€λŠ₯ν•˜λ‹€.

spring.data.rest.base-path=/magic-api

μœ„μ™€ 같이 λ³€κ²½λœ base path 에 λŒ€ν•˜μ—¬ POST method 도 잘 μ μš©λœλ‹€.

λ˜ν•œ, PUT μ΄λ‚˜ PATCH method λ₯Ό μ‚¬μš©ν•  λ•Œ, Spring Data REST λŠ” id λ₯Ό 였직 URL μ—μ„œλ§Œ μ‚¬μš© κ°€λŠ₯ν•˜λ‹€. λ§Œμ•½ id 값을 request body 에 ν¬ν•¨μ‹œν‚¨λ‹€λ©΄, 이에 λŒ€ν•œ μœ„ν—˜μ„±μ€ μ—¬κΈ°μ„œ 확인 κ°€λŠ₯ν•˜λ‹€. λ‹¨μˆœν•˜κ²Œλ§Œ μ„€λͺ…ν•˜λ©΄, Client κ°€ κ³ μ˜μ μœΌλ‘œλ‚˜ μ‹€μˆ˜λ‘œ κΈ°μ‘΄ data λ₯Ό λ³€κ²½μ‹œν‚¬ 수 있기 λ•Œλ¬Έμ΄λ‹€.

μœ„μ™€ 같이 PUT method 도 잘 μž‘λ™ν•˜λŠ” 것을 λ³Ό 수 μžˆλ‹€.

PATCH 도 잘 μž‘λ™ν•˜λ©°, μ•„λž˜μ™€ 같이 DELETE 도 μ„±κ³΅μ μœΌλ‘œ μž‘λ™ν•œλ‹€.

DELETE μ—μ„œ, μ΄μ „μ˜ Spring Boot version μ—μ„œλŠ” default 둜 204 No Content λ₯Ό return ν•˜μ˜€μ§€λ§Œ, 졜근의 Spring Boot version μ—μ„œλŠ” 200 OK λ₯Ό default 둜 return ν•œλ‹€.

졜근 Spring Boot λ₯Ό κΈ°μ€€μœΌλ‘œ, request header 의 Accept variable 이 μ‘΄μž¬ν•˜μ§€ μ•Šμ„ λ•Œλ§Œ 204 No Content λ₯Ό return ν•˜κ±°λ‚˜ λ³„λ„μ˜ configuration 을 ν†΅ν•˜μ—¬ return 값을 ν•  수 μžˆλ‹€. λ³„λ„μ˜ configuration 및 더 μžμ„Έν•œ λ‚΄μš©μ€ μ—¬κΈ°μ„œ 확인할 수 μžˆλ‹€.

Postman 을 ν†΅ν•˜μ—¬ Accept variable 을 μ„€μ •ν•˜μ§€ μ•ŠμœΌλ©΄ μ•„λž˜μ™€ 같이 204 No Content κ°€ return λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€.