🌿SPRING/🌱연습[SPRING]

[SPRING][JPA] Paging/Pagination - Pageable 객체 받아 사용하기

디카페인라떼 2022. 10. 11. 16:29
더보기
Paging / Pagination
  • DB에 저장된 데이터들을 페이지에 맞춰서 몇 개씩 뿌릴건지 알려주는 것
  • DB에 저장된 데이터가 20개이고 프론트에서 1페이지에 5개씩 이라고 요청하면
  • 백엔드에서 전체 DB에서 데이터를 앞에서부터 5개씩 분류하여 해당 페이지에 맞는 데이터를 넘겨줌.

 

JPA - Pageable
  • 이를 위해서 JPA에서 Pageable이라는 객체를 제공하고있다.
  • Pageable이란?

  • Pageable 이 Pagination 요청 정보를 담기위한 추상 인터페이스 라는 의미/실제로 쓰기 위해서는 구현체가 필요
    • class QPageRequest : QueryDSL 을 위한 Pageable 구현체
    • class PageRequest : 가장 기본적인 Pageable 구현체
    • enum Unpaged : pagination 정보가 없는 것을 표현하기위한 구현체. INSTANCE 를 가지고 있다.

이 중 가장 기본이 되는 PageRequest 를 가장 많이 사용 (보통 Cusotom Query를 사용해서 같이 사용함.)


  • Repository
public interface MeetingRepository extends JpaRepository<Meeting,Long> {
  Page<Meeting> findAllByOrderByCreatedAtDesc( Pageable pageable);

 

  • Controller
@GetMapping
public ResponseDto<Page<MeetingResponseDto>> getAllMeeting(@PageableDefault(size = 12) Pageable pageable) {
  return ResponseDto.success(meetingService.getAllMeeting(pageable));
}

👉 Pageable을 객체로 넘기면서 Repository에서 원하는 만큼의  Page를 반환 받는다.

더보기

✔ Page vs Slice

Page<User> findByLastname(String lastName, Pageable pageable);

Slice<User> findByLastname(String lastName, Pageable pageable);

List<User> findByLastname(String lastName, Pageable pageable);

JPA에서는 반환 값으로 List, Slice, Page 로 다양하게 제공하고 있다. Page 구현체의 경우에는 전체 Page의 크기를 알아야 하므로, 필요한 Page의 요청과 함께, 전체 페이지 수를 계산하는 count 쿼리가 별도로 실행된다. 

Slice 구현체의 경우에는 전후의 Slice가 존재하는지 여부에 대한 정보를 가지고 있다. 각 특성을 익혀 본인의 상황에 적합한 자료형을 사용하는 것을 추천한다.

spring.jpa.show-sql=true 옵션을 설정 파일에 추가하면 Page를 반환하는 메소드 실행 시, 실제로 count 명령어가 실행되는 것을 확인 할 수 있다.

🤯Slice는 Iterable을 구현하고 List와 페이지처리에 쓸만한 다양한 멤버변수, 메서드들을 명시한 인터페이스이고,

Page는 Slice 를 확장한 인터페이스로 사용시에는 JPA 내부에서 페이징 처리를 하려하는 데이터들의 총 갯수(total count) 쿼리를 하나 더 날리게되며, 이를 활용하는 getTotalPages(), getTotalElements() 메서드 등을 사용할 수 있다.

따라서 페이징 박스를 렌더링하는 정책에 따라 Page나 Slice중 하나를 골라 사용하면 된다.

 

https://www.jiniaslog.co.kr/article/view?articleId=202 

 

스프링 JPA 환경에서 오프셋 페이징을 커서 페이징으로 개선하기 - Jinia's LOG'

페이지네이션(Pagination) 한정된 네트워크 자원을 효율적으로 활용하기 위하여 특정 정렬 기준에 따라 데이터를 분할하여 가져오는 방식 데이터 베이스에서 조회하려는 데이터의 양이 일정 이상

www.jiniaslog.co.kr

 

 

Spring JPA에서는 페이징 기능을 제공한다.

 

JPA Repository를 사용하면서 매개변수에 Pageable만 추가하면 끝이다.

그 이유는 이미 JpaRepository가 PagingAndSortingRepository를 구현하고 있기 때문이었다.

 

Pageable 구현체는 PageRequest 를 사용하면 되고, 페이지 번호와 페이지 사이즈를 넣어주면 된다.

 

Page, Slice 혹은 List를 반환형으로 가지며, Page는 전체 페이지 수와 전체 데이터수를 가진다.

Slice는 count는 알지 못하고 단지 더보기 기능을 위해 limit + 1을 조회할 뿐이다.

List는 어떠한 count도 알지 못한다.

  • Service 도 변경해준다
public Page<MeetingResponseDto> getAllMeeting(Pageable pageable) {

    Page<Meeting> meetingList = meetingRepository.findAllByOrderByCreatedAtDesc(pageable);
    List<MeetingResponseDto> meetingResponseDtoList = new ArrayList<>();

    for (Meeting meeting : meetingList) {
        MeetingResponseDto meetingResponseDto = new MeetingResponseDto(meeting);
        meetingResponseDtoList.add(meetingResponseDto);
    }

    return new PageImpl<>(meetingResponseDtoList, pageable, meetingList.getTotalElements());
}

👉 new PageImpl 구현체를 사용하여 Page를 반환해주면 된다

 

PageImpl?
  • Page의 구현체 PageImpl

  • content : 해당 페이지에 들어갈 내용 (리스트)
  • pageable : 요청한 페이지의 정보
  • total : 들어갈 내용들의 양 (총 데이터의 갯수)

 

 

Postman 조회
  1. 파라미터 정보 없이 요청한 경우

  • totalPages : 총 페이지 수
  • totalElements : DB의 전체 데이터 갯수
  • last : 마지막 페이지 인지
  • size : 페이지 당 나타낼 수 있는 데이터의 갯수
  • number : 현재 페이지의 번호
  • sort 
    • Sorting에 대한 값을 설정하는 파라미터. 기본적으로 오름차순.
    • 표기는 정렬한 필드명 , 정렬기준(ex. sort=title,asc    sort=rank,desc) 
    • 현재는 설정이 되어있지 않아 sorted = false로 나와있다.
  • numberOfElements : 실제 데이터의 갯수
  • first : 첫번째 페이지 인지
  • empty : 리스트가 비어있는지 여부

 

2. size = 2 로 보낸 경우 (?size=2)

  • size가 2로 변경이 되어있고 첫번째 페이지만 출력이 된 걸 알수 있다.