Heestory

JPA 페이징 처리 본문

개발(0)/JPA

JPA 페이징 처리

까만밀가루 2025. 2. 7. 23:58

 

✅ 1. 페이징 처리란?

페이징 처리는 대량의 데이터를 일정한 크기로 나누어 필요한 부분만 조회하는 방식입니다. 이는 데이터베이스의 성능을 최적화하고, 사용자에게 빠른 응답 속도를 제공합니다.

  • Page: 전체 페이지 정보
  • Pageable: 페이지 요청 정보 (페이지 번호, 크기, 정렬 기준 등)
  • Slice: 다음 페이지 유무만 확인 가능 (더 가벼움)

 

🚀 2. 기본적인 JPA 페이징 처리

📌 Repository 설정

public interface ReviewRepository extends JpaRepository<Review, Long> {
    Page<Review> findByProductId(Long productId, Pageable pageable);
}

 

findByProductId 메서드는 Pageable을 파라미터로 받아 페이징 처리된 결과를 반환합니다.

 

📌 Service 레이어

@Service
public class ReviewService {
    @Autowired
    private ReviewRepository reviewRepository;

    public Page<Review> getReviewsByProductId(Long productId, Pageable pageable) {
        return reviewRepository.findByProductId(productId, pageable);
    }
}

 

📌 Controller

@RestController
@RequestMapping("/products")
public class ReviewController {
    @Autowired
    private ReviewService reviewService;

    @GetMapping("/{id}/reviews")
    public ResponseEntity<Page<Review>> getReviewsByProductId(
        @PathVariable Long id,
        Pageable pageable // 자동으로 page, size, sort 매핑
    ) {
        return ResponseEntity.ok(reviewService.getReviewsByProductId(id, pageable));
    }
}

 

 

📌 요청 예시

GET /products/1/reviews?page=0&size=5&sort=createdAt,desc

 

  • page=0: 첫 번째 페이지 (0부터 시작)
  • size=5: 한 페이지에 5개 데이터 표시

sort=createdAt,desc: 생성일 기준 내림차순 정렬

 

 


🔍 3. 커스텀 정렬 처리

기본 정렬 외에 복잡한 정렬 로직이 필요한 경우 @RequestParam을 활용합니다.

📌 복합 정렬 예제

@GetMapping("/{id}/reviews")
public ResponseEntity<Page<Review>> getReviewsByProductId(
    @PathVariable Long id,
    @RequestParam(defaultValue = "latest") String sort,
    Pageable pageable
) {
    Sort sortOption = sort.equals("rating") ?
        Sort.by(Sort.Direction.DESC, "rating") :
        Sort.by(Sort.Direction.DESC, "createdAt");

    Pageable sortedPageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sortOption);
    return ResponseEntity.ok(reviewService.getReviewsByProductId(id, sortedPageable));
}

 

  • rating: 별점순으로 정렬
  • latest: 최신순으로 정렬 (기본값)

📌 프론트엔드 요청 예시

/products/1/reviews?page=0&size=5&sort=rating

 

 

📌 복합 정렬 처리 (별점 + 최신순)

if ("ratingWithDate".equals(sort)) {
    sortOption = Sort.by(Sort.Order.desc("rating"), Sort.Order.desc("createdAt"));
}

 

별점이 같을 경우 최신순으로 정렬하는 복합 조건

 

 


⚠️ 4. Pageable의 한계와 커스텀 로직 필요성

프로젝트 과정 중 Pageable은 매우 편리하지만, 복잡한 정렬 조건에서는 한계가 있었다.

❌ 어려운 사례 1: 복합 정렬 (다중 조건)

리뷰를 별점 높은 순으로 정렬하되, 같은 별점일 경우 최신순으로 정렬

/products/1/reviews?sort=rating,desc&sort=createdAt,desc

 

이처럼 두가지 조건을 한 번에 정렬이 어려웠다.

 

❌ 어려운 사례 2: 사용자 맞춤형 정렬

특정 사용자에게는 별점순, 다른 사용자에게는 최신순으로 정렬

if (userId == 1) {
    pageable = PageRequest.of(0, 5, Sort.by("rating").descending());
} else {
    pageable = PageRequest.of(0, 5, Sort.by("createdAt").descending());
}

 

 


⚡ 5. Pageable vs @RequestParam 비교

구분 Pageable 사용 @RequestParam 사용
간결함 매우 간결 약간 더 복잡
커스텀 정렬 제한적 유연하게 처리 가능
복합 로직 처리 어려움 복잡한 조건에 적합
추천 상황 기본적인 페이징 및 정렬 커스텀 정렬 또는 복잡한 비즈니스 로직

 


이렇게 해서 초기 Pageable에 대한 페이징 처리를 했었는데, 프로젝트에서 리뷰는 최신순, 별점순하더라도 내부 커스텀이 들어가 있기 때문에 RequestParam으로 이용하여 페이징 처리를 하였다.