[Spring] 페이징 처리하기 (Pageable 사용)

이수민·2023년 3월 3일
0

spring

목록 보기
12/12

오늘은 Spring에서 페이징(Paging) 처리를 하는 방법에 대해 알아보려 한다.
List 목록을 반환할 때 페이징 처리가 자주 사용되기 때문에 이 참에 알아두는 것이 좋을 것 같았다.

Paging

페이징은 속도는 빠르게, 부하는 적게 하기 위해 지금 당장 필요한 데이터만 가져올 수 있도록 데이터를 분리하는 작업이다.
ex) 게시판 목록, 댓글 목록..



Pageable

Spring에서는 데이터를 페이지 단위로 처리하기 위해 Pageable 인터페이스와 Page 인터페이스를 제공한다.

  • Pageable : 요청된 페이지와 페이지당 데이터 수 등을 포함하는 객체
  • Page : 요청된 페이지에 해당하는 데이터를 담고 있는 객체

Pageable 인터페이스

Pageable 인터페이스는 다음과 같다.

public interface Pageable {
    int getPageNumber();
    int getPageSize();
    long getOffset();
    Sort getSort();
    Pageable next();
    Pageable previousOrFirst();
    Pageable first();
    boolean hasPrevious();
    default Sort getSortOr(Sort sort) {
        return getSort().isSorted() ? getSort() : sort;
    }
}

Page 인터페이스

Pageable 인터페이스를 사용하여 데이터를 조회하면 Page 객체가 반환된다. Page 객체는 다음과 같이 선언된다.

public interface Page<T> extends Slice<T> {
    int getTotalPages();
    long getTotalElements();
    <U> Page<U> map(Function<? super T, ? extends U> converter);
    boolean hasPrevious();
    boolean isFirst();
    boolean isLast();
    boolean hasNext();
    Pageable nextPageable();
    Pageable previousPageable();
    Iterator<T> iterator();
    List<T> getContent();
    boolean hasContent();
    Sort getSort();
}
  • getTotalPages() : 전체 페이지 수
  • getTotalElements() : 전체 데이터 수
  • getContent() : 요청된 페이지의 데이터를 리스트로 반환

Pageable과 Page 에 대해 알았으니, 바로 구현으로 넘어가보자.



Paging 구현

예시 Controller를 하나 생성해보자.

// Controller
@GetMapping("/list")
public ResponseEntity<?> getLists(
            @PageableDefault(size=10) Pageable pageable
) {
	Page<Dto> result = testService.getLists(pageable);
    return ResponseEntity.ok(result);
}

@PageableDefault()

  • Spring Data에서 제공하는 애노테이션 중 하나로, Pageable 객체의 디폴트 값을 설정할 때 사용된다.

  • Pageable 인터페이스를 구현한 객체를 생성하는 과정에서, 디폴트 값으로 사용되는 요청 파라미터를 지정한다.

    • (size = 10) : 페이지당 최대 10개의 데이터를 반환하도록
  • 다음과 같은 파라미터를 가질 수 있다.

    • size: 페이지당 결과 수의 디폴트 값. 기본값은 20
    • page: 요청한 페이지 번호의 디폴트 값. 기본값은 0
    • sort: 정렬 기준의 디폴트 값.
      • 예를 들어 @PageableDefault(sort={"firstName", "lastName"})은 firstName을 우선순위 1순위로 하고, 그 다음에 lastName을 우선순위 2순위로 정렬한다.

@PageableDefault를 사용하면, Pageable 객체의 기본 값을 쉽게 설정할 수 있어 편리합니다.


다음으로 Service 메서드와 Repository를 구현해보자.

// Service
public Page<Dto> getLists(Pageable pageable) {
	return testRepository.findAll(pageable).map(Dto::new);
}
// testRepository (JPA)
Page<User> findAll(Pageable pageable);

그리고 요청을 보낼 때 파라미터와 함께 보내면 된다.
/list?page= &size= &sort=



PageImpl

위에선 JPA 메서드 파라미터에 Pageable을 던지고 결과 목록을 Page로 감싸서 반환받은게 끝이었다.
하지만 만약 Service 로직 내에서 가공된 ListPaging 하고 싶다면?
PageImpl을 사용하자.

PageImpl 클래스

PageImpl

Spring Data JPA에서 Page 인터페이스의 구현 클래스 중 하나이다. 생성자를 통해 List 객체, Pageable 객체, 전체 데이터의 총 개수를 받아 Page 객체를 생성한다.

PageImpl(List + Pageable) -> Page 라는 것이다.
한번 사용해보자.

Controller는 그대로 사용하고, Service 로직만 수정해보자.

// Service
public Page<Dto> getLists(Pageable pageable) {
	List<Dto> result = new ArrayList<>();
    ... // result에 값 넣는 로직
    
	int start = (int) pageable.getOffset();
    int end = Math.min((start + pageable.getPageSize()), result.size());
    return new PageImpl<>(result.subList(start, end), pageable, result.size());
}
  • new PageImpl<List, Pageable, 데이터 총 개수>(); => Page 객체로 반환

이제부터 List를 반환할 때 성능 향상을 위해 Page로 감싸서 반환하자.

profile
BE 개발자를 꿈꾸는 학생입니다🐣

0개의 댓글