동적 쿼리 (QueryDsl) - showMeTheMoneyPrac/BE_Repo GitHub Wiki
1️⃣ 프로젝트에서의 동적 쿼리 사용의 이유
프로젝트를 진행함에 있어 검색 기능이 존재하였고 사용자가 카테고리 및 검색어를 설정하지 않은 전체보기의 경우에 쿼리문에서 null값이 들어가는 것을 확인. → 이로 인한 쿼리의 동작이 정상적으로 이루어지지 않는 것이 문제가 되었다.
위 과정에서 처음의 단계에서는 API와 JPA의 갯수를 늘려가는 형식과 사용자가 기본 값을 설정하지 않았을 시, 기본 default값을 부여하는 형태로 코드를 진행하려하였으나, 위 방법은 올바른 방법이 아니라는 판단에 동적 쿼리를 사용하고자 하였다.
Springboot에서 효과적으로 동적쿼리를 사용하려는데 JPA Module 중 BooleanExpress를 사용할 수 있는 Querydsl을 사용하였다.
2️⃣ 동적 쿼리 활용 방안
동적 쿼리를 활용하는 방법으로 Querydsl을 사용하였고 기존의 default값을 JPA에서 활용하는 방법보다 사용자(프론트)에게 전달 받은 데이터가 일부 null 값이더라도 동적 쿼리를 통해 데이터의 반환을 이루어지도록 설계하였다.
이로 인하여 변수의 값이 존재하는지 안하는지에 따라 변수가 n개라면 $2^n$개가 생길 수 있는 쿼리문에 대해서 단 한가지의 동적쿼리로 해결할 수 있게 되었다.
이 과정에서 BooleanExpress를 활용하여 where문 안에 존재하는 조건들을 판별할 수 있게 되었다.
//searchByReviewCnt private Page<ProductResponseDto.ProductList> getSearchByReview(Pageable pageable, String category, String searchKeyword) { List<ProductResponseDto.ProductList> productLists = jpaQueryFactory .select(Projections.bean(ProductResponseDto.ProductList.class, product.id, product.title, product.category, product.reviewCnt, product.detail, product.price, product.firstImg)) .from(product) .where( booleanSearchKeyword(searchKeyword), booleanCategory(category) ) .offset(pageable.getOffset()) .limit(pageable.getPageSize()) .orderBy(product.reviewCnt.desc()) .fetch(); Long count = jpaQueryFactory .select(product.count()) .from(product) .where( booleanSearchKeyword(searchKeyword), booleanCategory(category) ) .fetchOne(); return new PageImpl<>(productLists,pageable,count); } //동적 쿼리를 위한 문들 private BooleanExpression booleanSearchKeyword(String searchTitle) { return isEmpty(searchTitle) ? null : product.title.contains(searchTitle); } private BooleanExpression booleanCategory(String category) { return isEmpty(category) ? null : product.category.eq(category); }
수많은 쿼리문들을 단 하나의 쿼리문으로 문제를 해결하였다.
3️⃣ 기술에 대한 참고 문헌
QueryDsl의 사용 이유
[[JPA] Spring Data JPA와 QueryDSL 이해, 실무 경험 공유](https://ict-nroo.tistory.com/117)
QueryDsl 동적 쿼리 활용 방법
[[querydsl] 동적 쿼리 만들기](https://devkingdom.tistory.com/254)
[querydsl 동적 쿼리](https://hjhng125.github.io/querydsl/querydsl-dynamic-query/)
4️⃣ 기술의 장점
- 동적 쿼리의 이용이 가능하다.
- 컴파일 시점에서 문법 오류 파악이 가능하다.
- @Entity를 가지고 Q를 활용하여 queryDSL 전용 객체를 만들어서 활용한다.
- IDE의 도움을 받을 수 있고, 컴파일 타임에 오류를 잡아주므로 쿼리로 인한 실수를 할 일이 없다는 점이장점이다.
- 또한 원하는 필드만을 뽑아서 DTO로 반환이 가능하다는 점이 있다.
5️⃣ 추가적 방안은?
페이징에 있어 현재로는 Offset limit 구조로 되어있지만 이를 No Offset을 활용하여 더욱 가벼운 페이징을 처리할 수 있다는 점을 추가적으로 생각할 수 있다.