QueryDSL
[Querydsl] QueryDSL 란?
쌈뽕코딩
2025. 2. 17. 18:16
QueryDSL은 타입 안전(Type-Safe)한 동적 쿼리를 생성할 수 있도록 지원하는 Java 기반 ORM(Object-Relational Mapping) 프레임워크이다. JPA(Java Persistence API)를 사용할 때 JPQL(Java Persistence Query Language) 또는 Criteria API를 대체할 수 있도록 설계되었다.
✏️ 타입 안전한 동적 쿼리란?
BooleanBuilder builder = new BooleanBuilder();
if (age != null) {
builder.and(m.age.gt(age)); // 나이가 age보다 큰 조건 추가
}
if (name != null) {
builder.and(m.name.eq(name)); // 이름이 같은 조건 추가
}
List<Member> members = queryFactory
.selectFrom(m)
.where(builder)
.fetch();
- 동적 쿼리란 실행 시점에서 조건이 변경되는 쿼리다. 예를 들어, 사용자가 입력한 조건에 따라 age, name, city 등의 필터를 조합하는 경우 QueryDSL을 사용하면 안전하게 동적 쿼리를 생성할 수 있다.
- 그렇다면 "타입 안전한(Type-Safe) 동적 쿼리"라는 말은 컴파일 시점에 데이터 타입을 검증할 수 있는 방식으로 동적으로 생성되는 SQL 쿼리를 의미한다. 즉, 실행하기 전에 문법 오류나 타입 오류를 체크할 수 있어 런타임 오류를 방지할 수 있다.
✏️ JPQL이란?
String jpql = "SELECT m FROM Member m WHERE m.age > " + age;
List<Member> members = em.createQuery(jpql, Member.class).getResultList();
- JPQL(Java Persistence Query Language)은 JPA에서 엔티티 객체를 대상으로 SQL과 유사한 쿼리를 작성하는 객체 지향 쿼리 언어이다.
- SQL과 유사하지만, SQL이 데이터베이스 테이블을 대상으로 하는 반면 JPQL은 엔티티 객체를 대상으로 동작한다.
- JPA의 @Query 어노테이션과 함께 사용 가능
📌 1. 타입 안전성이 없는 JPQL(문자열 기반 쿼리) 예제
String jpql = "SELECT m FROM Member m WHERE m.age > " + age;
List<Member> members = em.createQuery(jpql, Member.class).getResultList();
🔴 문제점
- 문자열(String)로 쿼리를 작성하기 때문에 컴파일 타임에 문법 오류를 체크할 수 없음
- 오타(예: m.aga → m.age 오타)를 내도 런타임까지 알 수 없음
- 필드 타입이 바뀌더라도 쿼리는 자동으로 검증되지 않음
📌 2. QueryDSL을 활용한 타입 안전한 동적 쿼리 예제
QMember m = QMember.member;
List<Member> members = queryFactory
.selectFrom(m)
.where(m.age.gt(20)) // age 필드는 int 타입으로, 문자열 오류 방지
.fetch();
✅ 타입 안전성 확보
- m.age가 int 타입이므로, m.age.gt("20") 같은 실수는 컴파일 오류로 감지 가능
- 필드명이 변경되거나 오타가 있어도 컴파일 타임에 오류를 알려줌
- 자동완성 기능 제공 (IDE에서 지원)
그럼 왜 QueryDSL을 사용해야 할까?
📌 예제 코드 (JPQL vs QueryDSL 비교)
// jpql 사용
String jpql = "SELECT m FROM Member m WHERE m.age > :age";
List<Member> members = em.createQuery(jpql, Member.class)
.setParameter("age", 20)
.getResultList();
// querydsl 사용
QMember m = QMember.member;
List<Member> members = queryFactory
.selectFrom(m)
.where(m.age.gt(20))
.fetch();
- JPA를 사용할 때 JPQL을 직접 작성하면 문자열 기반이라 가독성이 떨어지고 유지보수가 어렵다.
- Querydsl이 더 간결하고 직관적이며, 타입 안정성이 보장됨
QueryDSL은 코드 기반으로 작성되므로, 아래와 같은 장점이 있다.
✅ 1. JPQL 대비 장점
- 문자열 기반이 아니라 코드 기반이라 유지보수 쉬움
- 컴파일 타임 오류 체크 가능 → 런타임 오류 감소
- 동적 쿼리 작성이 편리
✅ 2. Criteria API 대비 장점
- 더 직관적이고 가독성이 뛰어남
- 코드량이 줄어들어 유지보수 비용 절감
✅ 3. JPA와의 강력한 연동 지원
- Spring Data JPA와 함께 사용하면 복잡한 쿼리도 간단하게 작성 가능
- fetchJoin, GroupBy, having 등 SQL의 다양한 기능 활용 가능
QueryDSL의 대체 기술에는 어떤 것이 있을까?
- Spring Data JPA (Specifications 포함)
- Spring Data JPA에서 Specification을 활용하여 동적 쿼리를 생성 가능
- Querydsl 없이도 복잡한 동적 쿼리를 작성할 수 있지만 가독성은 Querydsl보다 떨어짐
- JPA Criteria API
- JPA에서 제공하는 표준 API
- Querydsl이 나오기 전에는 동적 쿼리를 작성할 때 많이 사용되었지만, 코드가 너무 길고 가독성이 떨어지는 단점이 있음
- Native Query (SQL 직접 작성)
- 복잡한 쿼리를 작성할 때 사용 가능
- 데이터베이스 종속성이 높아지므로 유지보수 어려움
- JOOQ
- Querydsl과 비슷한 기능을 제공하는 SQL 빌더
- SQL 중심이라 JPA와의 연동보다는 직접 SQL을 다룰 때 유리