본문 바로가기
Back-end/JPA 개념

33. JPQL - Fetch Join의 한계

by devraphy 2022. 5. 6.

0. 개요

- 이번 포스팅에서는 Fetch Join의 한계에 대해서 알아보자.

 

 

1. Fetch Join의 한계

- Fetch Join 사용 시, 하지 못하는 것 또는 하면 안 되는 것에 대해서 알아보자.

 

 

a) 별칭, Where 절 사용 금지

- Fetch Join을 사용할 때에는 별칭과 Where 절을 사용하지 않는 것을 권장한다. 

 

- 첫 번째 이유는 Fetch Join의 역할 또는 정의를 위배하기 때문이다.

- Fetch Join은 연관된 Entity를 모두 조회한다는 정의를 가지고 있다.

- 그러나 Where 절을 통한 필터링은 Fetch Join의 결과 값에 변화를 주게 된다.

- 즉, 연관된 Entity를 모두 조회한다는 역할이 필터링을 사용함으로써 변질되는 것이다.

 

- 두 번째 이유는 데이터 무결성을 위배하기 때문이다.

- DB의 측면에서 Fetch Join의 결과가 3개라면 JPA에서도 3개의 데이터를 사용해야 한다.

- 그러나 Where 절을 통해 필터링된 데이터가 1개라면 JPA에서는 Fetch Join의 결과로 1개의 데이터를 사용한다.

- 즉, DB와 JPA의 데이터 싱크가 맞지 않게 되므로 데이터 무결성이 위배된다. 

 

- 예외적으로, 재귀적인(= 연속적인) Fetch Join을 사용하기 위한 경우 별칭의 사용을 허가한다.

- 재귀적인 Fetch Join은 데이터 무결성 또는 Fetch Join의 정의를 위배하지 않기 때문이다.

 

- 결론으로, Fetch Join과 Where 절을 함께 사용하지 말고 일반적인 Join을 사용하면 된다. 

 

 

b) 둘 이상의 컬렉션은 Fetch Join 할 수 없다.

- 상황에 따라 다르지만 두 컬렉션의 Fetch Join은 컬렉션 * 컬렉션의 결과를 만든다.

- 즉, 카테시안 곱의 결과를 만들어낸다. (조회 데이터가 엄청나게 증가한다.)

 

- Hibernate 사용 시, 둘 이상의 컬렉션을 사용한 Fetch Join은 오류를 발생시킨다.

- 그러므로 사용하지 말자.

 

 

c) Collection Fetch Join은 페이징을 사용할 수 없다.

- 일대일(OneToOne), 다대일(ManyToOne)의 경우 Fetch Join과 페이징을 사용할 수 있다.

- 그 이유는 데이터가 컬렉션 Fetch Join과 다르게 데이터가 증가하지 않기 때문이다. 

- 즉, 조회된 데이터의 수를 예상할 수 있다.

 

- 그러나 컬렉션 Fetch Join의 경우, 페이징을 사용할 수 없다.

- 그 이유는 데이터의 수를 가늠하기가 힘들다.

- 그러므로 잘못된 페이지 사이즈를 설정이 데이터 누락을 초래하게 된다. 

 

- Hibernate에서는 Fetch Join과 페이징을 사용할 수 있다.

- 다만, 경고가 발생한다. 

 

- 굳이 컬렉션을 사용한 Fetch Join을 사용해야 한다면, 반대로 쿼리를 작성하면 된다.

- 즉, OneToMany를 ManyToOne으로 접근할 수 있도록 쿼리를 작성하는 것이다. 

 

 

2. 결론

- Fetch Join은 JPQL의 성능 최적화를 위하여 사용한다.

- 그러므로 N + 1 케이스가 발생하는 부분을 해결하기 위해서 사용한다. 

- 즉, 최적화가 필요한 곳에서 Fetch Join을 사용하자.

 

댓글