인:향 - 쿼리 개선

김준석·2023년 12월 28일
0

향수 추천 서비스

목록 보기
19/21

타인의 향수를 추천해주는 기능은 선택된 향수 중에서 1가지를 선택하여 상대방에게 제시되는 기능입니다.

문제 상황

조합에 맞는 향수들을 모두 고른 뒤 그 중에서 1가지의 향수를 랜덤 선택하여 제시하는 로직이기 때문에, 불필요하게 쿼리수가 나간다는 단점이 있었습니다.

결국 사용되지 않는 자원임에도 불구하고 쿼리가 많이 발생되어 트래픽이 증가하면 부하가 발생할 것이라고 판단되었습니다.

문제 코드

@Query("SELECT s FROM survey s WHERE s.genderAnswer LIKE %:genderAnswer% AND s.scentAnswer = :scentAnswer AND s.moodAnswer LIKE %:moodAnswer% AND s.styleAnswer LIKE %:styleAnswer%")
    List<Survey> findSurveysByGenderScentMoodAndStyle(@Param("genderAnswer") String genderAnswer,
                                                      @Param("scentAnswer") String scentAnswer,
                                                      @Param("moodAnswer") String moodAnswer,
                                                      @Param("styleAnswer") String styleAnswer);

이전 설문을 통한 향수 추천 로직과 동일한 코드를 그대로 사용하였기 때문에 여러가지 향수 리스트가 추천되었습니다.
향수가 하나만 추천될 수 있도록 새로운 메서드를 정의했습니다.

@Query(value = "SELECT * FROM survey s WHERE s.gender_answer LIKE :genderAnswer AND s.scent_answer = :scentAnswer AND s.mood_answer LIKE :moodAnswer AND s.season_answer LIKE :seasonAnswer AND s.style_answer LIKE :styleAnswer ORDER BY RAND() LIMIT 1", nativeQuery = true)
    Optional<Survey> findSurveysByRecommend(@Param("genderAnswer") String genderAnswer,
                                            @Param("scentAnswer") String scentAnswer,
                                            @Param("moodAnswer") String moodAnswer,
                                            @Param("seasonAnswer") String seasonAnswer,
                                            @Param("styleAnswer") String styleAnswer);

JPQL에서는 ORDER BY RAND()와 LIMIT 구문을 직접 지원하지 않습니다. 따라서 네이티브 쿼리를 사용하였습니다.
JPA에서 네이티브 쿼리를 사용하려면 @Query 어노테이션 내에 'nativeQuery = true'를 추가해주면 됩니다.

문제 2

여기까지 한 상태로 쿼리를 실행시켰는데 향수 조회가 되지 않았습니다.
JPA에서는 '%'를 통해 문자열 부분 포함 여부를 선택할 수 있는데 네이티브 쿼리에서는 이를 지원하지 않았습니다.

따라서 파라미터 요청을 할때 '%' 값을 추가하도록 파싱하는 메서드를 request내에 추가시켜주었습니다.

    public void addQueryParameter() {
        this.genderAnswer = "%" + genderAnswer + "%";
        this.moodAnswer = "%" + moodAnswer + "%";
        this.seasonAnswer = "%" + seasonAnswer + "%";
        this.styleAnswer = "%" + styleAnswer + "%";
    }

이렇게 수정한 후에 실행을 해보았습니다.

쿼리수가 줄게 되었습니다!!

profile
기록하면서 성장하기!

0개의 댓글