JPA 순환 참조 시 StackOverFlow : java.lang.StackOverflowError

bbbooo·2023년 8월 19일

문제 상황

TDD 방식으로 리뷰를 쓰면 댓글을 달 수 있는 기능을 추가하고 댓글이 잘 작성되었는지 확인할려고 print를 할 때였다.

	@DisplayName("댓글 작성 확인")
    @Test
    void CreateComment(){
        Long reviewNo = 1L;
        CreateCommentRequest createCommentRequest = TestObjects.createComment();

        CreateCommentResponse createCommentResponse = commandCommentService.createComment(createCommentRequest, reviewNo);
        Comment comment = commentRepository.findByCommentNo(reviewNo);
        System.out.println("comment = " + comment);
    }

그러자 바로 java.lang.StackOverflowError 라는 문구가 출력되며 코드가 종료되었다. 이유인 즉슨, Comment(댓글)과 Review(리뷰)의 양방향 관계때문에 발생했었다.

//Comment.java
@ToString
@Builder
public class Comment {

	...
    
    @ManyToOne
    @JoinColumn(name = "review_no")
    private Review review;

}

//Review.java
@ToString
@Builder
public class Review extends BaseTimeEntity{

	...
    
    @OneToMany(mappedBy = "review", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Comment> comments;
}

서로 양방향 관계에 있어 서로의 엔티티를 참조하고 있는 상황이다. 이런 엔티티를 출력할려고 할 때, 서로의 @ToString 어노테이션이 서로를 계속 참고하게 되어 결국 스택오버플로우가 일어나는 것이라고 생각한다.

1.comment는 review ToString을 호출함
2. comment에서 순환 참조한 review는 다시 comment ToString을 호출함
3. review에서 순환 참조한 comment는 다시 review ToString을 호출함... 무한 반복

문제 해결

따라서 Comment의 어노테이션을 다음과 같이 수정하였다. @ToString(exclude = "review")

종종 lombok을 남용하지 말라고 들었는데 이번에 그 이유를 확실하게 깨닫게 되었다.

0개의 댓글