Spring Boot/트러블슈팅

트러블슈팅 - 쿼리 최적화로 11초 → 681ms 단축

cyh0309 2025. 5. 3. 01:55

개발 중 더미 데이터를 활용한 테스트 과정에서 쿼리 성능 저하 문제가 발생했고, 이를 해결하기 위해 쿼리 구조 개선 및 인덱스 추가를 진행했던 경험을 공유합니다.

 

❗ 문제 발생

더미 데이터를 약 496,000건 삽입한 상태에서 특정 게시글 리스트를 조회하는 쿼리 실행 시, 응답 시간이 약 11초가 소요되는 문제가 발생했습니다.
이러한 응답 지연은 실제 서비스에서도 치명적인 영향을 줄 수 있어, 즉시 원인 분석 및 해결이 필요했습니다.

 

🔍 원인 파악

쿼리를 디버깅한 결과, 다음과 같은 구조에서 병목이 발생하고 있었습니다.

  • post 테이블과 category 테이블 사이의 중간 테이블인 post_category_matches를 JOIN하는 과정에서 조건 검색 속도가 급격히 느려지고 있었습니다.
  • 조인 대상 컬럼에 인덱스가 없어 전체 테이블을 탐색하는 상황이었고, 데이터가 많아질수록 성능 저하가 심해졌습니다.

🛠️ 해결 과정

1. JPQL → QueryDSL 전환

처음에는 JPQL을 사용하고 있었는데, 복잡한 쿼리 구조와 조인 조건 때문에 성능 병목 포인트를 파악하기 어려웠습니다.
이에 따라 QueryDSL로 전환하여 쿼리 구조를 더 명확하게 만들고, 실행 쿼리를 쉽게 추적할 수 있도록 개선했습니다.

// QueryDSL 예시 코드 (간단 예)
queryFactory.selectFrom(post)
    .join(postCategoryMatches).on(post.id.eq(postCategoryMatches.post.id))
    .where(postCategoryMatches.category.id.eq(targetCategoryId))
    .orderBy(post.createdAt.desc())
    .limit(20)
    .fetch();

2. 인덱스 추가

자주 사용되는 조건 검색 대상 컬럼에 인덱스를 추가하여 DB 레벨에서 성능을 최적화했습니다.

-- 중간 테이블 인덱스 추가 예시
CREATE INDEX idx_post_category ON post_category_matches(category_id);

해당 인덱스를 추가하자, 조인 및 조건 검색이 빠르게 수행되며 전체 쿼리 응답 시간이 대폭 줄어들었습니다.

 

✅ 최종 결과

항목 개선 전 개선 후
실행 시간 약 11초 681ms
쿼리 가독성 낮음 (JPQL) 높음 (QueryDSL)
DB 인덱스 없음 존재 (성능 향상)

 

💡 배운 점

  • 데이터가 많아질수록 조인 조건에 인덱스를 고려해야 합니다. (항상 필요한 것은 아니지만, 대부분의 경우 성능에 긍정적인 영향을 줍니다.)
  • JPQL로는 복잡한 성능 병목을 추적하기 어려운 경우가 있고, QueryDSL은 구조적으로 파악이 용이합니다.
  • 이 경험을 통해 단순히 코드만 고치는 것이 아닌, DB 설계와 쿼리 최적화까지 함께 고민해야 진짜 문제를 해결할 수 있다는 것을 다시 한 번 느꼈습니다.