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 연동
TodoService에 searchTodos() 메서드 작성
TodoController에서 /api/todos/search GET API 제공
Pageable 기반 결과 반환
✅ 완성 결과
- 검색 조건별 필터링
- title, nickname, createdAt 조건 조합
- 페이징 + 결과 개수 카운트
- 필요한 데이터만 DTO로 반환