[Spring] 엔티티를 Response에 넣으면?

하원·2024년 7월 3일
post-thumbnail

안녕하세요, 하원입니다.
이번에는 제가 스프링 프로젝트를 하던 도중 발생했던 오류에 대해 소개해 보겠습니다.


요즘 메인으로 참여하고 있는 프로젝트에서 열심히 코딩 중이었는데 Get 메서드 API를 만드는 과정에서 Response 부분에 오류가 발생했습니다.

getPosters라는 전체 Poster를 조회하는 메서드였습니다.

@Getter
@AllArgsConstructor
public class GetPostersResponse {
    private List<Poster> posters;
}

그래서 저는 당연히 List<Poster>ResponseDto를 만들었고...
resolved [org.springframework.http.converter.httpmessagenotwritableexception: could not write json: could not initialize proxy - no session] 라는 오류를 마주치게 되었습니다.

Poster가 엔티티로 선언되어 있었기 때문에 영속성 컨텍스트의 LAZY 로딩으로 인해 위와 같은 오류가 발생한 것이었습니다. OSIV를 사용하지 않아 Service와 Repository만 트랜잭션 범위 안에 해당하기 때문에, Controller에서 Poster 엔티티를 사용할 때는 이미 영속성 컨텍스트가 소멸되어 작업을 할 수 없었던 것이었습니다.

또한, LAZY 로딩(지연 로딩) 방식은 먼저 Proxy 객체로 저장되고 실제로 사용될 때 데이터를 가져오는 방식이기 때문에, 이미 영속성 컨텍스트가 소멸된 Controller 단에서는 사용할 수 없었던 것이었습니다. 그래서 해결 방법을 찾아봤는데 fetch 전략을 LAZY 로딩에서 EAGER 로딩으로 바꾸면 해결된다고 합니다. 하지만 그러면 성능이 나빠져서 의미가 없어지겠죠..?


엔티티를 어떻게 전달해야 할까?

여러 해결 방법을 찾아봤습니다.

  1. LAZY 로딩을 EAGER로 바꾸는 방법
  2. 서비스 단에서 작업을 진행하고 컨트롤러로 반환해 주는 방법
  3. API에서 Response로 보내줄 DTO를 만드는 방법

1번은 앞서 말했듯이 LAZY 로딩을 EAGER 로딩으로 전부 바꿔버리면 성능적으로 좋지 않아 사용하지 않았습니다.
2번 방법을 사용하시는 분들도 있으셨는데 사실.. 시도하다가 계속 오류가 나서 3번으로 넘어가게 되었습니다.

3번을 가장 많이 사용하시는 방법이었는데요, Response로 보내줄 필드만 따로 DTO로 만드는 방법이었습니다.
서비스 단에서 posterRepository.findAll()과 같은 메서드를 호출하면 List<Poster>의 posters가 반환됩니다. 그러면 이 posters를 map 메서드를 이용해 각각의 Poster를 PosterDto에 매핑해 주는 것입니다.

        posterRepository.findAll()
                .map(poster -> new PosterDto(
                        poster.getPosterId(),
                        poster.getTitle(),
						poster.getContent()
        ));

위와 같이 서비스 단에서 PosterDto에 매핑해 주고 컨트롤러로 반환해 주는 것입니다.
또한, 엔티티 자체를 넘겨주는 것은 보안 측면에서도 좋지 않고 API에 필요하지 않은 필드까지 전달될 수 있기 때문에 지양해야 한다고 생각합니다.


Response에는 엔티티를 직접적으로 넣지 말고 DTO로 만들자

이 오류에 대한 해결 방법으로 DTO를 사용해야 한다는 글을 봤을 때, 이전에 김영한 님 강의에서 해주신 조언이 이제야 머리를 스치며 떠올랐습니다..!

그때 분명히 엔티티를 직접 반환하지 않고 DTO를 만들어 전달해 주는 것이 좋다라고 하셨는데 말이죠.. 역시 사람은 경험을 해봐야 학습되나 봅니다.


마무리

프로젝트를 진행하면서 다양한 이슈 사항들을 겪게 되는 것 같다.
강의를 들었을 때는 와닿지 않았던 부분들이 이제서야 하나씩 스며드는 것 같다.
프로젝트를 진행하면서 발생하는 이슈 사항들을 하나씩 포스팅 해봐야겠다.


참고

profile
호기심 저장소

0개의 댓글