ManyToOne, OneToOne 연관관계 조회 최적화 V1(Worst)

KMS·2022년 4월 19일
0

SpringBoot + JPA

목록 보기
9/14

Order -> Delivery를 OneToOne로 연관되어 있으며, Order -> Member는 ManyToOne으로 연관되어 있을때, Order를 통해 연관된 Delivery와 Member도 같이 DB로 부터 값을 가져와서 Response로 보내는 작업입니다.

V1: 엔티티를 그대로 반환하기

	@GetMapping("/api/v1/simple-orders")
    public List<Order> ordersV1() {
        List<Order> all = orderRepository.findAllByCriteria(new OrderSearch());
        
        return all;
        /**
         * 무한으로 값들을 반환한다
         * Order -> Member -> Orders -> Order ...  서로 양방향으로 참조를 하기 때문에 무한으로 서로 참조하고 값을 반환
		*/
    }

엔티티를 그대로 가져오게되면, 무한 루프에 빠져서 끝없는 값을 반환받습니다. 그러한 이유는 모든 엔티티를 양방향에 지연 로딩(FetchType.LAZY)로 설정 했기 때문입니다. 리스트 값을 JSON을 변환하는 과정에서, 처음에 Order를 가져온 후, Order와 연관되어 있는 Member를 가져오고, Member에서 Orders를 가져오는데, 지연 로딩으로 설정 했기 때문에 처음에 Order의 값을 이미 갖고 있는 것을 모르는 상태에서 Orders에서도 다시 이미 가져온 Order를 또 참조하게 됩니다. 그렇기 때문에 결국 무한 루프에 빠지게 됩니다.

해결 방법:
1. 엔티티들을 즉시 로딩(FetchType.EAGER)로 바꾸면 되지만, 이런 경우에는 해당 엔티티를 조회 할때, API 스펙에 필요 없는 연관관계의 값들도 가져오게 되기 때문에 유지 보수도 어려워지며 성능 저하도 발생하기 합니다.
2. API 스펙에 필요 없는 연관관계의 속성에 @JsonIgnore 애노테이션 추가를 하면 되지만, 이럴 경우는 다른 API 스펙에서도 모두 해당 속성 값을 Response로 보내지 못하는 문제가 있습니다.
3. Hibernate5Module 등록해서 사용하시면 됩니다
1,2번 방법은 다른 API 스펙을 모두 변경해야 되는 문제가 생기며, 3번은 외부 모듈을 설치해서 사용해야 되기 때문에 3가지 모두 추천하지 않는 방법으로써, 엔티티를 그대로 가져오고 반환하는 방법은 절대 사용하지 않습니다.
대신, DTO를 생성해서 DTO로 값을 가져오고 반환하는 방법을 추천드립니다.

profile
Student at Sejong University Department of Software

0개의 댓글