Spring MVC 패턴에서 Argument Resolver의 역할을 알아보도록 하겠습니다.
1. MVC 흐름
Spring MVC 패턴 설계 시 대략적인 흐름은 그림과 같습니다.
클라이언트가 HTTP 요청을 보낸다면 DispatcherServlet(FrontController)에서 클라이언트 요청을 수신하고 요청된 URI를 기반으로 애플리케이션의 컨트롤러를 호출한 뒤, ViewResolver에 반환합니다.
이 때, ArgumentResolver가 Controller(Handler)에 공통으로 필요한 패러미터(객체)를 생성하고 Controller를 호출하면서 값을 넘겨주게 됩니다. 이를 Spring에서는 애노테이션 기반으로 인터페이스를 제공하는데 한 번 살펴보겠습니다.
2. 예시
@Slf4j
@Controller
public class RequestBodyStringController {
@PostMapping("/request-body-string-v1")
public void requetBodyString(HttpServletRequest request, HttpServletResponse response) throws IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);// String은 byte code로 지정해야함
log.info("messageBody={}",messageBody);
response.getWriter().write("ok");
}
@ResponseBody
@PostMapping("/request-body-string-v4")
public String requetBodyStringV4(@RequestBody String messageBody) throws IOException {
log.info("messageBody={}", messageBody);
return "ok";
}
}
위 코드는 패러미터로 HttpServletRequest는 물론이고 @RequestBody와 같이 HTTP 메시지를 처리하고 있습니다. HttpServlet이나 @RequestBody와 같은 패러미터를 처리해야 하는데 이는 Argument Resolver 인터페이스를 보면 알 수 있습니다.
Argument Resolver(정확한 인터페이스 명은 HandlerMethodArgumentResolver)의 API를 한 번 확인해보겠습니다.
supportsParameter의 MethodParameter를 확인해보면 Controller에서 받아야 할 패러미터의 정보를 확인할 수 있습니다.
MethodParameter에서 boolean true를 반환하면 Object(객체)타입으로 만들어 resolveArgument가 객체를 만들어 넘겨주게 됩니다.
supportsParameter를 확인해보면
많은 종류의 타입을 처리하는 Resolver를 확인할 수 있습니다. 그 중 무작위로 RequestParamMethodArgumentResolver를 하나 살펴보겠습니다.
패러미터에 RequestParam이 있다면 (hasParameterAnnotation(RequestParam.class) return하는 형식입니다.
결론적으로 supportsParameter를 통해 루프를 돌면서 이 패러미터가 처리가능한지 확인한 뒤에 return 하게 되겠네요.
사용가능한 패러미터는 매뉴얼에서 확인할 수 있습니다.
3. HTTP Converter
Argument Resolver에서는 일반적으로 위의 패러미터에서 다 처리하게 되는데 HTTP 메시지 컨버터를 사용하는 패러미터가 있다면( ex- @RequestBody, @ResponseBody, HttpEntitiy 등..) 컨버터를 거쳐 객체를 생성할 뿐만 아니라 호출하여 응답 결과까지 만들게 됩니다. 예시 중 하나인 HttpEntitiy의 API를 살펴보겠습니다.
상속받은 주입관계가 많아 간단하게 다이어그램을 통해 보면, Superclass인 HanderlMethodArgumentResolver를 확인할 수 있는데
이는 HttpEntity를 처리하는 Argument Resolver임을 확인할 수 있습니다.
resolveArgument 메서드를 확인해보면 body라는 이름의 객체를 생성하고 HttpEntity<>를 return하는 것을 확인할 수 있습니다.
Spring은 Argument Resolver, Http message Converter, ReturnValue Handler를 인터페이스로 제공하여 구현체를 넣어 간편하게 확장할 수 있어 편리함을 제공하고, 확장에 대해 열려있고 수정에 대해 닫혀있어야 한다는 OCP의 원칙을 지킬 수 있게됩니다.
참조
'Skills > Spring' 카테고리의 다른 글
Spring - Bean Scope 관리 (0) | 2022.09.13 |
---|---|
Spring - Bean 생명주기 콜백 (0) | 2022.09.09 |
Spring - ComponentScan(컴포넌트 스캔) (0) | 2022.09.06 |
Spring - Singleton(싱글톤) (0) | 2022.09.04 |
Spring - BeanFactory & BeanDefinition (0) | 2022.09.01 |