[스프링 MVC - 백엔드 웹 개발 기술] 18. 요청 매핑 핸들러 어뎁터 구조 - RequestMappingHandlerAdapter
by ymkim01. 요청 매핑 핸들러 어뎁터 구조
- 이번 시간에는 요청 매핑 핸들러 어뎁터(RequestMappingHandlerAdapter) 구조에 대해서 알아본다
- 이전에 HTTP 메시지 컨버터에 대해 배웠지만 아래 사진에서는 메시지 컨버터 관련한 부분이 보이지 않는다.
- 이러한 HttpMessageConverter 는 아래 사진에서 어떠한 부분에 해당이 되는 것일까?
- 이번 시간의 주요 포인트는 요청 매핑 핸들러 어댑터, 그리고 HTTP 메시지 컨버터가 어디에서 사용이 되는지 확인해보자
- HTTP 메시지 컨버터는 스프링 MVC의 어느곳에서 사용되는 것일까?
- 위 그림만 봤을때는 HTTP 메시지 컨버터가 사용되는 곳은 보이지 않는다
- 비밀은 어노테이션 기반의 컨트롤러인 @RequestMapping을 처리하는 핸들러 어댑터인 요청 매핑 핸들러 어뎁터에 있다
- 다음으로 요청 매핑 핸들러 어뎁터의 동작 방식에 대해서 살펴보자
01-1. 요청 매핑 핸들러 어뎁터(RequestMappingHandlerAdapter) 동작 방식
- 사용자 HTTP 요청 → DispathcerServlet → 핸들러 어댑터(RequestMappingHandlerAdapter)는 위와 같다
- 핸들러 어댑터는 ArgumentResolver에게 요청에 대한 처리 가능 여부를 묻는데 해당 부분은 아래에서 알아보자
01-2. ArgumentResolver(요청시)
// 아래와 같은 API들이 있다고 가정해보자
// 여기서 다양한 매개변수 HttpServletRequest, HttpServletResponse, HttpEntity
// 들은 누가, 어떻게 주입 해주는 것인가?
// ----> 주입 해주는 녀석은 핸들러 어댑터 이지만, 처리는 ArgumentResolver가 담당한다
@GetMapping("/test1")
public ResponseEntity<?> test01(HttpServletRequest request, HtttpServletResponse response) {
return ResponseEntity.ok("ok");
}
@PostMapping("/test2")
public ResponseEntity<?> test02(@RequestBody Member member) {
return ResponseEntity.ok("ok");
}
@PostMapping("/test3")
public ResponseEntity<?> test03(HttpEntity httpEntity) {
return ResponseEntity.ok("ok");
}
@PostMapping("/test4")
public ResponseEntity<?> test03(@ModelAttribute Member member) {
return ResponseEntity.ok("ok");
}
- 위와 같이 컨트롤러(API)들은 다양한 파라미터를 매개변수로 받아서 유연하게 사용이 가능하다
- HttpServletRequest, HttpServletResponse
- Model
- @RequestParam, @RequestBody, @ModelAttribute
- HttpEntity
- 위와 같이 파라미터를 유연하게 처리할 수 있는 이유가 ArgumentResolver 덕분이다
- 어노테이션 기반 컨트롤러를 처리하는 요청 매핑 핸들러는 ArgumentResolver 를 호출하여 컨트롤러(핸들러)가 필요로 하는 다양한 파라미터 값(객체)을 생성해준다. 또한 이렇게 파라미터의 값이 모두 준비되면 컨트롤러를 호출하면서 값을 넘긴다
스프링은 30개가 넘는 ArgumentResolver를 기본적으로 제공한다.
어떤 종류가 있는지 확인만 해보자.
01-3. HandlerMethodArgumentResolver(인터페이스)
// HandlerMethodArgumentResolver는 기본적으로 인터페이스로 구성이 되어있다
// ㄴ 위 사진을 보면 HandlerMethodArgumentResolver 인터페이스를 구현하는 구현 클래스가 다수 존재함
// ㄴ HttpEntityMethodProcessor
// ㄴ ModelMethodProcessor.. 등등이 존재함
package org.springframework.web.method.support;
import org.springframework.core.MethodParameter;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
/**
* Strategy interface for resolving method parameters into argument values in
* the context of a given request.
*
* @author Arjen Poutsma
* @since 3.1
* @see HandlerMethodReturnValueHandler
*/
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
}
HandlerMethodArgumentResolver의 동작방식은 아래와 같다
- supportsParameter(MethodParameter parameter)
- 해당 파라미터 처리가 가능한지 지원 여부 체크
- resolveArgument(…중략)
- 파라미터 처리가 가능한 경우, 위 함수가 호출 되고 실제 객체 생성 후 컨트롤러에게 객체 전달
- HttpservletRequest, DTO 등등
- HandlerMethodArgumentResolver는 인터페이스이기에 사용자가 직접 구현도 가능
01-4. ReturnValueHandler(응답시)
- HandlerMethodReturnValueHandler를 줄여서 ReturnValueHandler 라 부른다
- ArgumentResolver 와 비슷한데 ReturnValueHandler은 ‘응답 값’을 변환하고 처리한다
- ex) 컨트롤러에서 String으로 뷰 이름으로 반환해도, 동작하는 이유가 ReturnValueHandler 덕분이다
- ModelAndView
- @ResponseBody
- HttpEntity
- String
02. HTTP 메시지 컨버터
02-1. HTTP 메시지 컨버터 위치
- HTTP 메시지 컨버터는 ArgumentResolver, ReturnValueHandler 2곳에서 모두 사용된다
- 요청 파라미터 검증 후 객체를 생성하는 경우와 객체를 응답하는 경우 둘다 사용
- 요청의 경우(Request)
- @RequestBody를 처리하는 ArgumentResolver가 존재
- HttpEntity를 처리하는 ArgumentResolver가 존재
- 해당 ArgumentResolver 들이 HTTP 메시지 컨버터를 사용하여 필요한 객체를 생성하는 것
- 응답의 경우(Response)
- @ResponseBody를 처리하는 ReturnValueHandler가 존재
- HttpEntity를 처리하는 ReturnValueHandler가 존재
- 그리고 여기에서 HTTP 메시지 컨버터를 호출해서 응답 결과를 만든다
- 스프링 MVC에서 @RequestBody, @ResponseBody 어노테이션이 존재하면
- RequestResponseBodyMethodProcessor(ArgumentResolver)
- 스프링 MVC에서 HttpEntity 존재하면
- HttpEntityMethodProcessor(ArgumentResolver)
02-2. 확장
스프링에서는 다음을 모두 인터페이스로 제공, 하여 필요하면 언제든 기능 확장이 가능하다
- HandlerMethodArgumentResolver
- HandlerMethodReturnValueHandler
- HttpMessageConverter
02-3. 스프링은 대부분의 기능을 제공하기에 확장할 일이 많지 않음
- 기능 확장은 WebMvcConfigure를 상속받아서 스프링 빈으로 등록하면 된다
- 실제 자주 사용하지는 않으니 실제 기능 확장이 필요한 경우 사용한다
@Bean
public WebMvcConfigurer webMvcConfigurer() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
WebMvcConfigurer.super.addInterceptors(registry);
}
}
'Spring MVC > 스프링 MVC - 백엔드 웹 개발 기술' 카테고리의 다른 글
블로그의 정보
기록하고, 복기하고
ymkim