둘셋 개발!

[API개발과 성능최적화-2] 주문 api 생성 시 성능 최적화 본문

JPA

[API개발과 성능최적화-2] 주문 api 생성 시 성능 최적화

23 2021. 11. 17. 16:15

주문 객체는 회원과 배송정보가 함께 있기 때문에 이때 발생하는 이슈들을 잘 다뤄봐야 한다.

 


 

order객체 mem와 address는 지연로딩으로 설정되어 있기 때문에 order를 불러올 때 이 둘은 프록시 객체가 있다.

그래서 json은 이를 프록시 객체를 어떻게 생성하지 모르기 때문에 Hibernate5Module을 스프링 빈으로 등록시킴.

이렇게 되면 지연로딩은 null로 처리되고 정상적으로 돌아간다.

 

하지만 엔티티를 외부에 그대로 노출시키는 것은 좋지 않다.

 

그래서 해결방법은 DTO를 생성하는 것이다.

 

DTO객체의 생성자


하지만 이때 성능문제가 발생한다.

order.getMember().getName() 과 order.getDelivery().getAddress() 를 할 때 지연로딩이 초기화 된다.

그러면 name과 address가 다를 때마다 쿼리가 나간다.

 

그렇게 되면 1 + N + N 번 쿼리가 시행되는데(이때 1은 orderrepositroy에서 모든 order정보를 꺼낼때 이다.)

이는 성능을 매우 떨어뜨린다.

 


 

이를 해결할 수 있는 방법은 총 2가지가 있다!

 

1. 레포지토리에 멤버와 배송정보를 같이 불러올 수 있는 쿼리를 만든다 (쿼리를 한번에 조회함)

    -> 이때 패치 조인을 사용한다

orderRepository에 있는 함수

2. order에 대한 쿼리를 뽑아내는 repository를 따로만들어 createQuery를 할 때 select절에서 원하는 데이터를 직접 선택

 

 

하지만 리포지토리의 재사용성이 떨어지고, api스팩에 맞춘 코드가 리포지토리에 들어가는 단점이 있다.

 

이 2가지의 방법든 각각 장단점이 있기 때문에 선택을 해야하는데!! 다음은 강사님이 권장하시는 순서이다.

 

1. 우선 엔티티를 DTO로 변환하는 방법을 선택
2. 필요하면 페치 조인으로 성능을 최적화(문제가 90%해결됨)   --- 위의 방법 첫번째
3. 그래도 안되면 DTO로 직접 조회하는 방법을 사용               --- 위의 방법 두번째
4. 최후의 방법은 JPA가 제공하는 네이티브 SQL이나 스프링 JDBC Template를 사용해서 SQL를 직접사용

(참고 : 인프런 김영한 강사님 - 실전! 스프링 부트와 jpa활용2)