본문 바로가기

Tech/Spring

[Spring] Could not write JSON: Infinite recursion (StackOverflowError) 이슈

상황

스프링 기반 API 서버를 구현 프로젝트에서 Controller 테스트를 하는 도중 에러가 발생했다.

nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError)

 

에러 로그를 확인해 보니 Could not write JSON: Infinite recursion (StackOverflowError) 부분을 통해 재귀 호출로 인해 StackOverflow가 발생한 것을 알 수 있었다.

 

현재 테스트하고 있는 부분은 채팅 기능 관련 api로

채팅방 식별자를 기준으로 채팅방에 속한 메시지를 불러오는 과정에서

채팅방(ChatRoom)과 채팅메시지(ChatMessage)라는 두 엔티티가 양방향 연관 관계에 놓여있어 JSON으로 포맷팅하는 과정에서 무한 순환 참조가 되는 것이 주요 원인이었다.

 

 

 

해결방법

1. @JsonIgnore

가장 간단해 보이는 방법이었다. 이 어노테이션을 붙여주면 해당 프로퍼티의 값은 null이 되어, 데이터가 들어가지 않는다.

 

 

2. @JsonMangedReference와 @JsonBackReference

@JsonIgnore와 같이 어노테이션을 붙여 해결하는 방법이다. 부모가 되는 엔티티에서 자식 엔티티 필드에 @JsonManagedRefernce를 , 자식 엔티티에서 부모 엔티티 필드에 @JsonBackReference를 붙인다. @JsonManagedReference를 사용하는 클래스에서는 해당 부분을 정상적으로 직렬화를 수행하고, @JsonBackReference를 사용하는 클래스에서는 직렬화를 수행하지 않게 된다.

 

채팅방과 채팅메시지 관계로 예를 들면 다음과 같다.

 

[ChatRoom.java]

 @JsonManagedReference
 @OneToMany(mappedBy = "chatRoom", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
 private List<ChatMessage> messages = new ArrayList<>();

[ChatMessage.java]

@JsonBackReference
@ManyToOne
@JoinColumn(name = "room_id")
private ChatRoom chatRoom;

 

 

 

3. DTO 사용

문제의 근원은 순환참조이긴 하지만 엔티티 자체를 응답 결과로 리턴하려다보니 이런 이슈가 발생하는 것이기도 하다. DTO와 같이 별도의 데이터 전달 객체로 맵핑하여 리턴을 하여 문제를 해결할 수 있다고 한다. 1,2번 방식대로 순환참조를 방지하도록 하는 것도 중요하지만, 엔티티를 직접 리턴하여 데이터를 전달하기에는 민감한 정보까지 넘겨줄 우려가 있기 때문에 DTO로 맵핑하는 과정이 필요해 보인다.

 

 

 

[참고]

 

JPA에서 순환참조를 해결하는 방법 | @JsonIgnore, @JsonManagedReference, @JsonBackReference

 JPA는 ORM이기 때문에 RDB를 관리하는데 있어서 양방향 참조를 필요로 한다. 물론 필수는 아니지만 Entity는 본질적인 데이터를 표현하는 것이기 때문에 그 관계에 대하여 명세해주는 것이 원칙이

binarycube.tistory.com

 

[JPA] 순환참조와 해결 방법 @JsonIgnore, @JsonManagedReference, @JsonBackReference

실무에서 개발을 진행하다가 희안한 현상을 맞닥뜨렸다.JPA를 사용하여 개발을 진행하면서 여러 Entity...

blog.naver.com

 

20190720 [문제해결] Infinite recursion (StackOverflowError)

JPA 엔티티, JSON 변환 에러 org.springframework.http.converter.HttpMessageNotWritableException Could not write JSON Infinite recursion (StackOverflowError) nested exception is com.fasterxml.jack..

pasudo123.tistory.com

 

반응형