프로그래밍 공부/Spring

스프링 HandlerMethodArgumentResolver이란?

Wonuk 2021. 12. 6. 18:20
반응형

ArgumentResolver 

정확히는 HandlerMethodArgumentResolver 인데 줄여서 ArgumentResolver 라고 부릅니다.

 

애노테이션 기반의 컨트롤러는 매우 다양한 파라미터를 사용할 수 있습니다.

HttpServletRequest , Model 은 물론이고, @RequestParam @ModelAttribute 같은 애노테이션

그리고 @RequestBody , HttpEntity 같은 HTTP 메시지를 처리하는 부분까지 매우 큰 유연함을 보여줍니다.

 

이렇게 파라미터를 유연하게 처리할 수 있는 이유가 바로 ArgumentResolver 덕분입니다.

애노테이션 기반 컨트롤러를 처리하는 RequestMappingHandlerAdaptor

바로 이 ArgumentResolver 를 호출해서 컨트롤러(핸들러)가 필요로 하는 다양한 파라미터의 값(객체)을 생성합니다.

그리고 이렇게 파리미터의 값이 모두 준비되면 컨트롤러를 호출하면서 값을 넘겨줍니다.

스프링은 30개가 넘는 ArgumentResolver 를 기본으로 제공합니다.

 

참고 > 가능한 파라미터 목록은 다음 공식 메뉴얼에서 확인할 수 있습니다.

https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-argument

 

RequestMappingHandlerAdapter 동작 방식

 

사진출처 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/


HandlerMethodArgumentResolver

public interface HandlerMethodArgumentResolver {
	boolean supportsParameter(MethodParameter parameter);
    
	@Nullable
	Object resolveArgument(MethodParameter parameter, 
    	@Nullable ModelAndViewContainer mavContainer,
		NativeWebRequest webRequest, @Nullable WebDataBinderFactory 
		binderFactory) throws Exception;
}

 

동작 방식

ArgumentResolversupportsParameter() 를 호출해서 해당 파라미터를 지원하는지 체크하고,

지원하면 resolveArgument() 를 호출해서 실제 객체를 생성합니다.

그리고 이렇게 생성된 객체가 컨트롤러 호출시 넘어가는 것입니다.

 

그리고 원한다면 개발자가 직접 이 인터페이스를 확장해서 원하는 ArgumentResolver 를 만들 수도 있습니다.

실제 확장하는 예제는 아래의 예제에서 보여드리겠습니다.

 

어디에 사용하는가?

HandlerMethodArgumentResolver은 컨트롤러 메서드에서 특정 조건에 맞는 파라미터가 있을 때

원하는 값을 바인딩해주는 인터페이스입니다.

스프링에서는 Controller에서 @RequestBody 어노테이션을 사용해 Request의 Body 값을 받아올 때 혹은
@PathVariable 어노테이션을 사용해 Request 의 Path Parameter 값을 받아올 때

HandlerMethodArgumentResolver 사용해서 값을 받아옵니다.

 

 

실제 적용사례(글 작성자 개인 프로젝트)

HandlerMethodArgumentResolver 를 이용하여 Custom Annotion 을 만든다음

로그인 정보(세션)을 쉽게 가져오도록 구현했습니다.

 

작성자의 프로젝트는 AOP도 함께 활용하였지만 다음 포스팅에 AOP와 함께 설명하고이번 포스팅에는 ArgumentResolver를 중점으로 설명하겠습니다.

 

회원을 관리하는 API 를 만들게 되면 꼭 필요로 하게 되는 것이 

HandlerInterceptorAdapter를 이용하여 HttpServletRequest 에 정보를 저장한 뒤

사용자 정보를 필요로 하는 Controller 에서 꺼내서 사용하는 방식입니다.

 

만약, HttpServletRequest 을 사용하지 않고 static 변수나 공유 가능한 변수 형태로 사용하게 된다면

Thread safe 하지 않기 때문에 Multi-thread 환경에서 다른 사용자의 정보를 노출하게 되는

위험한 상황을 만들 수 있습니다.

 

하지만, 매번 API 에서 HttpServletRequest parameter 로 받아

get, set으로 값을 얻어오는 방식은 많은 코드 중복을 발생시킵니다.

이러한 문제를 해결하기 위한 방법으로 HandlerMethodArgumentResolver가 사용됩니다. 

 

제가 만든 프로젝트에서는 ArgumentResolver와 AOP를 함께 사용하였기 때문에

AOP포스팅때 코드 설명을 함께 하겠습니다.

 

깃허브 링크

https://github.com/Hwangwonuk/cucumber-market/commits?author=Hwangwonuk

 

GitHub - Hwangwonuk/cucumber-market: 개인 프로젝트

개인 프로젝트. Contribute to Hwangwonuk/cucumber-market development by creating an account on GitHub.

github.com

 

 

참고자료

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/

 

 

반응형