상품 페이징 및 정렬

금은체리·2023년 11월 18일
1

Spring

목록 보기
39/49

페이징 및 정렬 설계

  • UI

  • 상품 조회 API 수정 필요 (GET /api/products)

  • Client ➡️ Server

    1. 페이징
      • page : 조회할 페이지 번호 (1부터 시작)
      • size : 한 페이지에 보여줄 상품 개수 (10개로 고정)
    2. 정렬
      • sortBy (정렬 항목)
        • id : Product 테이블의 id
        • title : 상품명
        • lprice : 최저가
      • isAsc (오름차순?)
        • true : 오름차순(asc)
        • false : 내림차순(desc)
  • Server ➡️ Client

    • number : 조회된 페이지 번호 (0부터 시작)

    • content : 조회된 상품 정보 (배열)

    • size : 한 페이지에 보여줄 상품 개수

    • numberOfElements : 실제 조회된 상품 개수

    • totalElements : 전체 상품 개수 (회원이 등록한 모든 상품의 개수)

    • totalPages : 전체 페이지 수

      totalPages = totalElement / size 결과를 소수점 올림
      1 / 10 = 0.1 => 총 1 페이지
      9 / 10 = 0.9 => 총 1페이지
      10 / 10 = 1 => 총 1페이지
      11 / 10 => 1.1 => 총 2페이지
      
    • first : 첫 페이지인지? (boolean)

    • last : 마지막 페이지인지? (boolean)

Spring Data 페이징, 정렬 기능 확인하기
  • Spring Data에서 페이징 및 정렬 기능을 제공하기 때문에 손쉽게 페이징, 정렬을 구현 가능
Sort.Direction direction = isAsc ? Sort.Direction.ASC : Sort.Direction.DESC;
Sort sort = Sort.by(direction, sortBy);
Pageable pageable = PageRequest.of(page, size, sort);

Page<Product> products = productRepository.findAllByUser(user, pageable);
  • Pageable은 손쉽게 페이징, 정렬 처리를 하기위해 제공되는 인터페이스이며 PageRequest는 해당 인터페이스의 구현체
  • 파라미터로 (현재 페이지(0시작), 데이터 노출 개수, 정렬 방법(ASC, DESC))
  • 를 전달하여 생성된 Pageable 구현 객체를 Spring Data JPA의 Query Method 파라미터에 함께 전달하면 페이징 및 정렬 처리가 완료된 데이터를 Page 타입으로 반환
  • Page 타입에는 Client에 전달해야할 데이터인 totalPages, totalElements 등의 데이터를 함께 포함하고 있음

페이징 및 정렬 구현

  • 페이징 및 정렬 기능 추가로 인한 Client 코드 변경
  • 페이징 및 정렬 기능 추가로 인한 Server 코드 변경

테스트 데이터 생성

package com.sparta.myselectshop.util;

import com.sparta.myselectshop.entity.Product;
import com.sparta.myselectshop.entity.User;
import com.sparta.myselectshop.entity.UserRoleEnum;
import com.sparta.myselectshop.naver.dto.ItemDto;
import com.sparta.myselectshop.naver.service.NaverApiService;
import com.sparta.myselectshop.repository.ProductRepository;
import com.sparta.myselectshop.repository.UserRepository;
import com.sparta.myselectshop.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

import static com.sparta.myselectshop.service.ProductService.MIN_MY_PRICE;

@Component
public class TestDataRunner implements ApplicationRunner {

    @Autowired
    UserService userService;
    @Autowired
    ProductRepository productRepository;
    @Autowired
    UserRepository userRepository;
    @Autowired
    PasswordEncoder passwordEncoder;
    @Autowired
    NaverApiService naverApiService;

    @Override
    public void run(ApplicationArguments args) {
        // 테스트 User 생성
        User testUser = new User("Robbie", passwordEncoder.encode("1234"), "robbie@sparta.com", UserRoleEnum.USER);
        testUser = userRepository.save(testUser);

        // 테스트 User 의 관심상품 등록
        // 검색어 당 관심상품 10개 등록
        createTestData(testUser, "신발");
        createTestData(testUser, "과자");
        createTestData(testUser, "키보드");
        createTestData(testUser, "휴지");
        createTestData(testUser, "휴대폰");
        createTestData(testUser, "앨범");
        createTestData(testUser, "헤드폰");
        createTestData(testUser, "이어폰");
        createTestData(testUser, "노트북");
        createTestData(testUser, "무선 이어폰");
        createTestData(testUser, "모니터");
    }

    private void createTestData(User user, String searchWord) {
        // 네이버 쇼핑 API 통해 상품 검색
        List<ItemDto> itemDtoList = naverApiService.searchItems(searchWord);

        List<Product> productList = new ArrayList<>();

        for (ItemDto itemDto : itemDtoList) {
            Product product = new Product();
            // 관심상품 저장 사용자
            product.setUser(user);
            // 관심상품 정보
            product.setTitle(itemDto.getTitle());
            product.setLink(itemDto.getLink());
            product.setImage(itemDto.getImage());
            product.setLprice(itemDto.getLprice());

            // 희망 최저가 랜덤값 생성
            // 최저 (100원) ~ 최대 (상품의 현재 최저가 + 10000원)
            int myPrice = getRandomNumber(MIN_MY_PRICE, itemDto.getLprice() + 10000);
            product.setMyprice(myPrice);

            productList.add(product);
        }

        productRepository.saveAll(productList);
    }

    public int getRandomNumber(int min, int max) {
        return (int) ((Math.random() * (max - min)) + min);
    }
}
  • implements ApplicationRunner
    • Spring이 처음에 run 할 때 내부 코드들이 수행됨
    • = run 메서드가 수행됨
      • 그래서 @Component로 등록
profile
전 체리 알러지가 있어요!

0개의 댓글