Spring Data JPA 에서는 페이징처리에서 사용되는 Pageable 인스턴스와 해당 인스턴스의 디폴트 값을 설정 및 변경할 수 있는 @PageableDefault 어노테이션을 제공한다.
@GetMapping("/comments")
public ResponseEntity<RestResponse<List<CommentsResponse>>> findComments(
@PageableDefault Pageable pageable,
@RequestParam String crewName,
@Authenticate AuthenticatedMember ignored
) {...}
위와같이 HandlerMethod 에서 @PageableDefault 를 사용하여 Pageable 인스턴스의 디폴트값을 변경할 수 있는 이유는 내부적으로 @PageableDefault 를 해석하기 위한 PageableHandlerMethodArgumentResolver
가 사용되기 때문이다.
Class 의존관계도
PageableHandlerMethodArgumentResolver 와 관련된 클래스에는 아래와 같다.
- PageableArgumentResolver
- PageableHandlerMethodArgumentResolverSupport
- PageableHandlerMethodArgumentResolverCustomizer
- SortHandlerMethodArgumentResolver (범위 밖이므로 나중에 다뤄보기로 한다.)
PageableArgumentResolver
- HandlerMethodArgumentResolver 를 extends 한 interface 이며, PageableHandlerMethodArgumentResolver 가 implement 한다.
PageableHandlerMethodArgumentResolverSupport
- PageableHandlerMethodArgumentResolver 가 extends 하고 있는 추상 클래스이며, WebRequest 로부터 페이징 정보를 만들기위한 메서드를 제공한다.
PageableHandlerMethodArgumentResolverCustomizer
- PageableHandlerMethodArgumentResolver 를 마음대로 커스터마이징 할 수 있게 제공하는 Functional Interface 이다. 해당 설정을 통해 @PageableDefault 의 정보를 커스터마이징 할 수 있다.
@PageableDefault 원리
PageableHandlerMethodArgumentResolver 에서는 WebRequest 로부터 Page 파라미터와 Size 파라미터를 통해 page 와 pageSize 를 가져오고 SortHandlerMethodArgumentResolver 를 통해 정렬조건을 가져온 후, Pageable 인스턴스를 만들어서 리턴하게 된다.
하지만 WebRequest 로부터 Page 파라미터와 Size 파라미터를 통해 page 와 pageSize 를 가져오는 작업은
PageableHandlerMethodArgumentResolverSupport
가 수행한다. 기본적으로 Page 파라미터와 Size 파라미터 값이 page, size 로 정해져있고, HandlerMethod 에서 다중 Pageable 를 사용할 때 이를 구분하기 위한 Qualifier 구분자도 _ 로 설정되어 있다.
하지만 이러한 디폴트 값도 구현되어있는 setter 를 오버라이딩하면 커스터마이징 할 수 있다.
Multiple Pageable
HandlerMethod 에서 다중 Pageable
를 사용하기 위해서는 @Qualifier
를 통해 각각의 Pageable 인스턴스를 구별할 수 있다.
Pageable 들의 구분자.
HandlerMethod 에서 2개 이상의 Pageable 인스턴스를 주입받는 경우에는 ${qualifier}_가 구분자가 된다.
@GetMapping("/comments")
public ResponseEntity<RestResponse<List<CommentsResponse>>> findComments(
@Qualifier("parent") Pageable parentPageable,
@Qualifier("child") Pageable childPageable,
@RequestParam String crewName,
@Authenticate AuthenticatedMember ignored
) {...}
하지만 이렇게되면 웹 요청을 날릴 때, 아래 curl 문과 같이 파라미터명을 parent_size, parent_page
그리고 child_size, child_page
로 구분해서 날려주어야 한다.
$curl -G "localhost:8083/api/v1/crew/comments" --data-urlencode "crewName=크루 1" --data "parent_page=1&parent_size=2&child_page=2&child_size=3" -H 'Authorization: Bearer TOKEN'
이럴 때는 PageableHandlerMethodArgumentResolverCustomizer 를 구현하여 QualifierDelimiter, PageParameterName, SizeParameterName 이름을 바꿔준 다음 Bean 으로 등록하게 되면, 디폴트 Qualifier 구분자와 Page 와 Size 디폴트 파라미터 이름을 변경할 수 있다.
@Configuration
public class JpaConfig {
@Bean
public PageableHandlerMethodArgumentResolverCustomizer customPageableResolver() {
return pageableResolver -> {
pageableResolver.setQualifierDelimiter("");
pageableResolver.setPageParameterName("Page");
pageableResolver.setSizeParameterName("Size");
};
}
}
위와 같이 설정을 바꾸면 아래와 같이 자연스럽게 파라미터를 변경할 수 있다.
$curl -G "localhost:8083/api/v1/crew/comments" --data-urlencode "crewName=크루 1" --data "parentPage=1&parentSize=2&childPage=2&childSize=3" -H 'Authorization: Bearer TOKEN'