[66해빗 페이백 챌린지] 14일차

tree·2023년 5월 15일
0

HTTP 메시지 컨버터

  • HTTP 메시지 컨버터는 HTTP 메시지 바디의 내용을 객체로 변환하거나 혹은 그 반대로 변환하는 역할을 담당한다.

    • 정적 리소스를 전송하거나 뷰 템플릿으로 동적으로 생성한 HTML을 메시지 바디에 담아서 전송하는 건 제외.
  • 스프링 MVC는 다음의 경우에 메시지 컨버터를 사용한다.

    • 요청을 받을 때 메소드에 @RequestBody가 있거나 HttpEntity 파라미터가 있는 경우.
    • 응답을 보낼 때 메소드에 @ResponseBody가 있거나 HttpEntity를 리턴하는 경우
  • HttpMessageConverter 인터페이스

    package org.springframework.http.converter;
    
    public interface HttpMessageConverter<T> {
    
      boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
      boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
    
      T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;
      void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;
    }
    • canRead()
      • 해당 미디어 타입(요청 메시지의 Content-type)의 바디를 해당 클래스 타입으로 변환 가능한지 판단.
    • canWrite()
      • 해당 클래스 타입의 객체를 해당 미디어 타입(HTTP 요청의 Accept, 더 정확히는 @RequestMapping 의 produces 값)의 바디로 변환 가능한지 판단.
    • read()
      • 메시지를 읽어서 객체로 변환
    • write()
      • 객체를 메시지로 변환
  • 스프링 부트 기본 메시지 컨버터

    0 = ByteArrayHttpMessageConverter
    1 = StringHttpMessageConverter
    2 = MappingJackson2HttpMessageConverter
    • 우선순위대로 나열한 것이다.
    • 더 많은 컨버터가 존재한다.
    • 컨버터들은 각자 처리할 수 있는 클래스 타입과 미디어 타입이 있는데 둘을 체크해서 해당 컨버터를 사용할지 판단한다.
      • ByteArrayHttpMessageConverter
        • byte[] 데이터를 처리한다.
        • 클래스 타입: byte[], 미디어 타입: */*
        • 해당 컨버터를 사용해 응답 메시지를 생성하면 미디어 타입으로 application/octet-stream이 지정됨.
      • StringHttpMessageConverter
        • String 데이터를 처리한다.
        • 클래스 타입: String, 미디어 타입: */*
        • 해당 컨버터를 사용해 응답 메시지를 생성하면 미디어 타입으로 text/plain이 지정됨.
      • MappingJackson2HttpMessageConverter
        • 클래스 타입: 객체 또는 HashMap, 미디어 타입: application/json
        • 해당 컨버터를 사용해 응답 메시지를 생성하면 미디어 타입으로 application/json이 지정됨.

요청 매핑 헨들러 어뎁터 구조

  • @RequestMapping을 사용하는 컨트롤러의 메소드는 HttpServletRequest, Model, HttpEntity은 물론이고, @RequestParam , @ModelAttribute, @RequestBody 같은 어노테이션을 이용하여 생성된 객체까지 매우 다양한 파라미터를 주입받아 사용할 수 있다.

    • 어떻게 이런 일이 가능할까?
      • RequestMappingHandlerAdapter의 ArgumentResolver가 이런 객체들을 생성하여 @RequestMapping을 사용하는 컨트롤러의 메소드의 파라미터로 주입해주기 때문이다.

  • ArgumentResolver

    • RequestMappingHandlerAdapter는 컨트롤러 메소드의 파라미터 타입에 적합한 ArgumentResolver를 호출하여 객체를 생성한 다음 컨트롤러 메소드를 호출하면서 파라미터로 넘겨준다.
    • 스프링은 30가지가 넘는 ArgumentResolver를 제공한다.
    • 원래 이름은 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()를 호출해 실제 객체를 생성한다.
    • 필요에 맞게 HandlerMethodArgumentResolver 구현해서 새로운 ArgumentResolver를 만들 수 있다.
  • HTTP 메시지 컨버터

    업로드중..

  • @RequestBody를 처리하는 ArgumentResolver와 HttpEntity를 처리하는 ArgumentResolver가 HTTP 메시지 컨버터를 호출해 파라미터에 넘길 객체를 생성한다.

  • @ResponseBodyHttpEntity를 처리하는 ReturnValueHandler가 HTTP 메시지 컨버터를 호출해서 응답 결과를 만든다.

  • 기능 확장

    • 스프링은 대부분의 기능을 제공하기 때문에 기능 확장이 필요하지는 않지만 기능 확장이 필요하면 WebMvcConfigurer를 상속해 빈으로 등록하면 된다.

0개의 댓글