-> 블로그 이전

[Spring] Handler Adapter / Argument Resolver / HTTP Message Converter

2022. 6. 12. 18:36Language`/Spring

요청 매핑 핸들러 어댑터 (RequestMappingHandlerAdapter)

 

[Spring] HTTP 메시지 컨버터

뷰 템플릿으로 HTML을 생성해서 response하는게 아니라, HTTP API처럼 JSON형식의 데이터를 HTTP Message Body에 읽거나 쓸 경우 "HTTP 메시지 컨버터"를 사용하면 손쉽게 body의 데이터를 조작할 수 있다 JSON뿐

cs-ssupport.tistory.com

그러면 앞에서 설명한 HTTP 메시지 컨버터는 도대체 스프링 MVC 구조 어디서 사용되는 걸까??

 

전형적인 스프링 MVC 구조에서는 HTTP 메시지 컨버터가 사용되는 부분을 찾을 수가 없다

 

그러면 여기서 {핸들러 어댑터 - 핸들러}부분을 더 자세히 살펴보자

 

Argument Resolver

사실 {핸들러 어댑터 - 핸들러}사이에서는 Argument Resolver라는 아이가 과정을 도와주고 있다

 

Argument Resolver @Controller의 "파라미터 & 애노테이션 정보"를 기반으로 실제 로직을 수행하는 컨트롤러에게 전달할 데이터를 생성해준다

  • HttpServletRequest
  • Model
  • @RequestParam
  • @ModelAttribute
  • @RequestBody
  • HttpEntity
  • ...
Argument Resolver = 인자 해결사
>> Request Mapping에 의한 데이터가 들어올때 이 데이터들을 binding해주고 애노테이션에 맞게 modify해주는 기능을 제공해준다

 

예를 들어서 우리는 {param : username, age}라는 값을 @ModelAttribute를 통해서 HelloData에 담아왔다

이 과정이 어떻게 동작하는지는 전혀 모른채 사용하였는데, 이 과정을 도와주는 것이 바로 Argument Resolver이다

 

Annotation 기반 @Controller를 처리하는 "요청 매핑 핸들러 어댑터"는 Argument Resolver를 통해서 컨트롤러가 필요로 하는 다양한 파라미터의 값(객체)를 생성한다

이렇게 Argument Resolver에서 열심히 일을 해서 데이터를 생성하였으면 그제서야 핸들러 어댑터가 핸들러를 호출하면서 "생성된 데이터"도 같이 넘겨준다

 

 

ReturnValueHandlerResponse값을 변환하고 처리해주는 아이이다

Argument Resolver : Request로 들어온 다양한 파라미터 값들을 처리해서 데이터 생성
HandlerMethodReturnValueHandler : Response로 전달할 데이터를 생성

 

※ Example)

@PostMapping("/request-body-json-v1")
public void requestBodyJsonV1(
        HttpServletRequest request,
        HttpServletResponse response
) throws IOException {
    ServletInputStream inputStream = request.getInputStream();
    String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

    log.info("messageBody(JSON) = {}", (messageBody + " <Request - JSON>"));

    HelloData2 helloData = objectMapper.readValue(messageBody, HelloData2.class);

    log.info("messageBody(Object) = {}", (helloData + " <Request - Object>"));

    response.getWriter().write(messageBody + "\n" + helloData);
}

<1. 핸들러 어댑터>

"Argument Resolver야 HttpServletReqeust, HttpServlerResponse 값들 처리해서 데이터 생성해줘

각각의 파라미터가 처리해주는 Argument Resolver와 1:1로 매칭된다

  • 핸들러 어댑터는 각각의 Argument Resolver에 대해서 "supportsParameter()"를 호출해서 처리할 수 있는지 검증한다
  • 처리할 수 있는 A-R을 찾으면 resolveArgument()를 통해서 값을 통해서 데이터를 생성해낸다

 

<2. Argument Resolver>

파라미터 값들을 처리해서 핸들러 어댑터에게 전달한다

 

<3. 핸들러 어댑터>

처리된 데이터들을 받은 핸들러 어댑터는 핸들러를 호출하면서 데이터도 같이 넘겨준다

 

<4. 핸들러>

핸들러 어댑터로부터 처리된 데이터를 받은 핸들러는 여러 작업을 수행한다

 

<5. HandlerMethodReturnValueHandler>

핸들러가 로직 수행을 완료하고 Response 데이터를 작성하기 위해서 HandlerMethodReturnValueHandler가 동작한다

 


HTTP 메시지 컨버터 위치

지금까지 {핸들러 어댑터 - 핸들러}사이의 동작 과정을 살펴보았는데 그러면 HTTP 메시지 컨버터는 도대체 어디서 동작하는걸까?

>> HTTP 메시지 컨버터는 {Argument Resolver & HMRVH}가 호출해서 동작한다

결국 핸들러가 필요한 값을 Argument Resolver에서 생성하고, 생성할때는 {클래스 & 미디어 타입}을 고려해서 알맞은 데이터를 생성해야 하기 때문에 여기서 HTTP 메시지 컨버터가 이용된다

  • 모든 Argument Resolver가 HTTP 메시지 컨버터를 이용하는게 아니라, 일부만 이용한다
    • @RequestBody
    • HttpEntity

 

Argument Resolver가 HTTP 메시지 컨버터를 호출할때는 "read()"를 활용

HandlerMethodReturnValueHandler가 HTTP 메시지 컨버터를 호출할때는 "write()"를 활용