코딩과 결혼합니다

230816 - Controller에서 JPA Entity를 반환하면 안되는 이유 본문

2세/Spring

230816 - Controller에서 JPA Entity를 반환하면 안되는 이유

코딩러버 2023. 8. 17. 03:23
728x90

Controller에서 api 응답을 Entity로 하는 경우에 생기는 문제점들에 대한 이해를 하고자 한다.

 

1. 순환 참조 

두 테이블이 양방향 관계로 맺어졌을 때 

  • 컨트롤러에서 @ResponseBody를 통해 응답할 경우 스프링 부트는 HttpMessageConverter로 Jackson 라이브러리를 이용한다.
  • A Entity를 응답으로 내보내려 하면 Jackson의 ObjectMapper는 객체를 Json으로 변환하는데, 이때 영속성 컨텍스트가 살아있기 때문에 양방향 맵핑이 된 다른 B라는 Entity가 영속성 컨텍스트에 있다면 객체 그래프를 탐색할 것이고, 영속성 컨텍스트가 없다면 지연 로딩으로 설정된 프록시를 초기화 하여 직렬화 한다.
  • 또한 영속 상태인 B Entity에서도 맵핑 관계인 A를 직렬화 하기 위해 다시 객체 그래프를 탐색하는 과정이 발생하여 결국 무한으로 순회하게 된다.

2. 오버패칭(overfetching)

클라이언트가 필요로 하지 않는 데이터까지 프론트쪽으로 모두 보냄으로 자원을 낭비하게 된다.

DTO의 사용으로 불필요한 데이터를 사용하지 않을 수 있기에 비효율적인 면을 줄일 수 있다.

 

3. 의존성

repository layer를 제외한 다른 계층에서 특정 기술에 의존성이 생길 수 있다. 스프링에서 추구하는 설계는 내부 기술을 최대한 숨기고 의존성을 줄이는 데 있다. Entity를 계층 간 주고 받는 의존 관계가 강한 설계는 수정을 해야 할때 연관된 다른 많은 곳에서의 수정이 불가피해진다.

 

 

+ 순환참조가 일어났을 때~

  • @JsonIgnore
    • 해당 어노테이션이 붙은 필드는 직렬화되지 않고 null이 할당됩니다.
    • 양방향 순환 참조를 해결하기 위한 용도는 아니고, 해당 필드를 Json으로 직렬화하고 싶지 않은 경우 사용하는 용도입니다.
  • @JsonManagedReference, @JsonBackReference
    • 해당 어노테이션은 순환 참조를 방어하기 위한 어노테이션입니다.
    • @JsonManagedReference는 정상적으로 직렬화를 진행합니다.
    • @JsonBackReference는 직렬화에서 제외합니다.
  • DTO를 사용한다.