이 포스팅에서는 메인 화면에서 상품을 등록일, 낮은 가격, 높은 가격, 상품명 별로 정렬하는 기능을 QueryDSL에서 제공하는 OrderSpecifier 클래스를 활용하여 구현한 과정에 대해서 간략하게 정리하고자 한다.
현재 메인 화면에서 상품을 출력하는 쿼리는 Querydsl을 사용하여 작성되었다. 동적 정렬을 구현하기 위해 여러 개의 API를 만들어 호출하는 것은 리소스를 낭비하고 복잡성을 증가시킬 수 있다. Querydsl에서는 OrderSpecifier을 사용하여 정렬 조건을 간단히 추가할 수 있다. OrderSpecifier를 리스트로 선언한 이유는 현재는 하나의 정렬 조건이지만, 추후에 여러 개의 정렬 조건이 추가될 수 있기 때문이다.
/* ItemRepositoryCustomImpl.java */
@Override
public Page<MainItemDto> getMainItemPage(ItemSearchDto itemSearchDto, Pageable pageable) {
QItem item = QItem.item;
QItemImg itemImg = QItemImg.itemImg;
List<MainItemDto> content = queryFactory
.select(
new QMainItemDto(
item.id,
item.itemNm,
item.category,
item.itemDetail,
itemImg.imgUrl,
item.price,
item.discount)
)
.from(itemImg)
.join(itemImg.item, item)
.where(itemImg.repImgYn.eq("Y"))
.where(itemNmLike(itemSearchDto.getSearchQuery())
.or(itemCategoryLike(itemSearchDto.getCategory()))
.and(item.itemSellStatus.eq(ItemSellStatus.SELL)))
.orderBy(createOrderSpecifier(itemSearchDto))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
JPAQuery<Long> total = queryFactory
.select(item.count())
.from(itemImg)
.join(itemImg.item, item)
.where(itemImg.repImgYn.eq("Y"))
.where(itemNmLike(itemSearchDto.getSearchQuery()));
return PageableExecutionUtils.getPage(content, pageable, total::fetchOne);
}
// ProductSearchDTO 객체의 정렬 기준에 따라 OrderSpecifier 배열을 생성하는 메서드
private OrderSpecifier[] createOrderSpecifier(ProductSearchDTO productSearchDto) {
// OrderSpecifier 객체들을 담을 리스트를 생성
List<OrderSpecifier> orderSpecifiers = new ArrayList<>();
// 정렬 기준이 없거나, "new"이거나, 빈 문자열일 경우
if (Objects.isNull(productSearchDto.getSort()) || productSearchDto.getSort().equals("new") || productSearchDto.getSort().isEmpty()) {
// product.id를 기준으로 내림차순 정렬 (최신 상품 우선)
orderSpecifiers.add(new OrderSpecifier(Order.DESC, product.id));
}
// 정렬 기준이 "best"인 경우
else if (productSearchDto.getSort().equals("best")) {
// product.averageRating을 기준으로 내림차순 정렬 (평점 높은 순)
orderSpecifiers.add(new OrderSpecifier(Order.DESC, product.averageRating));
}
// 정렬 기준이 "low"인 경우
else if (productSearchDto.getSort().equals("low")) {
// product.price를 기준으로 오름차순 정렬 (가격 낮은 순)
orderSpecifiers.add(new OrderSpecifier(Order.ASC, product.price));
}
// 정렬 기준이 "high"인 경우
else if (productSearchDto.getSort().equals("high")) {
// product.price를 기준으로 내림차순 정렬 (가격 높은 순)
orderSpecifiers.add(new OrderSpecifier(Order.DESC, product.price));
}
// 정렬 기준이 "name"인 경우
else if (productSearchDto.getSort().equals("name")) {
// product.name을 기준으로 오름차순 정렬 (이름 순)
orderSpecifiers.add(new OrderSpecifier(Order.ASC, product.name));
}
// 리스트에 담긴 OrderSpecifier 객체들을 배열로 변환하여 반환
return orderSpecifiers.toArray(new OrderSpecifier[orderSpecifiers.size()]);
}