API 호출 시 FetchType.Lazy -> 무한루프

HotFried·2023년 11월 23일

문제 발생!

public class Order {

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

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

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

    @OneToOne(fetch = LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "delivery_id")
    private Delivery delivery;

    private LocalDateTime orderDate; //주문시간

    @Enumerated(EnumType.STRING)
    private OrderStatus status; //주문상태 [ORDER, CANCEL]

위는 Order클래스이다.

@GetMapping("/api/v1/simple-orders")
    public List<Order> ordersV1() {
        return orderRepository.findAllByString(new OrderSearch());
    } 

/api/v1/simple-orders 엔드포인트에 GET 요청을 보내면, 해당 엔드포인트에서 OrderRepository를 통해 검색된 Order 엔터티 목록을 JSON 형식으로 반환하는 코드이다.

물론, 엔티티를 직접 노출하는 것이 좋은 방법은 아니지만 해당 방법을 이용할 때 발생하는 오류에 대해 다뤄보고자 한다.


위와 같이 무한루프가 발생한다!

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

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

    @OneToOne(fetch = LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "delivery_id")
    private Delivery delivery;

Order -> Member -> Order -> Member ...
Order -> OrderItems -> Order -> OrderItems ...
Order -> Delivery -> Order -> OrderItems ...
참조하고 있는 엔티티를 계속 순회하면서 무한루프가 발생하게 되는 것이다.


해결 방법

@JsonIgnore

양방향이 걸리는 곳은 한 쪽에 @JsonIgnore 어노테이션을 이용하면 무한루프를 피할 수 있다.

Member - Order
Delivery - Order
OrderItem - Order

세 가지 경우 모두 한쪽에 @JsonIgnore 어노테이션을 이용하면 된다.

profile
꾸준하게

0개의 댓글