Springintermediate검토 2026.08

Querydsl 조회 설계

Type-safe Expression을 조합해 동적 Query와 DTO Projection을 명시적으로 구성한다.

#Querydsl#dynamic-query#projection#bulk-update

Overview

Querydsl은 Q Type과 Expression을 사용해 Java Compiler가 Property와 Type 오류를 일찍 발견하도록 돕는 Query Builder다. 핵심 가치는 문자열 JPQL을 없애는 것보다 검색 조건과 조회 결과를 재사용 가능한 조각으로 표현하는 데 있다.

동적 조건

BooleanBuilder는 조건을 차례로 쌓기 쉽다. 조건 Method가 null을 반환하면 where가 무시하는 특성을 사용하면 읽기 좋은 조합이 된다.

private BooleanExpression usernameEq(String username) {
    return username == null ? null : member.username.eq(username);
}
 
private BooleanExpression ageEq(Integer age) {
    return age == null ? null : member.age.eq(age);
}
 
return queryFactory.selectFrom(member)
    .where(usernameEq(condition.username()), ageEq(condition.age()))
    .fetch();

조건 Method의 이름이 Business 의미를 드러내도록 하고, 아무 Query에서나 재사용하는 거대한 Utility로 만들지 않는다.

Projection

  • Tuple: Repository 내부의 임시 다중 결과에 적합하지만 바깥 Layer로 노출하지 않는다.
  • Projections.fields/bean/constructor: DTO 결합 방식과 Runtime 실패 특성이 다르다.
  • @QueryProjection: Compile-time 안전성이 높지만 DTO가 Querydsl에 의존하고 Q Type 생성이 필요하다.
flowchart LR; A[검색 조건] --> B[BooleanExpression 조합]; B --> C[JPQL/SQL 생성]; C --> D[Entity 또는 DTO Projection]

Bulk Update 주의

Bulk Update/Delete는 Persistence Context를 거치지 않고 Database를 직접 변경한다. 이미 관리 중인 Entity 상태와 Database가 달라질 수 있으므로 실행 전 Flush, 실행 후 Clear 또는 Transaction 경계 분리를 고려한다.

entityManager.flush();
queryFactory.update(member)
    .set(member.username, "inactive")
    .where(member.age.lt(18))
    .execute();
entityManager.clear();

실무에서 발생하는 문제

  • 선택 조건과 Join이 한 Repository Method에 계속 추가되어 읽기 어려운 Query Object가 된다.
  • DTO Constructor 순서 변경이 Runtime 오류로 이어진다.
  • Count Query가 본 Query의 불필요한 Join을 그대로 가져가 Pagination이 느려진다.
  • Bulk 연산 후 같은 Transaction에서 오래된 Entity를 다시 사용한다.

Trade-off

Type Safety와 동적 조합성을 얻지만 Q Type 생성, Build 설정, Repository 구현 코드가 늘어난다. 정적인 단순 Query까지 모두 Querydsl로 바꿀 필요는 없다.

Interview Questions

  1. BooleanBuilder와 Where 다중 Parameter 방식의 차이는 무엇인가?
  2. @QueryProjection의 Type Safety와 Architecture Trade-off는 무엇인가?
  3. Bulk Update 후 Persistence Context를 정리해야 하는 이유는 무엇인가?
  4. Entity 조회와 DTO Projection을 선택하는 기준은 무엇인가?

Persistence Context와 Bulk 연산 불일치를, Fetch Join과 조회 전략을 연결한다.

SOURCE REFERENCES

이 문서의 근거

본문은 Dev Atlas 안에서 완결되며, 검증이 필요할 때만 원문을 확인할 수 있습니다.

원문 출처 보기 2