본문 바로가기
Study/JPA

[JPA] @JsonIgnore, @JsonManagedReference, @JsonBackReference

by 오늘만 사는 여자 2022. 3. 26.
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
반응형

'Study > JPA' 카테고리의 다른 글

[JPA] 벌크연산  (0) 2022.03.30
[JPA] Spring JPA CascadeType 종류  (0) 2022.03.28
[JPA] DTO, Domain(Entity)  (0) 2022.03.26
Spring Data JPA에서 Query를 사용하는 방법  (0) 2022.03.15
[JPA] Executing an update/delete query  (0) 2022.03.13

댓글