QueryDSL - BooleanExpression을 이용한 동적 쿼리 해결

DevSeoRex·2023년 6월 6일
3
post-thumbnail

😮 검색기능을 구현해야 한다면?

이번 프로젝트를 진행하면서 분양 글 검색 기능도 필요해서 이 부분을 어떻게 구현해야 할지 고민하고 있었습니다.

먼저 검색에 대한 요구사항을 보겠습니다.

요구사항

  1. 검색은 제목, 내용, 제목 + 내용, 품종으로 검색이 가능해야 한다.
  2. 게시글 검색과 함께 필터(강아지, 고양이, 기타)가 적용 가능해야 한다.
  3. 게시글 검색과 함께 더 보기(10개 단위) 기능이 가능해야 한다.
  4. 1~3번의 요구사항은 전부 적용될 수도 있고, 하나만 적용되거나 아예 적용되지 않을 수 있다.

검색에 대한 요구사항은 위와 같이 4가지입니다.
쉽게 풀어서 설명드리자면, 검색을 한 게시글 리스트에서 품종으로 필터링이 다시 들어갈 수 있고, 품종으로 필터링되고, 10개 단위로 게시글 리스트를 끌고 오는 기능까지 수행해야 합니다.

검색, 필터링, 추가조회와 같은 행위를 하나도 하지 않으면 기본 10개의 데이터만 반환하게 코드를 작성해야 했습니다.

방법의 고민

적용해야 하는 조건이 매우 많기도 하고, 3가지 요구사항이 모두 적용될 경우 and 조건으로 전부 결합해줘야 하는 문제가 생겼습니다.

변수의 값이 있는지 여부로 조건에 추가 되야할지 말아야 할지를 결정해야하는 동적쿼리 문제에 직면한 것입니다.

각 조건별로 사용할 변수를 보겠습니다.

  • saleNo : 현재 페이지의 맨 마지막 게시물의 고유 키 값
  • keyword : 검색을 위해 보낸 키워드
  • option : 검색 유형을 담고 있는 정수 값
  • filter : 개, 고양이, 기타를 검색할 수 있는 문자열

총 4가지의 변수를 파라미터로 받게됩니다.

어떤 파라미터의 값이 있고 어떤 파라미터의 값이 없을 것인지 조건을 줘서 비교해야 하는 것입니다. 만약 이것들을 모두 if ~ else 와 같은 조건문을 이용한 분기 처리를 한다면 위에서 아래로 물이 흐르면 필터로 걸러주는 정수기 코드가 나올 것이 분명했습니다.

조건을 나눠서 생각하기

일단 QueryDSL의 특성에 대해서 생각해보았습니다.
QueryDSL의 where절은 쉼표로 구분해서 넣어줄 경우, and 조건으로 결합됩니다.

따라서 1부터 3번까지의 요구사항에 대해서 BooleanExpression을 따로 생성해서 where절에 3개의 조건을 넣어주기로 결정하였습니다.


where 절에 들어가는 3개의 조건을 만들어내는 메서드를 작성해보도록 하겠습니다.

🥳 동적 쿼리! 유연하게 해결해보자

searchCondition 만들기

검색 조건은 아래와 같습니다.
1. 제목
2. 내용
3. 제목 + 내용
4. 품종

검색 조건은 option 값이 없다면, keyword의 null 여부도 검사하지 않고, 검색 조건이 없다고 판단해도 됩니다.

왜냐하면 option 값은 1~4까지의 값을 가지고 검색 유형을 정하는 정수 값입니다.
검색 유형을 알지 못한다면, keyword의 값이 있다고 해도 검색을 하지 못하기 때문에 조건에서 빼게 되는 것입니다.


먼저 option의 값이 비어있지 않다면, 1부터 4번의 검색 유형에 따라서 알맞은 조건을 만들어주는 메서드를 호출해 searchCondition의 값을 채워줍니다.


keyword의 값이 null이 아닐 경우에만 조건을 만들거나 조합해서 searchCondition의 값을 채워주게 됩니다.

QueryDSL은 where절에 null이 들어가게 되면 조건을 무시하고 실행하지 않습니다. 따라서 동적쿼리에 대한 유연한 대응이 가능합니다.

saleNoLt 만들기

saleNoLt는 현재 게시글 바로 다음 게시글부터 10개의 게시글을 가져오는 조건을 수행할때 사용하는 메서드입니다.


Offset을 사용하는 방법보다 NoOffset 전략을 통해 페이징 성능 향상을 이뤄낼 수 있기 때문에 인덱스를 사용할 수 있는 PK(기본키)값 비교를 통한 페이징 전략을 채택했습니다.

현재 들어온 saleNo(PK)보다 값이 더 작은지 비교하는 메서드입니다.

kindLike 만들기

kindLike는 filter의 값이 들어왔을때 강아지, 고양이, 기타 분양에 대한 분류를 필터링 할 수 있도록 조건을 만들어주는 메서드입니다.

😎 Let's Test!

이제 만들어진 코드들로 정말 잘 동작하는지 테스트를 해보도록 하겠습니다.

분양글 리스트 조회 API에 아무 조건을 주지 않고 요청을 보내보겠습니다.

이번에는 54번 이전의 분양글만 가져오도록 해보겠습니다.

55번 이상인 분양글은 노출되지 않는 것을 확인할 수 있습니다.

이번에는 검색 기능을 이용해서, 제목에 아르마딜로가 들어가는 분양글을 검색해보겠습니다.

제목에 아르마딜로만 나오는 게시글이 나오는 것을 볼 수 있습니다.

마지막으로 필터 기능이 잘 동작하는지 확인해보겠습니다. 분류가 고양이인 분양글만 검색해보겠습니다.

분류가 고양이인 게시글만 검색되는 것을 확인할 수 있습니다.

오늘은 프로젝트 진행중에 해결해야 했던 동적쿼리 문제를 해결한 방법을 함께 나눠보았습니다.
QueryDSL을 이용하면 BooleanExpression의 유연한 조합을 통해 다양한 조건을 합성하고 조건을 통한 데이터 필터링을 편하게 할 수 있다는 것을 알게 되었습니다.

앞으로 검색 기능이나 동적 쿼리를 해결할 일이 있다면 자신있게 해결할 수 있을 것 같습니다.

오늘도 읽어주셔서 감사합니다.

🙇

참고한 레퍼런스

인프런 - 실전! QueryDSL(김영한)

0개의 댓글