성능 최적화 요소까지 완벽한 고려는 아니지만 코드는 많이 정리된 거 같아서 적어둔다.

React 에서는 pk 값이 직접 노출되지 않도록 암호화처리하고, 대신에 no 를 넣어서 처리했다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
@Repository
@Transactional
@RequiredArgsConstructor
@Log4j2
public class ProductSearchImpl implements ProductSearch {
 
    private final JPAQueryFactory queryFactory;
    private final CryptoUtil cryptoUtil;
 
    @Override
    public Page<ProductDTO> searchList(PageRequestDTO pageRequestDTO) {
        QProduct product = QProduct.product;
        QProductImage productImage = QProductImage.productImage;
 
        SearchConditionBuilder<Product> scb = new SearchConditionBuilder<>(Product.class"product");
 
        String where = pageRequestDTO.getFilter().getWhere();
        String keyword = pageRequestDTO.getFilter().getKeyword();
 
        OrderSpecifier<?> orderSpecifier = product.pno.desc(); // 기본값: pno 내림차순
 
        if (keyword != null && !keyword.isBlank()) {
            switch (where) {
                case "pname" -> scb.addLike("pname", keyword);
                case "desc" -> scb.addLike("pdesc", keyword);
                case "price" -> {
                    try {
                        int minPrice = Integer.parseInt(keyword);
                        scb.addGreaterThanEqual("price", minPrice);
                        orderSpecifier = product.price.asc(); // 가격 오름차순 정렬
                    } catch (NumberFormatException e) {
                        log.warn("가격 필터 숫자 변환 실패: {}", keyword);
                    }
                }
            }
        }
 
        BooleanBuilder builder = scb.build();
 
        Pageable pageable = PageRequest.of(
            pageRequestDTO.getPage() - 1,
            pageRequestDTO.getSize()
        );
 
        List<Product> productList = queryFactory
            .selectFrom(product)
            .leftJoin(product.imageList, productImage).fetchJoin()
            .where(product.delFlag.eq(false)
                .and(productImage.ord.eq(0))
                .and(builder))
            .offset(pageable.getOffset())
            .limit(pageable.getPageSize())
            .orderBy(orderSpecifier)
            .fetch();
 
        long totalCount = queryFactory
            .select(product.count())
            .from(product)
            .leftJoin(product.imageList, productImage)
            .where(product.delFlag.eq(false)
                .and(productImage.ord.eq(0))
                .and(builder))
            .fetchOne();
 
        List<ProductDTO> dtoList = IntStream.range(0, productList.size())
            .mapToObj(i -> {
                Product entity = productList.get(i);
                int no = (int) (totalCount - (pageable.getPageNumber() * pageable.getPageSize()) - i);
                return toDTO(entity, no);
            }).toList();
 
        return new PageImpl<>(dtoList, pageable, totalCount);
    }
 
    private ProductDTO toDTO(Product product, int no) {
        String encryptedPno = cryptoUtil.encryptAES(String.valueOf(product.getPno()));
 
        List<String> fileNames = product.getImageList().stream()
            .map(ProductImage::getFileName)
            .toList();
 
        return ProductDTO.builder()
            .no(no)
            .pno(encryptedPno)
            .pname(product.getPname())
            .price(product.getPrice())
            .pdesc(product.getPdesc())
            .uploadFileNames(fileNames)
            .build();
    }
}
 
728x90

'Spring Boot > Basic' 카테고리의 다른 글

Spring Boot 이미지 로딩 문제  (0) 2025.05.24
Spring Boot fetch join  (0) 2025.05.19
Spring Boot 3.4.5 QueryDSL 예제 개선  (0) 2025.05.04
Spring Boot 3.4.5 QueryDSL 예제  (0) 2025.05.04
Spring Boot 3.4.5 JOOQ TodoSearch 예제  (0) 2025.05.03
블로그 이미지

Link2Me

,