오늘은 Spring에서 페이징(Paging)
처리를 하는 방법에 대해 알아보려 한다.
List 목록을 반환할 때 페이징 처리가 자주 사용되기 때문에 이 참에 알아두는 것이 좋을 것 같았다.
Paging
페이징은
속도는 빠르게
,부하는 적게
하기 위해 지금 당장 필요한 데이터만 가져올 수 있도록 데이터를 분리하는 작업이다.
ex) 게시판 목록, 댓글 목록..
Spring에서는 데이터를 페이지 단위로 처리하기 위해
Pageable
인터페이스와Page
인터페이스를 제공한다.
- Pageable : 요청된 페이지와 페이지당 데이터 수 등을 포함하는 객체
- Page : 요청된 페이지에 해당하는 데이터를 담고 있는 객체
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;
}
}
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 에 대해 알았으니, 바로 구현으로 넘어가보자.
예시 Controller
를 하나 생성해보자.
// Controller
@GetMapping("/list")
public ResponseEntity<?> getLists(
@PageableDefault(size=10) Pageable pageable
) {
Page<Dto> result = testService.getLists(pageable);
return ResponseEntity.ok(result);
}
Spring Data
에서 제공하는 애노테이션 중 하나로, Pageable
객체의 디폴트 값
을 설정할 때 사용된다.
Pageable 인터페이스를 구현한 객체를 생성하는 과정에서, 디폴트 값으로 사용되는 요청 파라미터를 지정한다.
(size = 10) : 페이지당 최대 10개의 데이터를 반환하도록
다음과 같은 파라미터
를 가질 수 있다.
size
: 페이지당 결과 수의 디폴트 값. 기본값은 20page
: 요청한 페이지 번호의 디폴트 값. 기본값은 0sort
: 정렬 기준의 디폴트 값.
@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=
위에선 JPA 메서드 파라미터에 Pageable
을 던지고 결과 목록을 Page
로 감싸서 반환받은게 끝이었다.
하지만 만약 Service 로직 내에서 가공된 List
를 Paging
하고 싶다면?
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로 감싸서 반환하자.