2025. 3. 3. 13:19ㆍSpring Framework/Spring HATEOAS
🌐 HATEOAS(Hypermedia as the Engine of Application State) 상세 설명
🔥 1. HATEOAS란?
HATEOAS(Hypermedia as the Engine of Application State)는 REST API의 확장 개념으로,
클라이언트가 별도의 API 문서 없이도 응답 데이터에 포함된 하이퍼링크를 사용하여 동적으로 리소스를 탐색할 수 있도록 하는 기법입니다.
✅ 즉, API 응답에 다음 가능한 액션(링크)을 포함하여, API 사용자가 이를 보고 자연스럽게 API를 활용할 수 있도록 하는 것!
📌 REST API vs HATEOAS
REST API | HATEOAS |
---|---|
요청에 대해 JSON/XML 응답 반환 | 응답에 추가 가능한 링크(URI) 포함 |
API 문서를 따로 확인해야 함 | 응답 자체에 추가 가능한 동작 안내 |
클라이언트가 특정 엔드포인트를 알고 있어야 함 | 클라이언트가 응답을 통해 다음 액션을 동적으로 탐색 |
🎯 2. HATEOAS가 필요한 이유
✅ 1) API 문서가 필요하지 않음
- 일반 REST API는 정적 엔드포인트 목록을 기반으로 동작합니다.
- 하지만 HATEOAS를 사용하면 응답 데이터 자체에 API 탐색 링크가 포함되므로, 클라이언트는 추가 문서 없이 API를 사용할 수 있습니다.
✅ 2) 유연한 API 확장 가능
- API가 확장될 경우 새로운 엔드포인트를 문서화하고 배포하는 과정이 번거로움
- 하지만 HATEOAS가 적용된 API는 서버에서 응답에 포함되는 링크만 변경하면 됨 → 클라이언트 변경이 최소화됨
✅ 3) 클라이언트와 서버의 결합도(Dependency) 감소
- 일반적인 REST API는 클라이언트가 고정된 엔드포인트를 알고 있어야 함
- 하지만 HATEOAS를 사용하면 서버가 제공하는 동적 링크를 기반으로 탐색 가능 → API 변경 시 클라이언트가 쉽게 적응 가능
⚙️ 3. HATEOAS 적용 방법 (Spring Boot)
Spring Boot에서는 Spring HATEOAS 라이브러리를 사용하여 쉽게 구현할 수 있습니다.
🛠 1) Spring HATEOAS 의존성 추가 (pom.xml)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
📝 2) HATEOAS 적용을 위한 모델 생성 (License.java)
import org.springframework.hateoas.RepresentationModel;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class License extends RepresentationModel<License> { // HATEOAS 지원을 위해 RepresentationModel 상속
private int id;
private String licenseId;
private String description;
private String organizationId;
private String productName;
private String licenseType;
}
✅ RepresentationModel<License>
→ Spring HATEOAS에서 제공하는 모델을 상속받아 링크 추가 기능 활성화!
📝 3) 컨트롤러에서 HATEOAS 링크 추가 (LicenseController.java)
import org.springframework.hateoas.Link;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(value = "v1/organization/{organizationId}/license")
public class LicenseController {
@GetMapping(value = "/{licenseId}")
public ResponseEntity<License> getLicense(
@PathVariable("organizationId") String organizationId,
@PathVariable("licenseId") String licenseId) {
License license = new License();
license.setId(1);
license.setLicenseId(licenseId);
license.setOrganizationId(organizationId);
license.setDescription("Software Product");
license.setProductName("Ostock");
license.setLicenseType("full");
// ✅ HATEOAS 링크 추가
Link selfLink = WebMvcLinkBuilder.linkTo(
WebMvcLinkBuilder.methodOn(LicenseController.class)
.getLicense(organizationId, licenseId))
.withSelfRel(); // 현재 리소스에 대한 링크
Link updateLink = WebMvcLinkBuilder.linkTo(
WebMvcLinkBuilder.methodOn(LicenseController.class)
.updateLicense(organizationId, license))
.withRel("updateLicense"); // 라이선스 업데이트 링크
Link deleteLink = WebMvcLinkBuilder.linkTo(
WebMvcLinkBuilder.methodOn(LicenseController.class)
.deleteLicense(organizationId, licenseId))
.withRel("deleteLicense"); // 라이선스 삭제 링크
license.add(selfLink, updateLink, deleteLink); // ✅ HATEOAS 링크 추가
return ResponseEntity.ok(license);
}
@PutMapping
public ResponseEntity<String> updateLicense(
@PathVariable("organizationId") String organizationId,
@RequestBody License request) {
return ResponseEntity.ok("License updated");
}
@DeleteMapping(value = "/{licenseId}")
public ResponseEntity<String> deleteLicense(
@PathVariable("organizationId") String organizationId,
@PathVariable("licenseId") String licenseId) {
return ResponseEntity.ok("License deleted");
}
}
📥 4. HATEOAS 적용된 API 응답 예시
✅ 클라이언트가 /v1/organization/123/license/456
로 GET 요청을 보냈을 때:
{
"id": 1,
"licenseId": "456",
"description": "Software Product",
"organizationId": "123",
"productName": "Ostock",
"licenseType": "full",
"_links": {
"self": {
"href": "http://localhost:8080/v1/organization/123/license/456"
},
"updateLicense": {
"href": "http://localhost:8080/v1/organization/123/license"
},
"deleteLicense": {
"href": "http://localhost:8080/v1/organization/123/license/456"
}
}
}
📝 HATEOAS가 적용된 특징
✅ "_links"
필드에 가능한 액션(URI)들이 포함됨
✅ 클라이언트가 "updateLicense"
링크를 확인하고, 업데이트 API 호출 가능
✅ "deleteLicense"
링크를 참고하여 삭제 API를 호출할 수도 있음
🏆 5. HATEOAS를 사용해야 하는 경우
사용해야 하는 경우 | 사용하지 않아도 되는 경우 |
---|---|
API가 동적으로 변화할 가능성이 높음 | API 구조가 고정되어 있고 변화가 없음 |
클라이언트가 서버 문서를 참고하지 않고 자동으로 API를 탐색해야 함 | 클라이언트가 항상 최신 API 문서를 참고 가능 |
다양한 서비스가 하나의 API를 소비해야 함 | 특정 클라이언트만 API를 사용 |
🎉 6. 결론
✅ HATEOAS는 REST API의 확장 개념으로, 클라이언트가 API 문서 없이도 동적으로 API를 탐색할 수 있도록 지원!
✅ Spring Boot에서는 spring-boot-starter-hateoas
라이브러리를 사용해 간편하게 HATEOAS를 적용 가능
✅ 클라이언트는 API 응답 내 _links
를 참고하여 자동으로 리소스 탐색 가능
✅ API가 확장되거나 변경되더라도 클라이언트는 동적으로 적응 가능 → API의 유지보수성이 향상됨! 🚀
💡 다음 단계 → API 응답을 HAL
또는 JSON:API
표준 형식으로 변환하여 더욱 체계적인 API 제공! 🔥
'Spring Framework > Spring HATEOAS' 카테고리의 다른 글
WebMvcLinkBuilder (0) | 2024.12.11 |
---|---|
_links (0) | 2024.12.11 |
self 링크 (0) | 2024.12.09 |
EntityModel (0) | 2024.12.09 |
RepresentationModel (0) | 2024.12.09 |