Spring/Spring 문법

ArgumentResolver - HandlerMethodArgumentResolver 란 무엇일까?

열심히 해 2024. 12. 14. 20:15

HandlerMethodArgumentResolver :

Strategy interface for resolving method parameters into argument values in the context of a given request.

 

 

메소드 매개변수를 확인하고, 이를 HTTP 요청을 바탕으로 인수 값 (argument value) 으로 변환하는 역할을 합니다. 즉 어떻게 '메서드 파라미터'를 적합한 '인수 값'으로 변환할지"를 결정하는 인터페이스입니다. 우리는 구현체를 만들어 사용하면 되겠습니다.

 

 

메서드 매개변수와 인수값이 무엇을 의미하는 걸까요 ?

@GetMapping("/profile")
public ResponseEntity<ProfileResponse> getProfile(VerifiedMember verifiedMember) {
    // ...
}

 

메소드 매개변수란 VerifiedMember verifiedMember 입니다.

 

인수값에 대해 설명하겠습니다. 위 메서드가 실행될 때 ArgumentResolver에 의해 verifiedMember에 들어갈 객체가 생성됩니다. 이때 그 객체를 인수값이라 부릅니다.

 

 


 

 

HandlerMethodArgumentResolver는 2개의 메서드로 구성되어 있습니다.

 

 

1. 

boolean supportsParameter(MethodParameter parameter);

 

메서드의 파라미터가 resolver 의 지원을 받는지, 그 여부에 관한 것입니다.

 

parameter 를 확인하여 지원을 받는다면 true, 아니라면 false를 반환합니다.

 

실제 사용

@Override
public boolean supportsParameter(MethodParameter parameter) {
    return parameter.getParameterType().equals(VerifiedMember.class);
}

 

 

2. 

 

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

 

 

컨트롤러 메서드의 특정 파라미터에 인수 값을 생성 및 할당합니다. 이때 인수 값은 HTTP 요청으로부터 만들어집니다.

 

따라서 parameter 와 webReauest 는 반드시 필요합니다(@Nullable 이 아닌 것입니다) !!

 

 

실제 사용

 

@Override
public Object resolveArgument(
    MethodParameter parameter,
    ModelAndViewContainer mavContainer,
    NativeWebRequest webRequest,
    WebDataBinderFactory binderFactory
) {
    HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest();
    String headerToken = request.getHeader(AUTHORIZATION_HEADER);
    String token = jwtUtil.substringToken(headerToken);
    Claims memberClaims = jwtUtil.getMemberClaims(token);
    Long memberId = Long.parseLong(memberClaims.getSubject());
    String email = (String)memberClaims.get("email");
    return VerifiedMember.builder()
        .id(memberId)
        .email(email)
        .build();
}

 

 

 


 

 

제대로 동작하기 위해서 명시적으로 ArgumentResolver 를 스프링(의 여러 Resolver 중)에 추가해야 하며, 그러기 위해선 빈으로 등록해야 합니다.

 

@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

    private final MemberArgumentResolver memberArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
       resolvers.add(memberArgumentResolver);
    }
}

 

 

구현체:

 

@Component
@RequiredArgsConstructor
public class MemberArgumentResolver implements HandlerMethodArgumentResolver {

    private static final String AUTHORIZATION_HEADER = "Authorization";
    private final JwtUtil jwtUtil;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
       return parameter.getParameterType().equals(VerifiedMember.class);
    }

    @Override
    public Object resolveArgument(
       MethodParameter parameter,
       ModelAndViewContainer mavContainer,
       NativeWebRequest webRequest,
       WebDataBinderFactory binderFactory
    ) {
       HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest();
       String headerToken = request.getHeader(AUTHORIZATION_HEADER);
       String token = jwtUtil.substringToken(headerToken);
       Claims memberClaims = jwtUtil.getMemberClaims(token);
       Long memberId = Long.parseLong(memberClaims.getSubject());
       String email = (String)memberClaims.get("email");
       return VerifiedMember.builder()
          .id(memberId)
          .email(email)
          .build();
    }
}

 

 

 

공식 문서

 

https://docs.spring.io/spring-framework/docs/6.2.x/javadoc-api/org/springframework/web/method/support/HandlerMethodArgumentResolver.html