본문 바로가기
SpringBoot/심화 주제

QueryDSL

by DEVLIB 2025. 4. 16.
728x90

QueryDSL 핵심 개념

항목 설명
DSL 방식 쿼리를 자바 코드처럼 작성 가능 (where().and())
타입 안전 컴파일 타임에 필드, 테이블 오류 감지 가능
코드 자동 생성 Q타입이라는 쿼리 객체 클래스 자동 생성됨
JPQL 대체 문자열 없이 객체 기반으로 조건/정렬 작성 가능

1. 의존성 추가 (Gradle)

plugins {
    id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
}

dependencies {
    implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
    annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
    annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
    annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
}

2. QueryDSL 설정 (build.gradle)

def querydslDir = "$buildDir/generated/querydsl"

querydsl {
    jpa = true
    querydslSourcesDir = querydslDir
}

sourceSets {
    main.java.srcDir querydslDir
}

compileJava {
    options.annotationProcessorGeneratedSourcesDirectory = file(querydslDir)
}

./gradlew clean build 실행 시 Q 접두사가 붙은 클래스가 자동 생성됨
예: QMember.java


3. 예제 Entity – Member

@Entity
public class Member {
    @Id @GeneratedValue
    private Long id;

    private String username;
    private int age;

    @ManyToOne
    private Team team;
}

 

QMember 자동 생성됨


4. 기본 사용 예제

조건 검색

@Repository
public class MemberQueryRepository {

    private final JPAQueryFactory queryFactory;

    public MemberQueryRepository(EntityManager em) {
        this.queryFactory = new JPAQueryFactory(em);
    }

    public List<Member> findByUsername(String name) {
        QMember member = QMember.member;

        return queryFactory
            .selectFrom(member)
            .where(member.username.eq(name))
            .fetch();
    }
}

복합 조건 & 정렬

List<Member> result = queryFactory
    .selectFrom(member)
    .where(
        member.age.goe(20),
        member.username.contains("홍길동")
    )
    .orderBy(member.age.desc())
    .fetch();

동적 쿼리도 가능

public List<Member> search(String name, Integer age) {
    BooleanBuilder builder = new BooleanBuilder();

    if (name != null) {
        builder.and(member.username.eq(name));
    }
    if (age != null) {
        builder.and(member.age.eq(age));
    }

    return queryFactory
        .selectFrom(member)
        .where(builder)
        .fetch();
}

DTO 직접 조회 (Projections)

public List<MemberDto> fetchMemberDto() {
    return queryFactory
        .select(Projections.constructor(MemberDto.class,
            member.username,
            member.age))
        .from(member)
        .fetch();
}
 

@QueryProjection을 사용하면 컴파일 시 타입 체크도 가능


QueryDSL vs JPQL 비교

항목 JPQL QueryDSL
문법 문자열 기반 자바 메서드 체이닝
타입 안전성 없음 (런타임 오류) 있음 (컴파일 타임 오류 체크)
동적 쿼리 복잡함 (StringBuilder 등) 매우 쉬움
학습 난이도 쉬움 약간 학습 필요
실무 사용성 제한적 고급 검색에 최적화

언제 QueryDSL을 사용할까?

상황 추천
단순 조회 JPA 메서드 쿼리, @Query
복합 조건 검색, 정렬 QueryDSL
API 페이징, 검색 QueryDSL + Pageable
복잡한 JOIN, 서브쿼리 QueryDSL 추천

마무리 요약

항목 설명
설정 build.gradle에 QueryDSL + annotationProcessor 설정
핵심 클래스 Q타입, JPAQueryFactory
장점 컴파일 시점 오류 체크, 동적 쿼리, DTO 매핑
주의 코드 생성 후 Q클래스를 Git에 포함하거나 .gitignore 처리
LIST

'SpringBoot > 심화 주제' 카테고리의 다른 글

마이크로서비스 아키텍처(MSA) 입문  (1) 2025.04.16
멀티모듈 프로젝트 구성  (0) 2025.04.16
WebSocket & 실시간 알림  (0) 2025.04.16
캐시(Cache)  (1) 2025.04.16