개발/Spring

Spring Data JPA QueryDSL 사용법

hanks 2026. 2. 24. 11:51

Spring Data JPA와 QueryDSL을 함께 사용하여 복잡한 쿼리를 효율적으로 작성하는 방법을 알아봅니다.

왜 Spring Data JPA와 QueryDSL을 함께 사용할까요?

Spring Data JPA는 개발자가 데이터 접근 계층을 쉽게 구현할 수 있도록 도와주는 강력한 프레임워크입니다. 하지만 복잡한 쿼리를 작성해야 할 때, Spring Data JPA의 기본 기능만으로는 한계가 있을 수 있습니다. 이때 QueryDSL을 함께 사용하면 타입-세이프하고 유지보수가 용이한 쿼리를 작성할 수 있습니다.

① 복잡한 쿼리 작성의 어려움

Spring Data JPA는 간단한 CRUD 작업을 위한 기본적인 쿼리 메서드를 제공하지만, 복잡한 조건이나 조인이 필요한 쿼리를 작성하기에는 불편함이 있습니다. 예를 들어, 여러 테이블을 조인하고 특정 조건을 만족하는 데이터를 검색하는 쿼리를 작성하려면 복잡한 JPQL을 사용해야 합니다.

② JPQL의 한계

JPQL은 문자열 기반의 쿼리 언어이기 때문에 컴파일 시점에 오류를 발견하기 어렵고, 오타나 문법 오류로 인해 런타임에 예외가 발생할 수 있습니다. 또한, JPQL은 복잡한 쿼리를 작성할수록 가독성이 떨어지고 유지보수가 어려워지는 단점이 있습니다.


핵심 개념

항목 설명
Spring Data JPA JPA를 사용하여 데이터 접근 계층을 쉽게 구현할 수 있도록 도와주는 프레임워크
QueryDSL 타입-세이프한 쿼리를 작성할 수 있도록 지원하는 프레임워크
Predicate QueryDSL에서 조건을 표현하는 인터페이스
BooleanExpression Predicate를 구현하는 클래스로, and, or 등의 메서드를 사용하여 조건을 조합할 수 있음

[클라이언트] ── 쿼리 요청 ──→ [Spring Data JPA + QueryDSL] ── 쿼리 실행 ──→ [데이터베이스] └── 쿼리 생성 ────┘


단계별 사용법

① 1단계: QueryDSL 설정 추가

먼저, 프로젝트에 QueryDSL을 사용하기 위한 설정을 추가해야 합니다. Maven 또는 Gradle을 사용하여 QueryDSL 관련 의존성을 추가합니다.

Maven 설정 (pom.xml):

xml com.querydslquerydsl-jpa${querydsl.version}com.querydslquerydsl-apt${querydsl.version}provided

Gradle 설정 (build.gradle):

gradle dependencies { implementation 'com.querydsl:querydsl-jpa' annotationProcessor "com.querydsl:querydsl-apt:${querydsl.version}:jpa" implementation "jakarta.annotation:jakarta.annotation-api" implementation "jakarta.persistence:jakarta.persistence-api" }

def generatedSourcesDir = "$projectDir/src/main/generated"

sourceSets { main.java.srcDirs += generatedSourcesDir }

tasks.withType(JavaCompile) { options.annotationProcessorPath = configurations.annotationProcessor }

clean { delete file(generatedSourcesDir) }

② 2단계: QueryDSL Q 클래스 생성

QueryDSL은 엔티티 클래스를 기반으로 쿼리 작성을 위한 Q 클래스를 생성합니다. Q 클래스를 생성하려면 QueryDSL APT(Annotation Processing Tool)를 사용해야 합니다. 위에서 설정한 의존성을 통해 Q 클래스를 생성할 수 있습니다. 프로젝트를 빌드하면 src/main/generated 폴더에 Q 클래스가 생성됩니다. (Gradle 설정 참고)

③ 3단계: QueryDSL을 사용한 쿼리 작성

Q 클래스를 사용하여 쿼리를 작성할 수 있습니다. Spring Data JPA Repository에서 QuerydslPredicateExecutor 인터페이스를 상속받아 QueryDSL을 사용할 수 있습니다.

java import com.querydsl.core.types.Predicate; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.querydsl.QuerydslPredicateExecutor;

public interface MemberRepository extends JpaRepository<Member, Long>, QuerydslPredicateExecutor { }

java import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Predicate; import com.example.entity.Member; import com.example.entity.QMember; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest public class QuerydslTest {

@Autowired
private MemberRepository memberRepository;

@Test
public void querydslTest() {
    QMember member = QMember.member;
    BooleanBuilder builder = new BooleanBuilder();

    // 조건 추가 (예: 이름이 "홍길동"인 멤버 검색)
    builder.and(member.name.eq("홍길동"));

    // 조건 추가 (예: 나이가 20세 이상인 멤버 검색)
    builder.and(member.age.goe(20));

    Predicate predicate = builder;
    Iterable<Member> results = memberRepository.findAll(predicate);

    results.forEach(System.out::println);
}

}

위 코드에서 QMember.member는 Member 엔티티에 대한 Q 클래스의 인스턴스입니다. builder를 사용하여 조건을 추가하고, memberRepository.findAll(predicate) 메서드를 사용하여 쿼리를 실행합니다.


자주 묻는 질문

Q: QueryDSL을 사용하면 어떤 장점이 있나요?

A: QueryDSL을 사용하면 타입-세이프한 쿼리를 작성할 수 있고, 컴파일 시점에 오류를 발견할 수 있습니다. 또한, 복잡한 쿼리를 쉽게 작성할 수 있으며, 쿼리의 가독성과 유지보수성을 향상시킬 수 있습니다.

Q: Spring Data JPA의 기본 기능만으로는 복잡한 쿼리를 작성할 수 없나요?

A: Spring Data JPA의 기본 기능만으로도 어느 정도 복잡한 쿼리를 작성할 수 있지만, JPQL을 사용해야 하므로 QueryDSL에 비해 불편함이 있을 수 있습니다.


마무리

Spring Data JPA와 QueryDSL을 함께 사용하면 복잡한 쿼리를 효율적으로 작성하고 관리할 수 있습니다. QueryDSL은 타입-세이프한 쿼리를 지원하여 개발 생산성을 높이고, 쿼리의 가독성을 향상시켜 유지보수를 용이하게 해줍니다.

  • QueryDSL 의존성 추가
  • Q 클래스 생성 확인
  • QueryDSL을 사용한 쿼리 작성 및 테스트