JPA N+1 문제 해결하기 - DTO 조회 방식 활용

momomoki·2025년 1월 9일
0

개요

N+1 문제를 해결하기 위한 방법으로 대부분 fetch join을 언급합니다. 하지만 fetch join만이 유일한 해결책은 아닙니다. 저는 QueryDSL의 Projections을 활용한 DTO 직접 조회 방식으로 N+1 문제를 해결해보았습니다.

왜 Projections인가?

기존 fetch join 방식은 엔티티의 모든 정보를 가져오고, 추후 DTO로 변환하는 과정이 필요했습니다. 반면 Projections을 활용하면:

  • 필요한 컬럼만 선택적으로 조회 가능
  • 연관 관계에서 발생하는 추가 쿼리 방지
  • fetch join 없이도 효율적인 쿼리 실행
  • 엔티티에서 DTO로의 변환 과정 생략

Projections을 활용한 구현

@Override
public List<FindHospitalReservationDto> findHospitalReservationByUserId(Long userId) {
    return jpaQueryFactory
        .select(Projections.constructor(FindHospitalReservationDto.class,
            hospitalReservationEntity.hospReservationId,
            hospitalReservationEntity.reservationAt,
            hospitalReservationEntity.reservationTime,
            hospitalReservationEntity.user.socialUserId,
            hospitalReservationEntity.hospital.hospId,
            hospitalReservationEntity.hospital.yadmNm,
            hospitalReservationEntity.hospital.addr,
            hospitalReservationEntity.hospital.telno
            ))
        .from(hospitalReservationEntity)
        .leftJoin(hospitalReservationEntity.user, socialUserEntity)
        .leftJoin(hospitalReservationEntity.hospital, hospitalEntity)
        .where(hospitalReservationEntity.user.socialUserId.eq(userId))
        .fetch();
}

코드 설명

DTO 직접 조회

  • Projections.constructor를 사용하여 DTO로 직접 조회
  • 필요한 컬럼만 선택적으로 지정
  • 엔티티 변환 과정 없이 바로 DTO 반환

조인 처리

  • 필요한 테이블과 leftJoin으로 연결
  • fetchJoin이 필요 없음 (DTO로 직접 조회하기 때문)
  • 연관된 엔티티의 특정 컬럼만 선택적으로 조회

쿼리 실행

  • 단일 쿼리로 모든 데이터 조회
  • N+1 문제 해결
  • 불필요한 데이터 조회 방지

결론

N+1 문제를 해결하기 위해 일반적으로 사용하는 fetch join 외에도 QueryDSL의 Projections을 활용한 방식이 효과적인 해결책이 될 수 있습니다. 이 방식은 필요한 데이터만 조회하고 DTO로 직접 변환함으로써 성능상의 이점을 제공할 뿐만 아니라, 코드도 더 간결해집니다.
더 나아가 이러한 접근은 단순히 N+1 문제 해결을 넘어서, 상황에 따라 적절한 기술을 선택하고 적용하는 것의 중요성을 보여줍니다. fetch join이 항상 최선의 해결책은 아니며, 때로는 다른 접근 방식이 더 효율적일 수 있다는 것을 배웠습니다.

profile
얍얍엽엽욥욥

0개의 댓글

관련 채용 정보