질문, 피드백 등 모든 댓글 환영합니다.
이전 블로그에서 HTTP 요청을 처리하는 방법을 정리하며 스프링 MVC가 어떻게 데이터를 적절히 인식하여 변환하는지에 관한 궁금증을 남겼습니다.
스프링 MVC는 HandlerMethodArgumentResolver
, HttpMessageConverter
등을 통해 해당 기능을 제공합니다.
먼저 스프링 MVC가 어떻게 컨트롤러에 파라미터를 생성하여 전달하는지 알아보겠습니다.
어노테이션 기반의 컨트롤러를 사용한다면 RequestMappingHandlerAdater
(요청 매핑 핸들러 어댑터)가 사용됩니다.
요청 매핑 핸들러 어댑터가 ArgumentResolver
를 통해 컨트롤러의 어노테이션이나 파라미터 정보를 인식하고 이를 기반으로 적절한 파라미터를 생성하여 전달합니다.
ex) @ModelAttribute
가 사용되고 파라미터로 Model
, HttpServletRequest
, XxObject(임의의 객체)가 사용된다면 각 객체를 생성하고 HTTP 요청 정보를 기반으로 적절히 매핑하여 전달합니다.
어노테이션 기반의 컨트롤러가 다양한 파라미터를 사용할 수 있는 이유는 스프링 MVC가 ArgumentResolver
(인터페이스)의 구현체 수십 가지를 미리 구현해 두었기 때문입니다.
가능한 파라미터 목록은 스프링 공식 문서에서 확인할 수 있습니다.
ArgumentResolver
는 supportsParameter()
와 resolveArgument()
두 메서드를 제공합니다.
supportsParameter()
를 통해 해당 컨트롤러의 파라미터를 지원하는지 체크하고 resolveArgument()
로 객체를 생성합니다.
추가로 컨트롤러에서 반환된 값은 HandlerMethodReturnValueHandler
(ReturnValueHandler)를 통해 변환하고 처리합니다. ArgumentResolver
와 유사하게 동작하며 컨트롤러에서 ModelAndView
를 반환하지 않고 String을 반환해도 같은 응답이 출력된 이유가 이 때문입니다.
사용 가능한 반환 타입 목록은 스프링 공식 문서에서 확인할 수 있습니다.
이제 스프링 MVC가 어떻게 데이터를 변환하는지 알아보겠습니다.
스프링 MVC는 HttpMessageConverter
를 통해 HTTP 요청 데이터나 응답 데이터를 변환할 수 있습니다.
HTTP 요청의 경우 @RequestBody
, HttpEntity
(RequestEntity
)가 있을 때,
응답의 경우 @ResponseBody
, HttpEntity
(ResponseEntity
)가 있을 때 메시지 컨버터가 작동합니다.
중요한 메시지 컨버터 두 가지를 알아보면
StringHttpMessageConverter
: String 타입으로 데이터 처리
@RequestBody String data
@ResponseBody {return "ok";}
미디어타입 text/plainMappingJackson2HttpMessageConverter
: 객체, HashMap, application/json 처리
@RequestBody User user
@ResponseBody {return user;}
미디어타입 application/json가장 많이 사용하는 MappingJackson2HttpMessageConverter
가 작동하는 방식을 더 자세히 알아보면
HTTP 요청 -> 컨트롤러에서 @RequestBody
, HttpEntity
여부 확인 -> canRead()
로 대상 클래스 타입(객체 or HashMap)과 미디어 타입(application/json
) 여부 확인 -> 통과 시 read()
로 객체 생성 및 반환
컨트롤러에서 @ResponseBody
, HttpEntity
여부 확인 -> canWrite()
로 return 대상 클래스 타입(객체 or HashMap)과 미디어 타입(application/json
) 여부 확인 -> 통과 시 write()
로 HTTP 메시지 바디에 데이터 생성
메시지 컨버터가 사용되는 위치
블로그를 읽으며 어느정도 예상 하셨겠지만 메시지 컨버터는 HTTP 요청을 컨트롤러의 파라미터로 바인딩하는 시점과 반환 값을 응답 메시지로 변환할 때 사용되므로 ArgumentResolver
와 ReturnValueHandler
에서 사용됩니다.
각 타입에 맞는 ArgumentResolver
와 ReturnValueHandler
가 대부분 구현되어 있고 이들이 HTTP 메시지 컨버터를 이용하여 데이터를 변환하고 처리합니다.
추가로 HandlerMethodArgumentResolver
, HandlerMethodReturnValueHandler
, HttpMessageConverter
는 모두 인터페이스로 제공되므로 필요하다면 직접 기능을 확장하여 사용할 수 있습니다.
WebMvcConfigurer
을 상속받은 클래스에 addArgumentResolvers()
나 extendMessageConverters()
를 이용하여 등록 후 스프링 빈에 등록하면 사용할 수 있습니다.
사진은 김영한님의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 강의자료에서 발췌하였습니다.