본문 바로가기

CS 잡지식

[양방향] 설정으로 인해 발생할 수 있는 치명적인 JPA 버그(매우 매우 중요)

@RestController
@RequiredArgsConstructor
public class OrderSimpleApiController {

    // 이 Controller는 DB에 있는 정보를 [조회]해와서 뿌리는 API용이다.
    // 즉, 회원 가입 등의 기능을 여기서 필요로 하지 않기에 Service 계층을 거치지 않아도 된다.
    private final OrderRepository orderRepository;

    @GetMapping("/api/v1/simple-orders")
    public List<Order> ordersV1(){

        List<Order> findOrders = orderRepository.findAllByString(new OrderSearch());
        return findOrders;

    }

이 API를 호출했다고 해보자. 

DB로부터 Order객체, 그리고 Order 객체와 연관 관계에 있는 엔티티들도 join 연산을 통해 같이 조회해서 JSON으로 반환

을 할 것이다. 

@Entity
@Table(name = "ORDERS")
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order {

    @Id@GeneratedValue
    @Column(name = "order_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="member_id")
    private Member member;


    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> orderItems = new ArrayList<>();
    
    //이하 생략

Member 클래스를 타고 들어가 보자

@Entity
@Getter
@Setter
public class Member {

    @Id@GeneratedValue
    @Column(name = "member_id") 
    private Long id;

    @NotEmpty
    private String name;

    @Embedded 
    private Address address; 

    @JsonIgnore 
    @OneToMany(mappedBy = "member") 
    private List<Order> orders = new ArrayList<>(); // 또 Order 객체가 있다. 


}

Member와 Order 사이의 [양방향] 설정 관계로, Meber 클래스에 또 Order 객체가 들어 간다. 

-> 객체를 JSON으로 만드는 JACKSON 라이브러리 입장에서는, 

Order 엔티티 탐색 -> Member 엔티티 탐색 -> Order 엔티티 탐색-> Member 엔티티 탐색 -> Order 엔티티 탐색 ,,,,,,,

즉, 무한 루프에 빠지게 되서, API를 호출하면 무한으로 JSON을 반환 받게 된다. 

양방향 설정은 이러한 [무한 루프] 문제를 일으킬 수도 있다.

 

결론 : Order 객체 내의 [양방향] 관계인 연관 관계 객체에는 모두 @JSONIgnore을 붙여 주자.