HTTP 메시지 컨버터와 Spring MVC 동작 방식
HTTP 메시지 컨버터는 스프링 MVC 어디쯤에서 사용 될까요?
HTTP 메시지 컨버터는 Spring MVC에서 중요한 역할을 하지만, Spring MVC 구조 내에서 직접 눈에 띄지 않습니다.
Spring MVC 구조부터 보겠습니다.
HTTP 메시지 컨버터는 위 그림에서 보이지 않는데 어디에 위치해야 할까요?
결론부터 말하면 본 글의 제목인 RequestMappingHandlerAdapter의 동작방식을 알아야합니다.
HTTP 메시지 컨버터가 동작하는 위치는 바로 RequestMappingHandlerAdapter라는 요청 매핑 핸들러 어댑터입니다.
RequestMappingHandlerAdapter의 역할
RequestMappingHandlerAdapter은 어노테이션 기반의 컨트롤러, 그러니까
@RequestMapping을 처리하는 핸들러 어댑터입니다.
RequestMappingHandlerAdapter의 동작 방식을 보겠습니다.
이 어댑터는 다음과 같은 과정으로 작동합니다:
- Dispatcher Servlet에서 요청을 전달받아 RequestMappingHandlerAdapter가 이를 처리.
- ArgumentResolver를 호출하여 컨트롤러 메서드의 파라미터를 준비.
- 파라미터 준비 후, 컨트롤러(핸들러) 호출.
- ReturnValueHandler를 통해 응답 값을 처리
위와 같이 Dispatcher Servlet에서 넘어온 요청을 RequestMappingHandlerAdapter가 받습니다.
그러면 RequestMappingHandlerAdapter는 ArgumentResolver를 호출합니다.
ArgumentResolver가 컨트롤러의 파라미터, 어노테이션 정보를 기반으로 전달 데이터를 생성하고
핸들러(컨트롤러)가 호출되는 것입니다.
여기서 중요한 개념이 나오는데 ArgumentResolver 입니다.
(정확히는 HandlerMethodArgumentResolver 인데 줄여서 ArgumentResolver 라고 부릅니다.)
ArgumentResolver
생각해보면, 어노테이션 기반의 컨트롤러는 매우 다양한 파라미터를 사용할 수 있습니다.
HttpServletRequest , Model은 물론이고, @RequestParam , @ModelAttribute 같은 어노테이션
그리고 @RequestBody , HttpEntity 같은 HTTP 메시지를 처리하는 부분까지 매우 큰 유연함을 보여줍니다.
ArgumentResolver는 컨트롤러 메서드의 다양한 파라미터를 유연하게 처리할 수 있도록 도와줍니다.
@RequestParam, @ModelAttribute, @RequestBody, HttpEntity 등의 파라미터를 적절히 처리하는 역할을 하며, Spring MVC의 핵심적인 유연성을 제공하는 요소입니다.
어노테이션 기반 컨트롤러를 처리하는 RequestMappingHandlerAdapter는 바로 이 ArgumentResolver를 호출해서
컨트롤러(핸들러)가 필요로 하는 다양한 파라미터의 값(객체)을 생성합니다.
그리고 이렇게 파리미터의 값이 모두 준비되면 컨트롤러를 호출하면서 값을 넘겨줍니다.
스프링은 30개 이상의 기본 ArgumentResolver를 제공하며, 이 인터페이스를 확장해 필요한 ArgumentResolver를 직접 구현할 수도 있습니다.
어떤 종류가 있는지는 아래 페이지를 참고하세요.
Method Arguments :: Spring Framework
Method Arguments :: Spring Framework
JDK 8’s java.util.Optional is supported as a method argument in combination with annotations that have a required attribute (for example, @RequestParam, @RequestHeader, and others) and is equivalent to required=false.
docs.spring.io
HandlerMethodArgumentResolver(ArgumentResolver) 인터페이스를 한번 보겠습니다.
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
}
- supportsParameter(): 해당 파라미터를 처리할 수 있는지 확인.
- resolveArgument(): 실제로 파라미터를 처리하고, 컨트롤러에 전달할 객체를 생성.
ArgumentResolver는 supportsParameter()를 호출해서 해당 파라미터를 지원하는지 체크하고,
지원하면 resolveArgument() 를 호출해서 실제 객체를 생성합니다.
그리고 이렇게 생성된 객체가 컨트롤러 호출 시 넘어가는 것입니다.
그리고 원한다면 직접 이 인터페이스를 확장해서 원하는 ArgumentResolver 를 만들 수도 있습니다.
실제 확장 하는 예제는 다음 글에서 다루겠습니다
(https://fox-dev-diary.tistory.com/entry/ArgumentResolver-%ED%99%9C%EC%9A%A9)
ReturnValueHandler
다시 위의 RequestMappingHandlerAdapter 동작 방식 그림을 보면 ArgumentResolver와 비슷하게
ReturnValueHandler라는 것도 있습니다.
컨트롤러의 응답 값을 처리하는 것은 ReturnValueHandler입니다.
예를 들어, 컨트롤러에서 String을 반환하면
해당 값을 뷰 이름으로 변환하는 것이 바로 이 ReturnValueHandler 덕분입니다.
어떤 종류가 있는지는 아래 페이지를 참고하세요.
Return Values :: Spring Framework
Return Values :: Spring Framework
A single value type, e.g. Mono, is comparable to returning DeferredResult. A multi-value type, e.g. Flux, may be treated as a stream depending on the requested media type, e.g. "text/event-stream", "application/json+stream", or otherwise is collected to a
docs.spring.io
HTTP 메시지 컨버터의 위치
그렇다면 이제 본 글의 시작이었던 HTTP 메시지 컨버터는 어디서 동작할까요?
잘 생각해보면 당연히
컨트롤러의 파라미터, 어노테이션 정보를 기반으로 전달 데이터를 생성하는
HandlerMethodArgumentResolver(ArgumentResolver)와
컨트롤러의 응답 값을 변환하고 처리하는
HandlerMethodReturnValueHandler(ReturnValueHandler)에서 동작을 합니다.
HTTP 메시지 컨버터는 컨트롤러의 요청과 응답 데이터를 변환하는 과정에서 사용됩니다.
- 요청 처리 시: @RequestBody와 HttpEntity 등을 처리하는 ArgumentResolver가 HTTP 메시지 컨버터를 통해 데이터를 변환하여 컨트롤러에 전달.
- 응답 처리 시: @ResponseBody와 HttpEntity 등을 처리하는 ReturnValueHandler가 HTTP 메시지 컨버터를 호출하여 응답 데이터를 생성.
아래 그림을 보면 이해가 됩니다.
HTTP 메시지 컨버터를 사용하는 @RequestBody도 컨트롤러가 필요로 하는 파라미터의 값에 사용됩니다.
@ResponseBody의 경우도 컨트롤러의 반환 값을 이용합니다.
- 요청의 경우 @RequestBody 를 처리하는 ArgumentResolver 가 있고, HttpEntity 를 처리하는 ArgumentResolver 가 있습니다. 이런 ArgumentResolver들이 HTTP 메시지 컨버터를 사용해서 필요한 객체를 생성하는 것입니다.
- 응답의 경우 @ResponseBody 와 HttpEntity 를 처리하는 ReturnValueHandler가 있습니다. 그리고 여기에서 HTTP 메시지 컨버터를 호출해서 응답 결과를 만듭니다.
- 스프링 MVC는 @RequestBody @ResponseBody 가 있으면 RequestResponseBodyMethodProcessor()를, HttpEntity가 있으면 HttpEntityMethodProcessor() 를 사용합니다.
이처럼 HTTP 메시지 컨버터는 RequestBody, ResponseBody, HttpEntity와 같은 어노테이션과 함께 사용되며, 컨트롤러가 주고받는 데이터의 변환을 담당합니다.
출처: 인프런, 김영한-스프링 MVC 1편
'Spring(boot)' 카테고리의 다른 글
오류 페이지(BasicErrorController) (0) | 2024.09.12 |
---|---|
ArgumentResolver 활용 (0) | 2024.09.10 |
스프링 인터셉터(Interceptor) (0) | 2024.09.09 |
서블릿 필터 (Filter) (0) | 2024.09.09 |
PatternMatchUtils(간단한 패턴 매치) (0) | 2024.09.09 |