Hello

[Spring HATEOAS] 유저 정보 관리에 적용해본 내용 정리 본문

spring

[Spring HATEOAS] 유저 정보 관리에 적용해본 내용 정리

nari0_0 2024. 5. 13. 15:35
728x90

Spring HATEOAS(Hypermedia As The Engine Of Application State)는 RESTful 서비스에서 하이퍼미디어를 쉽게 구현할 수 있도록 도와주는 라이브러리입니다. 하이퍼미디어는 클라이언트가 서버의 리소스와 상호작용할 수 있는 링크를 포함하여, API의 탐색성을 높여줍니다.

 

Spring HATEOAS를 사용한 이유는 유저 정보가 많고, 대부분의 정보가 변경이 필요 했기 때문입니다. 화면에서는 각 기능에 대한 URL을 받아 쉽게 처리할 수 있어  클라이언트가 링크를 통해 API를 탐색하고, 작업을 수행할 수 있습니다.

유저 정보 관리가 더 효율적이고 직관적으로 관리할 수 있을 것 같아 Spring HATEOAS적용을 고려하고, 적용하게 되었습니다. 

 

spring v 2.2.2사용

UserModel 클래스 정의

- RepresentationModel은 Spring HATEOAS에서 하이퍼미디어 링크를 추가할 수 있는 기본 클래스입니다.

public class UserModel extends RepresentationModel<UserModel> {
    private String id;
    private String imgUrl;
    private String nickName;
    private Boolean isLogin;
    // 생략..
    // Getters and Setters
}

UserService 클래스 정의

- 유저 정보를 조회해 UserModel로 변환 합니다.

@Service
public class UserService {
	@Autowired
    private UserRepository userRepository;

    public User findUserById(String id) {
        return userRepository.findById(id)
                .orElseThrow(() -> new UserNotFoundException("User not found with id: " + id));
    }

    public List<User> findAllUsers() {
        return userRepository.findAll();
    }

    public UserModel getUserModel(String id) {
        User user = findUserById(id);
        UserModel model = new UserModel();
        model.setId(user.getId());
        //..
        
        Class<UserRestController> controllerClass = UserRestController.class;        
        model.add(linkTo(methodOn(controllerClass).getUser(id)).withSelfRel());
        model.add(linkTo(methodOn(controllerClass).editNickName(id, null)).withRel("nick-name"));
        if (model.getIsLogin()) {
            model.add(linkTo(methodOn(KickRestController.class).kickId(id)).withRel("user-kick")
                    .withType("confirm")
                    .withName("KICK")
                    .withTitle("유저를 강퇴하시겠습니까?" + user.getId()));
        }
        //..
        return model;
    }
}

 

단일 리소스를 반환할 때는 EntityModel 클래스를 사용하고, 여러 리소스를 반환할 때는 CollectionModel 클래스를 사용합니다. UserModel을 EntityModel과 CollectionModel로 변환하는 방법을 살펴보겠습니다.

EntityModel

    @GetMapping("/user/{id}")
    public EntityModel<UserModel> getUser(@PathVariable String id) {
        UserModel userModel = userService.getUserModel(id);
        return new EntityModel<>(userModel);
    }

CollectionModel

    @GetMapping("/users")
    public CollectionModel<EntityModel<UserModel>> getAllUsers() {
        List<User> users = userService.findAllUsers();
        List<EntityModel<UserModel>> userModels = users.stream()
                .map(user -> {
                    UserModel userModel = new UserModel();
                    userModel.setId(user.getId());
                    userModel.setProfileUrl(user.getProfileUrl());
                    userModel.setNickName(user.getNickName());
                    userModel.setIsLogin(user.isLogin());

                    EntityModel<UserModel> entityModel = new EntityModel<>(userModel);
                    entityModel.add(linkTo(methodOn(UserRestController.class).getUser(user.getId())).withSelfRel());
                    return entityModel;
                })
                .collect(Collectors.toList());
        return new CollectionModel(userModels);
    }

 

응답 JSON에 _links 필드가 추가되어 관련 링크 정보를 포함하게 됩니다

예시)

{
  "_links" : {
    "self" : { "href" : "..." }, 
    "nickName" : { "href" : "..." } 
  }
}

 

정리.

  1. 링크 추가: HATEOAS의 핵심은 리소스에 관련 링크를 추가하는 것입니다. 이를 통해 클라이언트가 API의 다른 부분을 탐색할 수 있도록 합니다. Spring HATEOAS에서는 Link 클래스와 WebMvcLinkBuilder를 사용하여 링크를 생성하고 리소스에 추가할 수 있습니다.
    1. linkTo와 methodOn 메서드를 사용하여 링크를 작성합니다. ex) editNickName 메서드
  2. RepresentationModel 사용: Spring HATEOAS는 리소스를 표현하기 위해 RepresentationModel 클래스를 제공합니다. 이 클래스를 상속받아 리소스 모델을 만들고, 링크를 추가하여 클라이언트에게 전달할 수 있습니다.

+) RepresentationModelAssemblerSupport

RepresentationModelAssemblerSupport를 확장하여 UserModel EntityModel로 변환하는 어셈블러 클래스를 작성하면 작성해야 하는 코드 양을 줄이는 데 도움이 됩니다.

 

참고 : https://docs.spring.io/spring-hateoas/docs/current/api/org/springframework/hateoas/IanaLinkRelations.html

https://docs.spring.io/spring-hateoas/docs/current/reference/html/#mediatypes

https://docs.spring.io/spring-hateoas/docs/current/api/org/springframework/hateoas/EntityModel.html

https://howtodoinjava.com/spring/spring-hateoas-tutorial/

728x90