QueryDSL을 사용하는 이유는 타입 안전성, 가독성, 유지보수성이 뛰어난 동적 SQL 쿼리 생성 도구이기 때문입니다.
컴파일 시점에 쿼리 오류를 잡을 수 있음 (ex. 잘못된 필드명, 오타 등)
일반 JPQL이나 String 기반 쿼리에서는 런타임 에러가 날 수 있지만, QueryDSL은 IDE 자동완성 + 컴파일 오류로 방지 가능
QMember member = QMember.member;
JPAQuery<Member> query = new JPAQuery<>(entityManager);
Member result = query.selectFrom(member)
.where(member.username.eq("user1")) // 잘못된 필드명이면 컴파일 에러
.fetchOne();
조건절을 BooleanBuilder나 where(조건1, 조건2...) 방식으로 쉽게 조립 가능
복잡한 조건 조합도 if 문과 같이 자연스럽게 처리 가능
BooleanBuilder builder = new BooleanBuilder();
if (username != null) {
builder.and(member.username.eq(username));
}
if (age != null) {
builder.and(member.age.goe(age));
}
query.selectFrom(member)
.where(builder)
.fetch();
메서드 체이닝으로 쿼리 구성이 직관적이며 SQL-like한 구조
자동완성 지원 → 유지보수에 용이
JPQL보다 코드가 간결하고 구조화되어 있음
다중 테이블 조인, 서브쿼리 등도 명확하고 안정적으로 처리 가능
SQLBuilder보다 객체지향적으로 작성 가능
private BooleanExpression usernameEq(String username) {
return username != null ? member.username.eq(username) : null;
}
| 항목 | JPQL | QueryDSL |
|---|---|---|
| 타입 안정성 | ❌ 런타임 오류 | ✅ 컴파일 타임 체크 |
| 자동완성 | ❌ 없음 | ✅ IDE 지원 |
| 동적 쿼리 | ❌ 불편 (String 연결 등) | ✅ BooleanBuilder 등으로 유연 |
| 유지보수 | ❌ 변경 시 위험 | ✅ 안전하고 모듈화 쉬움 |
public List<Member> search(String name, Integer age) {
return queryFactory
.selectFrom(member)
.where(
name != null ? member.name.eq(name) : null,
age != null ? member.age.goe(age) : null
)
.fetch();
}
QueryDSL은 타입 안정성, 가독성, 동적 쿼리 조합의 편리함 때문에 복잡한 쿼리가 많은 프로젝트에서 특히 유용합니다.
JPA Criteria API보다 간결하고, JPQL보다 안정적이며, SQL보다 객체지향적입니다.