문제
해커톤 프로젝트를 진행하다가 JPA로 데이터를 가져오는 과정에서 순환 참조가 문제가 발생하였다.
그에 따라 내부에서 계속해서 순환 참조가 일어난 데이터가 반환되었다.
해커톤 프로젝트 특성상 빠른 개발을 위해 DTO가 아닌 Entity 자체를 response로 리턴 하였다.
해결 방법
1. FetchType.LAZY (지연로딩) (해결X)
- 처음에는 단순하게 지연로딩만을 활용하여 해결할 수 있다고 생각하여 모든 도메인에 참조하는 부분을 FetchType.LAZY로 바꿨다.
- 하지만 그럼에도 똑같은 순환 참조가 일어났다.
- 지연로딩은 JPA가 엔티티를 로드하는 방식에만 영향을 미치고, 직렬화 과정을 제어하지 못 하기 때문에 문제가 해결되지 않았다. (Entity를 response로 리턴하는 과정에서 JSON 직렬화가 필요하고 여기서 순환 참조가 발생하였다.)
2. DTO 사용
- 평소에 프로젝트에서는 순환 참조가 일어나더라도 Client에게는 전달되지 않았는데 왜 전달되었을까?
- 그 이유는 간단했다. Entity 자체를 response로 리턴 하였기 때문에 Client에게도 순환 참조가 일어난 데이터를 그대로 리턴 해 주었기 때문이다.
- DTO를 사용하여 필요한 데이터를 옮겨 Client에게 보여주게 된다면 순환 참조를 Client가 볼 일은 없을 것이다.
3. @JsonIgnore
- @JsonIgnore를 사용하면 직렬화시 특정 필드를 직렬화에서 제외할 수 있다.
- 최종적으로는 JsonIgnore를 사용하여 직렬화 방향을 한 쪽으로만 설정하여 사용하였다.
@Entity
public class Parent {
@Id
private Long id;
private String name;
@OneToMany(mappedBy = "parent")
private List<Child> children;
}
@Entity
public class Child {
@Id
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "parent_id")
@JsonIgnore
private Parent parent;
}