CateQuest

📅 기간: 2025.06 ~ 진행 중 (6개월) 👥 팀원: BE 1명, FE 2명

✨ 프로젝트 소개

사용자에게 카테고리 별 질문을 주어 오늘 하루에 대한 마무리 혹은 평소에 하는 생각을 정리할 수 있도록 하는 앱입니다. 연애, 공부, 가치관, 경제 등 사용자가 카테고리를 선택하여, 인공지능에게 알맞은 질문을 생성하여 사용자에게 줍니다.

🛠 기술 스택

💪 맡은 기능 구현

🔍 트러블 슈팅

다대다(M:N) 관계에서의 N+1 쿼리 문제 해결

문제 상황

일기(Diary)와 태그(Tag)의 다대다 관계 조회 시, 지연 로딩으로 N+1 쿼리 문제가 발생하는 것을 확인했습니다.

원인 분석

지연 로딩(Lazy Loading)으로 설정된 Tag 목록을 가져오는 과정에서, Diary 조회 쿼리(1) 이후, 각 Diary에 대한 Tag 조회 쿼리(N)가 추가로 발생했습니다.

해결 과정: JPQL 및 Projection DTO 도입

N+1 문제 해결을 위해 @BatchSize 사용도 고려했습니다. 하지만 해당 API가 읽기 전용(Read-Only)이므로, 엔티티를 조회하고 영속성을 관리하는 방식은 불필요한 오버헤드라고 판단했습니다.
따라서 읽기 성능 극대화를 위해, API 스펙에 최적화된 DTO로 직접 조회하는 방식을 채택했습니다.

  1. 조회 전용 DTO(DiaryFlatProjection)를 정의했습니다.
  2. DiaryRepository@Query 어노테이션을 사용하여, Diary와 Tag를 JOIN하는 JPQL 쿼리를 직접 작성했습니다.
  3. SELECT 절에 별칭(alias)을 사용하여 쿼리 결과가 DTO에 자동 매핑되도록 구현했습니다.

결과

기존 (1+N)번 쿼리를 단 1번의 JOIN 쿼리로 최적화했습니다. 읽기 작업에 불필요한 엔티티 조회를 피하게 되어, API 응답 속도 및 DB 부하를 개선했습니다.