개발 중 더미 데이터를 활용한 테스트 과정에서 쿼리 성능 저하 문제가 발생했고, 이를 해결하기 위해 쿼리 구조 개선 및 인덱스 추가를 진행했던 경험을 공유합니다.
❗ 문제 발생
더미 데이터를 약 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 설계와 쿼리 최적화까지 함께 고민해야 진짜 문제를 해결할 수 있다는 것을 다시 한 번 느꼈습니다.