- 이번 포스팅부터 단일 객체를 조회하는 API 성능을 최적화 하는 방식에 대해서 알아 볼 예정이다.
- 여기서 단일 객체란 Many To One 또는 One To One 관계를 가지는 객체를 의미한다.
- 단일 객체를 조회하는 방식에는 Entity 직접 노출, DTO 변환, DTO 직접 사용 방식이 있다.
- 이에 대해 하나씩 알아보자.
1. Entity 직접 노출 방식의 문제점과 해결방법
- 결론부터 말하면, 이 방식은 사용하지 않는다.
- Entity를 직접 노출하는 방식은 Entity의 내용 변동이 있는 경우, API 스펙에도 변경사항이 발생하기 때문이다.
- 즉, API 스펙에 영향을 끼치는 구조이므로 사용하지 않는다.
- 다만, Entity 직접 노출 방식을 사용하지 않는 이유에 대해서 이해할 수 있다.
a) 양방향 관계와 무한 루프
- 양방향 연관 관계를 형성하는 객체를 조회할 때에는 무한 루프가 발생한다.
- 예를 들어, 객체 A와 B가 양방향 연관 관계라고 해보자.
- 객체 A의 값을 조회하는 경우, 객체 A를 타고 객체 B에 들어간다. 그리고 다시 객체 B 내부에서 객체 A를 타고 들어간다.
- 이 과정이 반복되면서 무한 루프를 생성하게 된다.
b) @JsonIgnore
- 양방향 관계 조회 시 발생되는 무한 루프를 예방하기 위해서 @JsonIgnore를 사용한다.
- 양방향 관계 중 한쪽 필드에 @JsonIgnore를 부착하여 무한 루프를 방지하는 것이다.
- 객체 A를 조회한다면 일반적으로 객체 B 내부의 양방향 관계 필드에 @JsonIgnore를 부착한다.
c) @JsonIgnore의 문제점
- 양방향 관계라는 이름 그대로, 양쪽에서 조회하기 위해 형성된 관계다.
- 서비스의 기능에 따라 양방향 관계를 맺더라도 단방향의 조회 API만을 필요로 할 수 있다.
- 그러나 양방향 조회 API를 필요로 하는 경우, @JsonIgnore의 사용은 문제가 된다.
- @JsonIgnore가 부착된 필드는 애초에 조회 대상에서 제외되기 때문이다.
- 이 문제의 해결책으로 Hibernate5 Module 라이브러리를 사용한다.
d) Hibernate5 Module 사용 예시 - 연관 객체 제외
- 우선 Gradle과 같은 빌드 자동화 도구의 설정 파일에 Hibernate5 Module을 설치한다.
- 연관 객체의 값을 필요로 하지 않는 경우, 다음과 같이 사용한다.
@SpringBootApplication
public class JpabookApplication {
public static void main(String[] args) {
SpringApplication.run(JpabookApplication.class, args);
}
@Bean
Hibernate5Module hibernate5Module() {
return new Hibernate5Module();
}
}
- 위의 사진처럼, 연관 객체의 값에는 null이 들어간 것을 확인할 수 있다.
- 연관 객체는 기본적으로 LAZY를 사용하기 때문에 Proxy 객체가 할당되므로 Null 값으로 표현된다.
e) Hibernate5 Module 사용 예시 - 연관 객체 포함
- 연관 객체의 값까지 조회하는 경우, 다음과 같이 사용한다.
@SpringBootApplication
public class JpabookApplication {
public static void main(String[] args) {
SpringApplication.run(JpabookApplication.class, args);
}
@Bean
Hibernate5Module hibernate5Module() {
Hibernate5Module hb = new Hibernate5Module();
hb.configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, true);
return hb;
}
}
- 위의 코드에서 사용된 옵션은 강제적으로 LAZY 로딩을 실행시킨다.
- 위의 사진처럼, 모든 연관 객체의 데이터까지 조회되는 것을 확인할 수 있다.
f) Hibernate5 옵션 없이 Lazy 실행하는 방법
- Lazy를 실행시키는 방법은 Lazy가 걸려있는 필드의 데이터를 직접 호출하는 것이다.
- 객체에 접근하여 직접 해당 필드를 호출하는 방식으로 다음과 같이 코드를 작성한다.
@GetMapping("api/v1/simple-orders")
public List<Order> ordersV1() { // Entity 노출 방식
List<Order> all = orderRepository.findAllByString(new OrderSearch());
// Hibernate5 옵션(Force_Lazy_Loading) 없이 Lazy 로딩 시키는 방법
// => LAZY 옵션이 걸려있는 데이터를 직접 호출한다.
for(Order order : all) {
order.getMember().getName();
order.getDelivery().getAdderss();
}
return all;
}
'Back-end > JPA 개념' 카테고리의 다른 글
API 조회 성능 최적화 - DTO 직접 조회 (0) | 2022.05.30 |
---|---|
API 조회 성능 최적화 - DTO 변환 방식(Fetch Join) (0) | 2022.05.30 |
JPA를 이용한 API 개발 꿀팁 - Annotation (0) | 2022.05.27 |
JPA 개발 꿀팁 (0) | 2022.05.25 |
35. JPQL - 벌크 연산 (0) | 2022.05.08 |
댓글