Spring Data에서 Pageable
이 무엇이고 어떻게 활용할 수 있는지 알아보자!
데브코스에서 Spring JPA에 대해 공부하던 중 Pageable
을 활용하여 Pagination을 적용할 수 있다는 것을 알게 되었는데, Pagination이 무엇이고 Pageable
이 어떤 역할을 하는지 정확하게 인지하지 못하고 사용하는 것은 좋지 않다는 생각에 한번 공부해보자! 하고 포스트를 작성하게 되었다.
Pagination에 대한 정의를 찾아보니 아래와 같이 설명하고 있었다.
Pagination is the process of separating print or digital content into discrete pages. For print documents and some online content, pagination also refers to the automated process of adding consecutive numbers to identify the sequential order of pages.
Pagination은 데이터를 개별 페이지로 분리하고, 페이지의 순차적 순서를 식별하기 위해 연속적인 숫자를 추가하는 자동화된 프로세스라고 볼 수 있다.
우리가 Google에서 어떤 내용을 검색할 때 검색 결과에 대해 페이지를 나눠서 표현해주는 것처럼 많은 양의 데이터에 대해 페이지를 분리하고 순차적으로 제공하는 것을 Pagination이라고 할 수 있다.
그렇다면 Spring에서 Pagination을 적용하기 위해서는 어떻게 해야 할까? Spring은 Pageable
을 활용하여 Pagination을 활용할 수 있도록 해두었다.
@Controller
@RequestMapping("/post")
class PostRestController {
private final PostRepository repository;
PostRestController(PostRepository repository) {
this.repository = repository;
}
@GetMapping
public CommonResult<Page<PostServiceResponseDto>> getAllPost(Pageable pageable) {
return CommonResult.getResult(postService.findAll(pageable));
}
}
위와 같은 코드가 존재할 때 Pageable
은 아래 표와 같은 파라미터를 전달받음으로써 사용할 수 있다.
Parameter | Description |
---|---|
page | Page의 index를 요청합니다. 기본값 = 0 |
size | Page의 크기를 정해줍니다. 기본값 = 20 |
sort | 형식이나 property[(ASC | DESC), (.IgnoreCase)]를 전달함으로써 정렬 방식을 정할수 있습니다. 기본 정렬 방향은 대소문자를 구분하는 오름차순으로 정렬됩니다. |
예를 들어 .../post?page=0?size=10
Get 요청을 한다면 pageable은 page=0, size=10을 포함하게 된다.
PostReposity에 findAll(pageable)
을 실행하였을때의 SQL Query를 살펴보면 아래와 같은 Query를 요청하는 것을 확인할 수 있다.
select p1_0.id,p1_0.content,p1_0.created_at,p1_0.created_by,p1_0.title,p1_0.user_id
from post p1_0
offset ? rows
fetch first ? rows only
Pagination을 위해서 JPA에서 offset ? rows
, fetch first ? rows only
구문을 추가하여 Query를 요청하는데 각 Query의 역할은
offset ? rows
: 데이터 테이블의 전체 행중에서 ? 값만큼을 행을 건너뛴다.fetch first ? rows only
: 결과 집합에 지정될 행 수를 ?로 제한한다.이다.
즉 전체 테이블에서 정해진 값(page
*size
)만큼 건너 뛴 이후 순서대로 정해진 값(size
) 만큼을 반환하는 것이다.
테이블에서 반환된 값들은 Page<T>
형식으로 감싸져서 반환되는데 Page는 TotalPage
와 TotalElement
정보를 포함하고 있다.
Page<T>
와 Spring Document에서는 아래와 같은 주의점을 안내하고 있다.Often times,
COUNT(…)
queries are required that are costly.
Offset-based queries becomes inefficient when the offset is too large because the database still has to materialize the full result.
지금까지 API를 작성하면서 전체 조회의 경우에는 무조건 전체 데이터를 전송하게 작성했었는데 이번에 Pagination을 접하게 되면서 페이징을 통한 구분 방식도 활용할 수 있겠다고 생각했다.
What is pagination? – TechTarget Definition
Spring Data Commons - Web support
Spring Data JPA - Defining Query Methods