개발 도구/백엔드 개발 (Backend Development)
[Spring DB] Querydsl
MKISOS
2025. 8. 4. 06:05
반응형
Querydsl 정리
이 글은 인프런 김영한님의 "스프링 DB 2편 - 데이터 접근 활용 기술" 강의를 수강하고 정리한 내용이다.
Querydsl은 자바 코드로 타입 안전(type-safe)하게 SQL/JPA 쿼리를 작성할 수 있도록 도와주는 프레임워크다. 특히 복잡한 조건의 동적 쿼리를 작성할 때 코드의 가독성과 안정성을 높여주기 때문에, 실무에서 매우 유용하게 활용된다고 한다.
1. 기존 쿼리 방식의 문제점
JPQL 방식
String query = "select m from Member m " +
"where m.age between 20 and 40 " +
"and m.name like '김%' " +
"order by m.age desc";
- 장점: SQL과 유사해서 빠르게 익숙해질 수 있다.
- 단점: 문자열 기반, 타입 체크 불가, 오타 발견이 런타임에 발생
Criteria API
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> cq = cb.createQuery(Member.class);
Root<Member> m = cq.from(Member.class);
cq.select(m)
.where(cb.between(m.get("age"), 20, 40),
cb.like(m.get("name"), "김%"))
.orderBy(cb.desc(m.get("age")));
- 장점: 동적 쿼리 구성 가능
- 단점: 너무 복잡하고 가독성이 낮아 실무에서 거의 사용되지 않는다
2. Querydsl 소개
Querydsl은 위 두 가지 방식의 문제를 모두 해결할 수 있다. 타입 안전, 자동완성 지원, 메서드 체이닝 문법, 동적 쿼리 조합까지 자바 개발자에게 익숙한 방식으로 쿼리를 작성할 수 있다.
List<Member> list = queryFactory
.select(member)
.from(member)
.where(member.age.between(20, 40).and(member.name.like("김%")))
.orderBy(member.age.desc())
.limit(3)
.fetch();
SQL 오타로 인한 런타임 오류를 컴파일 시점에 막을 수 있고, IDE 자동완성의 도움을 받을 수 있어 생산성이 높아진다.
3. Querydsl 설정
스프링 부트 3.x 기준 (jakarta)
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"
Q타입 생성 확인
- Gradle: ./gradlew clean compileJava
- IntelliJ: Build > Build Project 또는 테스트 실행
- 생성 경로: build/generated/sources/annotationProcessor/java/main/QMember.java
Q클래스는 빌드시 자동 생성되므로 git 버전 관리에 포함하지 않는 것이 일반적이다.
4. Querydsl 적용 예시
저장소 구현체 예시
public class JpaItemRepositoryV3 implements ItemRepository {
private final JPAQueryFactory query;
...
public List<Item> findAll(ItemSearchCond cond) {
return query
.select(item)
.from(item)
.where(likeItemName(cond.getItemName()),
maxPrice(cond.getMaxPrice()))
.fetch();
}
private BooleanExpression likeItemName(String itemName) {
return StringUtils.hasText(itemName) ? item.itemName.like("%" + itemName + "%") : null;
}
private BooleanExpression maxPrice(Integer price) {
return price != null ? item.price.loe(price) : null;
}
}
null을 where 절에 넘기면 자동으로 조건에서 제외되는 구조를 활용해, 동적 쿼리를 매우 간결하게 작성할 수 있다.
5. Querydsl의 장점
| 타입 안전성 | 컴파일 시점에 오타, 잘못된 속성 검출 가능 |
| 자동완성 지원 | IDE 지원을 통한 빠른 개발 가능 |
| 동적 쿼리 | BooleanBuilder 또는 null 조건 조합으로 간결한 구성 가능 |
| 쿼리 재사용 | 조건 메서드를 재활용 가능 (likeName(), maxPrice() 등) |
| 정적 타입 생성 | Q클래스를 통해 명확하게 쿼리 경로를 제시함 |
6. 실무 적용 팁
- JPAQueryFactory는 스프링 빈으로 등록해 재사용할 수 있다.
- @Repository를 붙여 스프링 예외 변환이 자동으로 적용되도록 한다.
- 복잡한 조건의 쿼리는 Querydsl로, 단순한 조건은 SpringData JPA의 메서드 쿼리 방식으로 병행 사용한다.
7. 정리
Querydsl은 자바 코드만으로 동적이고 복잡한 쿼리를 안전하고 간결하게 작성할 수 있는 도구다. 특히 실무에서 동적 검색 조건이 많은 화면, 복잡한 페이징 조회, DTO 변환이 필요한 API에서 Querydsl은 필수적인 기술로 자리 잡았다.
반응형