oguri's garage

QueryDSL Q-Type 클래스 - 개념, 생성, 활용법 본문

개발하다/Spring

QueryDSL Q-Type 클래스 - 개념, 생성, 활용법

oguri 2025. 10. 1. 22:11

Java/Spring Boot 환경에서 QueryDSL의 핵심인 Q-Type 클래스(Q클래스)의 개념부터 자동 생성 설정, 그리고 실제 개발에서의 활용 흐름까지 설명합니다.

 

 


 

1. Q클래스의 개념과 역할

 

Q클래스는 개발자가 작성한 JPA @Entity를 기반으로 빌드 시점에 자동으로 생성되는 쿼리용 클래스입니다.

  • 역할: Entity와 그 안의 필드(컬럼)들을 객체 형태로 매핑하여, 컴파일 시점에 문법 오류를 잡을 수 있는 타입 세이프(Type-safe) 쿼리 작성을 가능하게 합니다.
  • 핵심 장점:
    • 컴파일 시점 오류 검증: member.age.gt(10)과 같이 코드로 쿼리를 작성하므로, 문자열 기반 SQL의 오타나 문법 오류를 컴파일 단계에서 방지할 수 있습니다.
    • IDE 자동완성 지원: Q클래스의 필드와 사용 가능한 연산자(메서드)를 IDE가 완벽하게 추천해 주므로 생산성이 향상됩니다.
    • 직관적인 동적 쿼리: 자바 코드를 이용해 복잡한 조건의 동적 쿼리를 간결하고 가독성 높게 구현할 수 있습니다.

 

JPA Entity와 Q클래스 비교:

JPA Entity (Member.java) 자동 생성된 Q클래스 (QMember.java)
private Long id; public final NumberPath<Long> id;
private String username; public final StringPath username;
private int age; public final NumberPath<Integer> age;

Sheets로 내보내기

⚠️ 중요: Q클래스는 target/generated-sources/java와 같은 빌드 결과물 폴더에 생성되며, 개발자가 절대로 직접 수정해서는 안 됩니다.

 

 


 

2. Q클래스 자동 생성을 위한 pom.xml 설정

 

Maven 프로젝트에서 Q클래스를 자동으로 생성하려면 maven-compiler-plugin에 어노테이션 프로세서를 통합하여 설정하는 것이 표준적인 방법입니다.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-jpa</artifactId>
        <classifier>jakarta</classifier>
    </dependency>
    <dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-apt</artifactId>
        <scope>provided</scope>
        <classifier>jakarta</classifier>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.12.1</version>
            <configuration>
                <source>21</source> <target>21</target> <annotationProcessorPaths>
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>${lombok.version}</version>
                    </path>
                    <path>
                        <groupId>com.querydsl</groupId>
                        <artifactId>querydsl-apt</artifactId>
                        <version>${querydsl.version}</version>
                        <classifier>jakarta</classifier>
                    </path>
                    <path>
                        <groupId>jakarta.persistence</groupId>
                        <artifactId>jakarta.persistence-api</artifactId>
                        <version>${jakarta-persistence.version}</version>
                    </path>
                </annotationProcessorPaths>
                <generatedSourcesDirectory>${project.build.directory}/generated-sources/java</generatedSourcesDirectory>
            </configuration>
        </plugin>

        </plugins>
</build>

💡 Tip: jakarta classifier는 Spring Boot 3.x / Java 17 이상 환경에서 필수입니다. Spring Boot 2.x 환경이라면 해당 부분을 제거하세요.

 

 


 

3. Q클래스를 활용한 개발 흐름 🚀

 

QueryDSL 개발은 다음과 같은 명확한 순서를 따릅니다.

1단계: Entity 정의 또는 수정

  • 데이터 모델에 따라 @Entity 클래스를 먼저 생성하거나 기존 클래스를 수정합니다.

2단계: 프로젝트 빌드 (Q클래스 생성)

  • 터미널에서 mvn clean install 명령을 실행하거나 IDE의 빌드 기능을 사용합니다.
  • 이때 maven-compiler-plugin이 Entity 변경사항을 감지하여 target/generated-sources/java 경로에 Q클래스를 자동으로 생성하거나 업데이트합니다.

3단계: 쿼리 구현 (Q클래스 사용)

  • 자동으로 생성된 최신 Q클래스를 import하여 JPAQueryFactory와 함께 쿼리를 작성합니다.
  • IDE의 자동완성 기능을 활용하여 개발 효율을 높입니다.
// Repository에서 쿼리 작성 예시

import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import java.util.List;

// static import로 코드를 간결하게 만듭니다.
import static com.example.project.domain.QMember.member;

@RequiredArgsConstructor
public class MemberRepositoryCustomImpl implements MemberRepositoryCustom {

    private final JPAQueryFactory queryFactory;

    public List<Member> findActiveMembers(String name) {
        // 2단계에서 생성된 QMember 객체를 사용합니다.
        return queryFactory
                .selectFrom(member)
                .where(
                    member.username.eq(name),
                    member.status.eq(MemberStatus.ACTIVE)
                )
                .fetch();
    }
}

 

Entity 수정빌드쿼리 작성 흐름을 따르면, SQL 관련 오류를 컴파일 시점에 대부분 방지하여 애플리케이션의 안정성을 높일 수 있습니다.