Study/JPA

[JPA] @JsonIgnore, @JsonManagedReference, @JsonBackReference

오늘만 사는 여자 2022. 3. 26. 23:24
728x90
반응형

순환 참조 발생

JPA는 디폴트로 맵핑된 데이터에 대해 FetchType.LAZY(게으른 불러오기)를 사용하게 된다.

예를 들어, User라는 Entity와 Acoount라는 Entity가 서로 양방향 참조 (1 :N)를 하고 있다고 해보자.

 

public class User{
	@Id
    privte long user_id;
    
    ..생략
    
    @OneToMany(mappedBy = "user")
    private List<Account> accounts;
}
public class Account{

	@Id
    private long id;
    
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}

JUtil을 통한 테스트 에서는 AccountRepository를 사용하여 return된 List의 사이즈가 1인지만 체크했다. 그 List에 포함된 

Account를 꺼내서 따로 다른 작업을 하지 않았기  때문에 Account가 참조하고 있는 User Entity 

는 전혀 건드리지 않은것이다.

 

하지만, Controller를 통해 Acoount Entity를 Response로 내보내고 브라우저 json형태로  뿌려주기 위해서는 Account entity 가 참조하고 있는 User entity도 함께 불러오게 된다.

그런데, 여기서 문제가 발생한다. User Entity 는 다시 Account Entity를 참조하기 때문에 또 Account Entity를 불러오는 것이다. Repository에서는 Account Entity한개를 Return 했지만 Controller 를 통해 Response 되어 Json으로 표시될 때는 이렇게 두 개의 entity 가 계속해서 서로를 불러오면서 페이지 가득 똑같은 데이터가 중복되어 노출된 것이다.

 

 

해결 방법

1. @JsonIgnore : 이 어노테이션을 붙이면 json 데이터에 해당 프로퍼티는 null로 들어가게 된다. 즉, 데이터에 아예 포함이 안되게 된다.

2. @JsonManagedReference 와 @JsonBackReference : 이 두개의 어노테이션이야 말로 순환참조를 방어하기 위한 Annotation이다. 부모 클래스에 @JsonManagedReference를, 자식 클래스측 에 @JsonBackReference 어노테이션을 추가해주면 된다.

3. DTO 사용 : 위와 같은 상황이 발생하게 된 주 원인은 양방향 매핑이기도 하지만, 더 정확하게는 entity 자체를 response로 리턴한데에 있다. entity 자체를 return하지 말고, dto 객체를 만들어 필요한 데이터만 옮겨 담아 client로 리턴하면 순환참조와 관련된 문제는 애초에 방어할 수 있다.

4. 맵핑 재설정 : 사람마다 다르지만 양방향 맵핑이 꼭 필요한지 다시 한번 생각해볼 필요가 있다. 만약 양쪽에서 접근할 필요가 없다면 단방향 맵핑을 하면 자연스레 순환참조가 해결된다.

 

 

출처 : https://m.blog.naver.com/writer0713/221587351970

 

728x90
반응형