๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
TIL

PageableArgumentResolver๋ฅผ ํ™œ์šฉํ•œ @Pageable ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ์ œํ•œ

by bamDal 2025. 2. 24.

 

ํ”„๋กœ์ ํŠธ์˜ ์š”๊ตฌ์‚ฌํ•ญ ์ค‘์— ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ๋ฅผ 10, 30, 50์œผ๋กœ ์ œํ•œํ•˜๊ณ  ์ง€์ •ํ•œ ์‚ฌ์ด์ฆˆ ์™ธ์— ๋‹ค๋ฅธ ์‚ฌ์ด์ฆˆ๊ฐ€ ์ž…๋ ฅ๋  ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์ธ 10์œผ๋กœ ํŽ˜์ด์ง•ํ•˜๋Š” ํ•ญ๋ชฉ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ฒ˜์Œ์—๋Š” ๊ฐ ๋„๋ฉ”์ธ์—์„œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ์ œํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ์ ์šฉ์„ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋˜ ์ค‘ ArgumentResolver์— ๋Œ€ํ•ด ์•Œ๊ฒŒ๋˜์—ˆ๊ณ ,
๊ทธ ์ค‘์—์„œ๋„ PageableArgumentResolver๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ์ œํ•œ์„ ์ ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

Handler Method Argument Resolver ๋ž€?

Spring MVC์—์„œ ์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์ „์— ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ๋กœ๋Š” @RequestParam, @ModelAttribute, @RequestBody ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

Handler Method Argument Resolver ๋™์ž‘ ๊ณผ์ •

  1. DispatcherServlet → HandlerAdapter
  2. HandlerAdapter
    •  Request Mapping Handler Adapter (Handler Adapter์˜ ๊ตฌํ˜„์ฒด) ๊ฐ€ Controller ์‹คํ–‰ ์ „์—
      Handler Method Argument Resolver ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ณ€ํ™˜
  3. Handler Method Argument Resolver ๋Š” ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜์—ฌ Handler Adapter ๋กœ ๋ฐ˜ํ™˜
  4. Handler Adapter ๋Š” ์ด ๊ฐ’๋“ค์„ ๊ฐ€์ง€๊ณ  Controller ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

 

 

PageableHandlerMethodArgumentResolver ๋ž€?

Pageable์— ๋Œ€ํ•œ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ฉด @Pageable ์–ด๋…ธํ…Œ์ด์…˜ ์‚ฌ์šฉ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ์ œํ•œ ์กฐ๊ฑด์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PageableArgumentResolver๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ ์ œํ•œ์„ ํ•˜๋ฉด์„œ ์–ป์€ 2๊ฐ€์ง€ ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

— HandlerMethodArgumentResolver๋ฅผ implements

  • ๋ชจ๋“  ๋กœ์ง์„ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•จ
  • ํŒŒ๋ผ๋ฏธํ„ฐ ํŒŒ์‹ฑ, ๋ณ€ํ™˜, ๊ฒ€์ฆ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ž‘์„ฑ
  • ์ •๋ ฌ(Sort) ์ฒ˜๋ฆฌ๋„ ์ง์ ‘ ๊ตฌํ˜„ ํ•„์š”
  • ๋” ์œ ์—ฐํ•˜๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ๊ฐ€๋Šฅ

— PageableHandlerMethodArgumentResolver๋ฅผ extends

  • Spring Data์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ๊ตฌํ˜„์ฒด ํ™œ์šฉ
  • ํŽ˜์ด์ง•, ์ •๋ ฌ ๊ด€๋ จ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ ๋ชจ๋‘ ์ œ๊ณต
  • ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ด์„œ ์ˆ˜์ •
  • ๋” ๊ฐ„๋‹จํ•˜๊ณ  ์•ˆ์ „ํ•œ ๊ตฌํ˜„

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ๋Š” ์ด๋ฏธ Pageable ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”๋“œ ์ž‘์„ฑ์ด ์ƒ๋‹น ๋ถ€๋ถ„ ์ง„ํ–‰์ค‘์ด์—ˆ์œผ๋ฉฐ,

์š”๊ตฌ๋˜๋Š” ์ œํ•œ ์‚ฌํ•ญ๋„ ๊ฐ„๋‹จํ•œ ์กฐ๊ฑด์ด์—ˆ๊ธฐ์— ์œ ์—ฐํ•œ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•๋ณด๋‹ค๋Š” ๊ฐ„๋‹จํ•˜๊ณ  ์•ˆ์ „ํ•œ ๊ตฌํ˜„์— ์ดˆ์ ์„ ๋งž์ถ”์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ฝ”๋“œ ์ž‘์„ฑ

— As is

private int validatePageSize(int pageSize) {
    if (Set.of(10, 30, 50).contains(pageSize))
        return pageSize;
    throw new CustomApiException(BaseException.INVALID_PAGESIZE);
}

— To be

public class CustomPageableArgumentResolver extends PageableHandlerMethodArgumentResolver {

    private static final Set<Integer> ALLOWED_PAGE_SIZES = Set.of(10, 30, 50); // ์‚ฌ์ด์ฆˆ ์ œํ•œ
    private static final int DEFAULT_PAGE_SIZE = 10; // ๊ธฐ๋ณธ๊ฐ’

    @Override
    public Pageable resolveArgument(MethodParameter methodParameter,
        ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest,
        WebDataBinderFactory binderFactory) {

        Pageable pageable = super.resolveArgument(methodParameter, mavContainer, webRequest, binderFactory);

        int pageSize = pageable.getPageSize();

        // ์š”์ฒญ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ๊ฐ€ ํ—ˆ์šฉ๋œ ๊ฐ’์ด ์•„๋‹ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์„ค์ •
        if (!ALLOWED_PAGE_SIZES.contains(pageSize)) {
            return PageRequest.of(pageable.getPageNumber(), DEFAULT_PAGE_SIZE, pageable.getSort());
        }

        return pageable;
    }
}
package com.ioteam.order_management_platform.global.config;

import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

	@Override
	public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
		argumentResolvers.add(new CustomPageableArgumentResolver());
	}
}

 

์ ์šฉ ๊ฒฐ๊ณผ

— As is

  • ์ •ํ•ด๋‘” ํŽ˜์ด์ง€ ์™ธ์— ๋‹ค๋ฅธ ํŽ˜์ด์ง€๊ฐ€ ๋“ค์–ด์˜ค๋ฉด exception์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

— To be

์˜ˆ์™ธ์ฒ˜๋ฆฌ ์ฝ”๋“œ์—†์ด๋„ ์ •ํ•ด๋‘์ง€ ์•Š์€ ๊ฐ’์€ ๊ธฐ๋ณธ๊ฐ’์ธ 5๋กœ ๋ณ€ํ™˜๋˜์–ด ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

(ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ๊ธฐ๋ณธ๊ฐ’์„ ์ž‘๊ฒŒ ์„ค์ •ํ•œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.)

 

 

์ฃผ์˜ํ•  ์ 

์ฝ”๋“œ ์ž‘์„ฑ ์ค‘์— PageableHandlerMethodArgumentResolver์™€ PageableArgumentResolver๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

PageableArgumentResolver ์˜ ๊ฒฝ์šฐ Spring 3.x ์ฏค ์‚ฌ์šฉ๋˜๋˜ ๋ ˆ๊ฑฐ์‹œ ํด๋ž˜์Šค๋กœ ํ˜„์žฌ Deprecated ๋œ ์ƒํƒœ์ด๋ฏ€๋กœ ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š๊ฒŒ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.