양방향 순환참조 문제
양방향 연관관계를 가진 두 객체가 서로를 참조하고 있어 무한히 서로의 정보를 조회하는 문제
Spring Boot에서 Rest API를 구현할 때 @ResponseBody 어노테이션을 사용하고, 응답 값으로 양방향 연관관계를 가진 객체를 반환하는 과정(JSON 형태로 변환)에서 순환 참조가 계속 발생해 stackoverflow가 발생하는 큰 문제점이 발생하였습니다.
아래는 예제 코드입니다.
@Entity
public class Team {
@Id @GeneratedValue
private Long id;
private String name;
// 양방향
@OneToMany(mappedBy="team")
List<Member> members;
}
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
// 다대일 조인
@ManyToOne
@JoinColumn(name="team_id")
private Team team;
}
회원(Member)과 팀(Team)은 다대일(N:1) 양방향 관계를 가지고 있습니다.
조회한 Member를 응답값으로 반환하는 과정에서 Member가 Team을 참조하고, 참조한 Team에 멤버 변수 Member를 참조하고, 다시 Team을 참조하여 무한히 참조하게 되는 현상입니다. (Member.getTeam() -> Team.getMembers() -> Member.getTeam() -> ...)
해결방법
1. @JsonIgnore
연관관계를 가지는 멤버변수에 @JsonIgnore 어노테이션을 붙이면 해당 변수의 값에는 null이 들어갑니다. 즉, 데이터에서 제외됩니다.
2. @JsonManagedReference 와 @JsonBackReference
부모 클래스(Team)의 members필드에 @JsonManagedReference를, 자식 클래스(Member)의 team필드에 @JsonBackReference를 추가해주면 순환 참조를 막을 수 있습니다.
3. DTO 구현
JPA로 구현된 Entity를 그대로 응답값으로 사용하는 것이 아닌, 응답을 위한 DTO를 따로 구현하여 데이터를 옮기고 반환하는 방법으로 순환참조를 막을 수 있습니다.
'Programming > JPA' 카테고리의 다른 글
[Spring Data JPA] Query를 사용하는 여러가지 방법 (0) | 2022.08.11 |
---|---|
[Spring Data JPA] FetchType - 즉시 로딩(EAGER)과 지연 로딩(LAZY) (0) | 2022.08.04 |
[Spring Data JPA] JPA 연관관계 매핑(JOIN) (0) | 2022.08.02 |
[Spring Data JPA] JPA 주요 어노테이션(Annotation) (0) | 2022.07.31 |
[Spring Data JPA] JPA란? JPA기본 예제 (0) | 2022.07.25 |