Skills/Spring

Spring - Argument Resolver를 이용한 패러미터 처리

aoaa 2022. 9. 27. 23:41

 

 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