티스토리 뷰

728x90

Page<Entity>를 꺼내는 방법은 정말 쉽다. 이미 JPA에 의해 다 구현이 되어있으므로 그냥 파라미터로 Pageable을 넘겨서 Page<Entity>를 리턴받으면 끝이다.

하지만 이 Entity를 DTO로 변환시켜서 넘겨야 하는건 생각보다 까다롭다.

 

Page 인터페이스는 List<Entity>, Pageable, totalElements 3가지를 가지고 있는 형태라고 볼 수 있다.

하지만 Page<>로 넘기지않고 PageImpl을 사용한다거나 하면 boundary 값 처리를 직접 해줘야 하는 등 귀찮은 일이 생긴다.

 

기본적인 구현 방법은 람다식을 이용하여 돌면서 값을 converting 해주면 된다.

여기서 중요한 점은 이때 사용되는 map 함수는 Page 인터페이스의 map이다.

선택하려고 해서 선택할 수 있는 것은 아니지만 map은 Stream의 map도 있고 Optional의 map도 있다.

public Page<ItemResponse> showItemsBySeller(User user, Pageable pageable) {
        Seller seller = sellerRepository.findByUserIdAndIsActivatedTrue(user.getId())
                .orElseThrow(() -> new SellerNotFoundException("판매자 권한이 없습니다"));

        return itemRepository.findBySellerId(seller.getId(), pageable)
                .map(item -> ItemResponse.builder()
                        .id(item.getId())
                        .name(item.getName())
                        .price(item.getPrice())
                        .build());

 

Page<Item> findBySellerId(Long id, Pageable pageable);

 

위에서 사용되는 findBySellerId()는 단순히 Page<Entity>를 반환하는 메서드였다.


 

이때 Optional을 사용하여 null-safe하게 처리하고 싶으면 어떻게 해야할까?

Optional<Page<Entity>>을 리턴해야 할까 Page<Optional<Entity>>을 리턴해야할까?

 

둘다 람다식을 돌며 처리해야 하는 것은 같다. 하지만 Optional의 처리 방식을 생각하면 Optional<Page<Entity>>의 형태로 반환하는 것이 바람직하다고 생각한다.

 

코드는 다음과 같다.

 

public Page<ItemResponse> searchItemsByKeyword(String keyword, Pageable pageable) {

    return itemRepository.findByNameContaining(keyword, pageable)
            .map(items -> items.map(item -> ItemResponse.builder()
                    .id(item.getId())
                    .name(item.getName())
                    .price(item.getPrice())
                    .build()))
            .orElseThrow(() -> new ItemNotFoundException("해당 키워드에 맞는 상품이 없습니다"));
Optional<Page<Item>> findByNameContaining(@Param("q") String name, Pageable pageable);

 

이때 위에서 말했던 map의 차이점이 여기에서 나온다.

첫번째의 map이 Optional을 처리해주는 map이고 

이 map에서 한 번 더 들어가서 사용되는 map이 Page의 map이다.

 

2번의 map처리를 nested 형태로 처리해줘야 하는 것을 명심해야 하며

Optional<Page<Entity>>의 형태로 만들었기에 마지막에 한번의 Optional 처리만 해주면 된다.

 

익숙해지면 편리하긴 한데 성능상의 문제가 생기지 않을까 걱정되기에성능 테스트를 돌려봐야 할 것으로 생각됨

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
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
글 보관함