[Spring] ArgumentResolver

이연우·2025년 8월 18일

TIL

목록 보기
75/100

⚙️ RequestMappingHandlerAdapter란?

  • @RequestMapping 계열(@GetMapping, @PostMapping 등) 컨트롤러 메서드를 실행하는 핵심 어댑터
  • 내부적으로 두 컴포지트를 보유:
    • HandlerMethodArgumentResolverComposite (파라미터 바인딩)
    • HandlerMethodReturnValueHandlerComposite (반환값 처리)
  • “어떤 파라미터를 어떻게 만들지?”, “이 반환값을 어떻게 응답으로 보낼지?”를 각각 위임

🧩 Spring MVC 구조

→ 요청 데이터가 변환됨 (HttpMessageConverter)
Controller에 전달되는 HandlerAdapterHandler 사이에서 어떤 일이 발생함

🧩 RequestMappingHandlerAdapter

@RequestMapping을 처리하는 HandlerAdapter의 구현체
@PostMapping, @GetMapping, @PutMapping, @PatchMapping, @DeleteMapping 등은 모두 @RequestMapping의 일종


🧲 ArgumentResolver란?

  • 컨트롤러 메서드 각 파라미터를 적절한 객체로 변환 후 주입
  • 예) @RequestParam, @PathVariable, @RequestBody, HttpServletRequest, Model

✍️ 핵심 메서드

boolean supportsParameter(MethodParameter parameter); // 내가 이 파라미터 처리가 가능한지?
Object resolveArgument(MethodParameter parameter, ...); // 실제 값 만들어서 반환

🧰 자주 쓰는 내장 Resolver 예시

  • RequestParamMethodArgumentResolver@RequestParam
  • PathVariableMethodArgumentResolver@PathVariable
  • RequestHeaderMethodArgumentResolver@RequestHeader
  • RequestResponseBodyMethodProcessor@RequestBody (내부에서 HttpMessageConverter 사용)
  • ModelAttributeMethodProcessor@ModelAttribute
  • (옵션) Spring Security: AuthenticationPrincipalArgumentResolver@AuthenticationPrincipal
  • (옵션) Spring Data Web: PageableHandlerMethodArgumentResolverPageable

📍 동작 포인트

  • 파라미터 개수만큼 순회하며, 각 파라미터에 대해
  • supportsParameter == true첫 ResolverresolveArgument() 수행

🎁 ReturnValueHandler란?

  • 컨트롤러 반환값HTTP 응답에 맞게 변환/가공
  • 예) ModelAndView, 뷰 이름 문자열, @ResponseBody, HttpEntity<>, 스트리밍 등

✍️ 핵심 메서드

boolean supportsReturnType(MethodParameter returnType); // 처리가 가능한지?
void handleReturnValue(Object returnValue, ...);        // 실제 응답으로 변환

🧰 내장 핸들러 예시

  • ModelAndViewMethodReturnValueHandlerModelAndView
  • ViewNameMethodReturnValueHandlerString(뷰 이름)
  • HttpEntityMethodProcessorHttpEntity / ResponseEntity
  • RequestResponseBodyMethodProcessor@ResponseBody(여기도 HttpMessageConverter 사용)
  • ResponseBodyEmitter*, StreamingResponseBody*, Callable*, DeferredResult* 등 비동기/스트리밍

📍 동작 포인트

  • 반환 타입에 맞는 첫 Handler가 잡아서 응답 본문/뷰로 변환

🐞 자주 만나는 예외 & 디버깅

예외/상태시점원인해결
MissingServletRequestParameterException (400)@RequestParam필수 파라미터 누락required=false/기본값/검증
MethodArgumentTypeMismatchException (400)변환 단계타입 변환 실패타입 확인, 포맷터/컨버터
MethodArgumentNotValidException (400)@Valid바인딩/검증 실패에러 응답 표준화
HttpMessageNotReadableException (400)@RequestBody바디 JSON 문법/매핑 실패JSON/DTO 점검
HttpMediaTypeNotSupportedException (415)읽기Content-Type 불일치올바른 헤더/consumes
HttpMediaTypeNotAcceptableException (406)쓰기Accept 불일치올바른 헤더/produces

🧠 요약 정리

항목RequestMappingHandlerAdapterArgumentResolverReturnValueHandler
기능컨트롤러 메서드 실행 엔진메서드 파라미터객체로 주입반환값응답 형식으로 변환
동작 시점핸들러 결정 후 전체 실행 단계컨트롤러 호출 직전(파라미터별)컨트롤러 호출 직후
선택 기준해당 없음(고정)supportsParameter(MethodParameter)supportsReturnType(MethodParameter)
핵심 메서드(컴포지트 보유)resolveArgument(...)handleReturnValue(...)
예시@RequestParam, @PathVariable, @RequestBody, HttpServletRequestModelAndView, String(view), @ResponseBody, HttpEntity
컨버터 연계간접@RequestBody → 내부에서 HttpMessageConverter.read@ResponseBody/HttpEntityHttpMessageConverter.write
확장커스텀 Resolver + addArgumentResolvers커스텀 Handler + extendHandlerExceptionResolvers 등(일반적으론 ResponseBodyAdvice 권장)
주의적용 범위 과도 확장 주의(명확한 애노테이션/타입 매칭)전역 래핑은 ResponseBodyAdvice가 더 간결

0개의 댓글