Lv3-10: QueryDSL 기반 검색 기능 정리

박화랑·2025년 5월 2일

1. 사용 기술 및 목적

항목설명
QueryDSL동적 쿼리 생성, 타입 안정성 확보
Projections필요한 필드만 선택적으로 반환 (DTO 직접 매핑)
페이징 처리Pageable, PageImpl 사용
동적 조건 처리BooleanExpression 활용 (null 조건 자동 무시)
조인 및 집계leftJoin, groupBy, countDistinct 등 사용

2. 📄 주요 클래스 요약

TodoSearchCond (검색 조건 DTO)

record TodoSearchCond(String keyword, LocalDateTime startDate, LocalDateTime endDate, String nickname)

TodoSearchResponse (검색 응답 DTO)

record TodoSearchResponse(String title, long managerCount, long commentCount)

TodoQueryRepositoryImpl (QueryDSL 로직 구현)

List<TodoSearchResponse> contents = queryFactory
    .select(Projections.constructor(TodoSearchResponse.class,
        todo.title,
        manager.countDistinct(),
        comment.countDistinct()))
    .from(todo)
    .leftJoin(todo.managers, manager)
    .leftJoin(manager.user, user)
    .leftJoin(todo.comments, comment)
    .where(
        containsTitle(cond.keyword()),
        betweenCreatedAt(cond.startDate(), cond.endDate()),
        containsNickname(cond.nickname()))
    .groupBy(todo.id)
    .offset(pageable.getOffset())
    .limit(pageable.getPageSize())
    .fetch();

✅ 동적 조건 메서드

private BooleanExpression containsTitle(String keyword) {
    return keyword != null ? todo.title.containsIgnoreCase(keyword) : null;
}

✅ Count 쿼리 (페이징용 total count 계산)

Long total = queryFactory
    .select(todo.countDistinct())
    .from(todo)
    ...
    .fetchOne();

3. Controller 및 Service 연동

  • TodoServicesearchTodos() 메서드 작성
  • TodoController에서 /api/todos/search GET API 제공
  • Pageable 기반 결과 반환

✅ 완성 결과

  • 검색 조건별 필터링
  • title, nickname, createdAt 조건 조합
  • 페이징 + 결과 개수 카운트
  • 필요한 데이터만 DTO로 반환

profile
개발자 희망생

0개의 댓글