[JPA] %키워드% 로 검색기능 구현하기

김정연·2024년 6월 11일
1
post-thumbnail

jpa로 게시판을 구현하던 중 검색을 어떻게 처리할지 고민을 많이 해봤다.

기존 생각

처음에는 mybatis를 통해서 일일히 하나씩 넣으려고 했었다.
예를 들어서 아래 방법처럼 필드마다 지정하려고 했는데 다른 방법이 있나 찾아봤다.

< if test="">AND KEYWORD = #{KEYWORD}</if>

JPQL

@Query("SELECT b FROM Board b WHERE b.category IN :categories AND (b.title LIKE %:keyword% OR b.content LIKE %:keyword%)")
    List<Board> searchList(@Param("categories") List<Category> categories, @Param("keyword") String keyword);

JPQL은 SQL과 비슷한 구문으로 복잡한 조건을 쿼리로 직접 풀어낼 수 있는 장점이 있다.
또 @Qurey 어노테이션을 사용해서 작성하기 때문에 유지보수도 쉽고, 코드가 간결해진다.

하지만 저렇게 직접 쿼리를 짜는 것은 마이바티스와 다른점이 없다고 생각이 들었고,
장점으로 유지보수가 좋다고는 하지만 더 길어지게 되면 가독성이 떨어질 것 같다고 생각했다.
실제로도 런타임 오류 가능성과 복잡성 증가 등의 단점이 있다고 한다.

그래서 다른 방법을 찾던 중 Containing 에 대해 알게되었다.

Containing

메서드 이름으로 쿼리를 정의할 때 사용되는 키워드 중 하나로, 특정 문자열을 포함하는 항목을 검색하는 데 사용된다. Containing은 SQL의 LIKE 연산자와 유사하며, 기본적으로 부분 문자열 매칭을 지원한다.

여기서 내가 사용하겠다고 마음 먹은 점은 LIKE %keyword%로 동일하다는 점이고, 다중 필드를 검색할 수 있다는 점이다. 그래서 직접 코드를 작성해봤다.

 List<Board> findByCategoryInAndTitleContainingOrContentContaining(List<Category> categories, String title, String content);

내가 원했던 조회는 category 2개와 검색 키워드가 제목 혹은 내용에 있다면 조회가 되어야다.
그래서 in 연산자를 사용했다. 실제 서비스는 아래와 같다.

 /**
     * 게시글 전체 검색(공지사항, 자주찾는 질문 포함)
     * @param keyword
     * @return
     */
    public List<BoardDto> searchMainBoardList(String keyword) {
        List<Category> findCate = List.of(
                entityFetcher.selectCategory(1L),
                entityFetcher.selectCategory(2L)
        );
        List<Board> boards = boardRepository.findByCategoryInAndTitleContainingOrContentContaining(findCate, keyword, keyword);
        return boards.stream()
                .map(boardMapper::boardToBoardDTO)
                .collect(Collectors.toList());
    }

이렇게 작성한 후 keyword 하나만 서버로 보내주면 원하는 보드 리스트를 받을 수 있다.
하지만 네이밍 메서드가 너무 길어지면 그것도 가독성이 떨어지니...
그때는 쿼리 dsl을 도입도 고민하고 있다.
오늘도 공부 끝!

profile
백엔드 개발자

0개의 댓글