Entity 직접 노출
주문, 배송 정보, 회원의 조회 API 개발한다.
지연 로딩으로 발생하는 성능 문제를 단계적으로 해결한다.
무한 루프
API를 요청하면 무한 루프를 돈다.
Order와 Member가 서로를 참조하고 있기 때문이다.
Order에 Member가 있어서 들어가보면 Member에 Order가 있고...
jackson이 무한 루프를 돌면서 계속 객체를 만든다.
@JsonIgnore
양방향이 걸리는 곳은 모두 한 쪽에
@JsonIgnore
를 붙여야 피할 수 있다.Order - Member
Delivery - Order
OrderItem - Order
지연 로딩 객체
이번에는 bytebuddy 예외가 발생한다.
member는 지연 로딩으로 가져오게 되어있다.
DB에서 가져올 때는 order 데이터만 가져온다.
member에는 프록시 객체를 생성해서 넣어둔다.
이때 쓰는 라이브러리가 예외에 나온
bytebuddy
다.
jackson 라이브러리가 member를 변환하려는 순간, 프록시 객체를 json으로 어떻게 생성할지 몰라 에러를 낸 것이다.
Hibernate5Module
Hibernate5Module
을 스프링 빈으로 등록하면 해결된다.
지연 로딩 때문에 member, orderItems, delivery는 null로 출력된다.
FORCE_LAZY_LOADING
FORCE_LAZY_LOADING
강제로 지연 로딩하면서 제대로 된 데이터가 반환된다.
양방향 연관 관계를 계속 로딩하기 때문에
@JsonIgnore
를 꼭 한쪽에 추가해줘야 한다.
하지만 이렇게 강제로 모든 데이터를 로딩하는 옵션은 좋지 않다.
API 스펙 상 필요 없는 데이터까지 노출된다.
추가로 데이터를 끌고 오면서 성능에도 문제가 발생한다.
직접 조회
get()을 통해 지연 로딩된 객체를 직접 조회하게 하면
FORCE_LAZY_LOADING
없이 불러올 수 있다.
정리
Entity를 API 응답 형태로 외부에 노출하면 안된다.
DTO로 변환해서 반환하자.
지연 로딩을 피하려고 즉시 로딩을 설정하면 안된다.
연관 관계가 필요없는 경우에도 항상 모든 데이터를 조회하면서 성능 문제가 발생한다.
연관된 데이터를 다 조회하면서 N+1 문제가 터진다.
즉시 로딩으로 설정하면 성능 튜닝이 매우 어려워진다.
항상 지연 로딩을 기본으로 하자.
성능 최적화가 필요하면 fetch join을 사용하자.
Last updated