Deep Dive /Java Web /12

12. DispatcherServlet → HandlerMethodArgumentResolver: resolveArgument()

preHandle()을 통과하면, Spring은 컨트롤러를 바로 호출하지 않고 먼저 파라미터를 준비합니다. 이 단계의 핵심은 HandlerMethodArgumentResolver가 요청 데이터를 컨트롤러 메서드 인자로 바꾸는 것입니다.


이번 단계의 역할

컨트롤러 진입 전에 요청 본문, 쿼리 파라미터, 경로 변수 등을 실제 메서드 인자로 만드는 단계입니다.


호출 흐름 요약

  1. HandlerAdapter가 컨트롤러 실행을 준비합니다.
  2. InvocableHandlerMethod가 각 파라미터를 순회합니다.
  3. 적절한 HandlerMethodArgumentResolver를 찾습니다.
  4. resolveArgument(...)로 DTO/기본 타입을 생성합니다.
  5. 필요하면 검증과 예외 처리 단계로 이어집니다.

호출 흐름 다이어그램

sequenceDiagram participant DS as DispatcherServlet participant HA as HandlerAdapter participant IHM as InvocableHandlerMethod participant Resolver as HandlerMethodArgumentResolver participant RR as RequestResponseBodyMethodProcessor DS->>HA: handle(...) HA->>IHM: invokeAndHandle(...) IHM->>Resolver: supportsParameter(param)? Resolver-->>IHM: true IHM->>RR: resolveArgument(...) RR-->>IHM: argument

핵심 코드

// RequestResponseBodyMethodProcessor.java
public @Nullable Object resolveArgument(MethodParameter parameter,
        @Nullable ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest,
        @Nullable WebDataBinderFactory binderFactory) throws Exception {

    Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
    ...
    return adaptArgumentIfNecessary(arg, parameter);
}

코드 해설

12번은 전체 오케스트레이션 단계이고, 실제 내부는 다시 세부 단계로 나뉩니다. 이 저장소에서는 이를 12-1 역직렬화, 12-2 검증, 12-3 예외 처리로 분리해 다룹니다.


설계 의도

1) 컨트롤러가 바인딩과 검증 책임을 직접 지지 않게 하기 위해

입력 생성과 검증을 Resolver 계층에 두면 컨트롤러는 비즈니스 로직에 집중할 수 있습니다.

2) 입력 품질을 컨트롤러 진입 전에 보장하기 위해

파싱 실패, 타입 불일치, 검증 오류를 먼저 걸러내면 컨트롤러는 더 신뢰할 수 있는 인자만 받습니다.


다음 단계 연결

세부 흐름은 12-1 JSON → DTO 생성, 12-2 검증, 12-3 검증 실패 예외 처리로 이어집니다.

← 이전: 11. DispatcherServlet → HandlerInterceptor | 다음: 12-1. AbstractJackson2HttpMessageConverter → ObjectMapper