Now Loading ...
-
-
-
내가 적어보는 Hateoas 정리
Hateoas
티켓 프로젝트를 진행하면서 rest(ful?) api 문서화를 만드는 중, 우리는 hateoas를 당장 써서 만들어야 할지 아닐지 고민되었다. 그래서 일단 자료조사를 위해서 hateoas에 대해 알아보려고 한다.
Hateoas 란?
Wikipedia에서 ‘hateoas’란 Hypermedia As The Engine of Applicaton state 라는 뜻으로 다른 어플리케이션 아키텍쳐랑 구별되는 REST 어플리케이션 구조 의 요소라고 정의해놨다. hateoas를 사용함으로써 클라이언트는 하이퍼미디어를 통한 다이나믹한 정보를 어플리케이션 서버에 제공하는 네트워크 어플리케이션과 상호작용할 수 있다. 이 제한은 클라이언트와 서버를 분리해주는 것을 도와준다고 말한다.
즉, 쉽게 말해 프론트 부분에서 가공해서 클라이언트한테 지원해줄 필요 없이 hateoas를 사용해 동적으로 상태나 전이를 전달해준다. 이는 더 높은 수준과 rest에 걸맞는 rest(ful?) api를 만들 수 있게 해준다.
Hateoas 사용법
hateos 설정
일단은 의존성을 통해
implementation 'org.springframework.boot:spring-boot-starter-hateoas'
라이브러리를 설정만 해주면 끝난다.
hateoas 사용
예를 들어 내가 보내주고 싶은 ‘AccountDto’가 있다면
AccountCotroller.java
AccountDto accountDto = new AccountDto(); // 예시론 빈 객체 생성인데 보내고 싶은 Dto 부분이라고 생각하면 된다
EntityModel<AccountDto> entityModel = EntityModel.of(accountDto);
entityModel.add(linkTo(AccountController.class).slash(accountDto.getId()).withSelfRel() );
// 자신 컨트롤러와 매핑된 URL, 주어진 accountDto의 Id 값을 가져와 withSelfRel()을 사용해 해당 url이 자기 참조라는 것을 추가해 entityModel에 넣어준다.
entityModel.add(linkTo(AccountController.class).slash(accountDto.getId()).withSelfRel("my") );
// 자신 컨트롤러와 매핑된 URL, 주어진 accountDto의 Id 값을 가져와 withSelfRel()을 사용해 my라는 relation을 만들어준다.
entityModel.add(linkTo(AccountController.class).slash(accountDto.getId()).withSelfRel() );
// 자신 컨트롤러와 매핑된 URL, 주어진 accountDto의 Id 값을 가져와 withRel()을 사용해 self라는 relation을 만들어준다.
entityModel.add(Link.of("/docs/index.html#resources-account-get").withRel("profile"));
// 이 부분은 내가 임의로 지정한 부분에 relation을 만들어 추가해준다 (여기서는 restdocs에 지정한 부분으로 이동하게).
여기서 linkTo()와 Link.of() 두가지가 나오는데, linkTo()는 내가 원하는 Object를 찾아 linkTo()가 제공하는 다양한 기능을 사용해 내가 리턴해줄 url에 추가로 넣어주는 것이고, Link.of()는 new Link로 임의로 url을 만들어 준 뒤 relation을 추가해준다 생각하면 된다.
리턴 방식은
return ResponseEntity.ok(entityModel);
나 다른 ResponseEntity의 함수나 객체를 생성해 던져주면
원래 리턴 값 ResponseEntity.ok(accountDto);
{
"id":1,
"name":"test",
"email":"test@email.com",
"role":"ROLE_USER"
}
Hateoas 적용
{
- "id":1,
- "name":"test",
- "email":"test@email.com",
- "role":"ROLE_USER",
- "_links":{
"self":{
"href":"http://localhost:8080/api/account/1"
},
"profile":{
"href":"/docs/index.html#resources-account-get"
}
}
}
이런 식으로 application/hal+json 으로 된 JSON을 리턴한다.
적용 후기
일단은 매우 기초적으로 hateoas를 적용해서 던져보았는데 좀 더 찾아보면 EntityModel 안에 다양한 기능들이 있고 이걸 사용하면 self, profile 말고 더 많은 url들을 이용해 다양하게 처리할 수 있다. (ex PageResourceAssembler 를 이용해 동적 페이징도 처리 가능하다.)
이렇게 전송되어 보내면 요청에 대한 URL을 던질 때 동적으로 처리할 수 있어 이후에 URL 정보가 변경되더라도 클라는 일일히 가서 수정할 필요가 없다. (허나 예제에선 그 장점이 두각되진 않았다ㅠ)
hateoas를 dto 안에 넣을 수 있을 까
여기서 우리는 ApiResponseDto 안의 data 라는 제네릭 타입에 집어넣은 상태에서 application/hal+json을 유지할 수 있냐이다.
그리고 여러 구글링을 찾아본 결과
hateoas 랑 Dto 관계?
이 스택오버플로우의 이야기 중 “hateoas는 dto을 대체하지 않는다. dto 위에 구축된다. 따라서 Dto 클래스를 확장해야 한다.”
이걸 읽고 만약 hateoas를 적용해야 한다면 ApiResponseDto에 hateoas가 지원하는 Model을 상속받아 구성해야 하는데, 어떻게 뜯어서 진행해야 할지는 팀원들과 이야기 한 다음에 결정해야 할 것 같다.
-
Touch background to close