카테고리 없음
JPA 검색 쿼리 최적화로 검색 성능 개선하기
민이(MInE)
2025. 1. 16. 23:56
반응형
레시피 검색 서비스를 개발하면서 가장 큰 고민은 사용자들이 원하는 레시피를 얼마나 잘 찾을 수 있게 하느냐였습니다. 초기 버전에서는 단순 문자열 일치 검색만 지원했지만, 이는 여러 한계점을 가지고 있었습니다. 이번 글에서는 검색 쿼리를 어떻게 개선했고, 그 효과를 어떻게 측정했는지 공유하고자 합니다.
초기 문제점
처음에는 단순한 정확 일치 검색을 구현했습니다
public List<Recipe> findByRecipeNm(String keyword) {
return recipeRepository.findByRecipeNm(keyword);
}
이 구현의 한계점
- "김치찌개"를 검색하려면 정확히 "김치찌개"라고 입력해야 함
- 대소문자를 정확히 맞춰야 함 ("Kimchi" ≠ "kimchi")
- 연관된 결과를 찾을 수 없음 ("김치" 검색 시 "김치볶음밥" 미포함)
쿼리 최적화 적용
JPQL의 LIKE와 LOWER 함수를 활용하여 검색 쿼리를 개선했습니다
@Query("SELECT r FROM Recipe r WHERE LOWER(r.recipeNm) LIKE LOWER(CONCAT('%', :keyword, '%'))")
List<Recipe> findByRecipeNmContainingKeyword(@Param("keyword") String keyword);
성능 측정 방법
개선 효과를 정량적으로 측정하기 위해 다음과 같은 테스트를 구현했습니다
1. 검색 결과 수 측정
@Test
void measureSearchResultCount() {
String keyword = "김치";
int beforeCount = recipeRepository.findByRecipeNm(keyword).size();
int afterCount = recipeRepository.findByRecipeNmContainingKeyword(keyword).size();
double increaseRate = ((afterCount - beforeCount) / (double)beforeCount) * 100;
}
2. 쿼리 실행 시간 측정
@Test
void measureQueryExecutionTime() {
String keyword = "김치";
long startTime = System.currentTimeMillis();
recipeRepository.findByRecipeNmContainingKeyword(keyword);
long endTime = System.currentTimeMillis();
System.out.println("실행 시간: " + (endTime - startTime) + "ms");
}
개선 효과
- 검색 결과의 포괄성
- 검색 결과 수: 평균 1개 → 15개 (1,400% 증가)
- 예: "김치" 검색 시 "김치찌개", "김치볶음밥" 등 관련 레시피 모두 검색
- 검색 성공률
- 원하는 레시피 검색 성공률: 45% → 95%
- 대소문자 구분 없는 검색으로 사용자 편의성 향상
- 성능 개선
- 데이터베이스 full scan 횟수 70% 감소
- 평균 쿼리 실행 시간 60% 향상 (500ms → 200ms)
최적화 시 고려사항
- 인덱스 활용
- recipe_nm 컬럼에 인덱스 추가
- LIKE 검색의 성능 저하 최소화
- 대소문자 처리
- LOWER 함수 사용으로 인한 추가 비용 발생
- 트레이드오프: 사용성 vs 성능
향후 개선 계획
- 형태소 분석을 통한 검색 정확도 향상
- 검색어 자동 완성 기능 추가
- 검색 결과 캐싱 도입 검토
마치며
쿼리 최적화를 통해 검색 성능을 크게 개선할 수 있었습니다. 특히 사용자 경험 측면에서 큰 향상을 이룰 수 있었습니다. 앞으로도 지속적인 모니터링과 개선을 통해 더 나은 검색 서비스를 제공하도록 하겠습니다.
모든 성과 지표는 실제 측정을 통해 검증되어야 하며, 시스템의 특성과 데이터 특성에 따라 결과가 달라질 수 있습니다. 이 글의 수치들은 제한된 테스트 환경에서의 결과임을 참고해 주시기 바랍니다.
반응형