프로그래밍/JAVA Spring

[Spring 스프링] HandlerMethodArgumentResolver 알아보기

hectick 2023. 5. 8. 01:45

 

 

ArgumentResolver는 요청으로 들어온 값을 원하는 객체로 만들어서 컨트롤러에 전달해 주고 싶을 때 사용한다.

 

다음은 ArgumentResolver를 구현할 때 사용되는 HandlerMethodArgumentResolver 인터페이스이다.

    public interface HandlerMethodArgumentResolver {

        boolean supportsParameter(MethodParameter parameter);

        @Nullable
        Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
                NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;

    }

 

 

supportsParameter

 

주어진 MethodParameter를 이 resolver에서 지원하는지 여부를 나타낸다.

지원한다면 true를, 아니면 false를 반환한다.

 

일반적으로는 커스텀 어노테이션과 같이 사용된다. 컨트롤러에 있는 메서드의 파라미터 앞에 커스텀 어노테이션을 달아주면,   ArgumentResolver의 supportsParameter 메서드는 MethodParameter로 들어온 값이 커스텀 어노테이션을 달고 있는지 아닌지 여부를 반환해줄 수 있다.

    //커스텀 어노테이션
    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface AuthenticationPrincipal {

    }
    //컨트롤러
    @DeleteMapping("/{cartItemId}")
    public ResponseEntity<Void> deleteCartItems(@AuthenticationPrincipal AuthenticatedMember authenticatedMember,
                                                @PathVariable Long cartItemId) {
        cartItemManagementService.delete(authenticatedMember.getEmail(), cartItemId);
        return ResponseEntity.noContent().build();
    }
    //ArgumentResolver
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(AuthenticationPrincipal.class);
    }

 

 

resolveArgument

 

공식 문서에는 이 메서드를 다음문장으로 설명한다.

Resolves a method parameter into an argument value from a given request.

 

나는 영알못인지라 정확한 해석은 못해도 최대한 해석해서 정리해보자면, resolveArgument 메서드는 메서드 파라미터(method parameter)를 해결하는 역할을 하는데, 주어진 요청(given request)를 인자 값(argument value)으로 바꿔서 해결해주는 것 같다.

 

뭐랄까, 컨트롤러가 주어진 요청을 바로 받을 수 없는 형태로 작성되었을 때, ArgumentResolver가 요청을 자~알 가공해서 인자 값으로 대신 바꿔서 컨트롤러에 넣을 수 있게 도와주는 느낌으로 나는 이해했다. 

 

아무튼, 해결되었을 때는 반환값이 argument value이고, 해결 못했으면 null을 반환한다.

 


 

HandlerInterceptor 포스팅에서 HandlerInterceptor의 preHandle은 HandlerMapping이 handler를 결정하고, HandlerAdapter가 handler를 호출하는 사이에 실행된다고 했다. 그러면 ArgumentResolver는 언제 동작할까? 명확한 레퍼런스를 찾지도 못했고, 아직 스프링이 어떻게 동작하는지에 대한 큰그림도 다 그리지 못했지만, 이번 장바구니 미션을 하면서 Interceptor의 preHandle -> ArgumentResolver -> Controller 순으로 동작하는 것을 확인한 바,  HandlerInterceptor의 preHandle이 동작하는 것과 HandlerAdapter가 handler를 호출하는 것 사이에 동작한다는 것은 알겠다.