Java/Spring
HandlerMethodArgumentResolver 란?
Z_Z
2026. 1. 7. 16:44
728x90
반응형
HandlerMethodArgumentResolver 란?
컨트롤러 메서드의 파라미터를 직접 해석해서 객체로 만들어주는 확장 포인트 인터페이스다
쉽게 말해, Spring MVC 에서 컨트롤러 메서드의 매개변수를 HTTP 요청에서 실제 인자 값으로
변환하는 인터페이스이다.
DispatcherServlet 이 HandlerMapping 에서 적절한 Mapping URL 을 찾아내고 HanlderAdapter 를 통해
적절한 컨트롤러 메서드를 호출한다.
여기서 컨트롤러 메서드를 호출하기 전 @RequestParam, @PathVariable, @RequestBody 등의 데이터들을
가공하거나 커스터마이징할 때 사용한다.
1️⃣ 왜 필요한가? (사용 이유)
@GetMapping("/users")
public String users(
@RequestParam String id,
@RequestHeader("Authorization") String token,
HttpServletRequest request
)
❌ 문제점
- 컨트롤러마다 같은 파라미터 파싱 코드 반복
- 인증 정보, 사용자 정보, 헤더 값 처리 로직이 컨트롤러에 섞임
- 테스트 어려움 / 관심사 분리 안됨
👉 그래서
컨트롤러 파라미터 하나로 의미 있는 객체를 자동 주입하고 싶을 때 HandlerMethodArgumentResolver를 사용한다.
2️⃣ HandlerMethodArgumentResolver 인터페이스
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
Object resolveArgument(
MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory
) throws Exception;
}
핵심 메서드 2개
| 메서드 | 역할 |
| supportsParameter() | 이 파라미터를 내가 처리할 수 있는지 판단 |
| resolveArgument() | 실제로 파라미터 객체를 만들어 반환 |
3️⃣ 동작 흐름 (중요 ⭐)
HTTP 요청
↓
DispatcherServlet
↓
HandlerMapping
↓
HandlerAdapter
↓
컨트롤러 메서드 호출 전
↓
HandlerMethodArgumentResolver 목록 순회
└ supportsParameter() == true ?
└ resolveArgument() 실행
↓
컨트롤러 메서드 실행
👉 컨트롤러는 파라미터 생성 과정을 전혀 모른다.
4️⃣ 실제 예제 (가장 이해 잘 되는 예)
🎯 목표
@GetMapping("/me")
public String me(@LoginUser User user) {
return user.getName();
}
4-1️⃣ 커스텀 어노테이션
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {
}
4-2️⃣ Resolver 구현
@Component
public class CustomResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
System.out.println("parameter === "+parameter.getParameterName());
System.out.println("parameter === "+parameter.getParameterType());
System.out.println("parameter === "+parameter.getParameterType().equals(int.class));
return parameter.hasMethodAnnotation(LoginUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request =
(HttpServletRequest) webRequest.getNativeRequest();
// 예: 세션에서 사용자 조회
HttpSession session = request.getSession(false);
return session != null ? session.getAttribute("LOGIN_USER") : null;
}
}
4-3️⃣ Spring MVC에 등록
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
CustomResolver customResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(customResolver);
}
}
4-4️⃣ 컨트롤러 사용
@GetMapping("/me")
public String me(@LoginUser User user) {
return user.getName();
}
컨트롤러 메서드에 오기전에 파라미터에 대한 공통 작업들을 처리해놓으면 깔끔해진다.
5️⃣ 언제 쓰면 좋은가?
✅ 쓰면 좋은 경우
- 로그인 사용자 주입(@LoginUser)
- JWT → User 객체 변환
- 공통 헤더 파싱( @ClientIp, @ApiVersion )
- Request → 도메인 객체 변환 로직이 반복될 때
❌ 굳이 안 써도 되는 경우
- 단순 @RequestParam, @PathVariable
- 컨트롤러마다 다른 파싱 로직
- 일회성 처리
6️⃣ Spring Security 와의 관계 (중요)
public String test(@AuthenticationPrincipal UserDetails user)
➡ 내부적으로 HandlerMethodArgumentResolver 구현체가 있음
728x90
반응형