[6] 스프링 MVC (12) - HTTP 메시지 컨버터 원리 (+Argument Resolver / ReturnValue Handler)

김정욱·2021년 5월 22일
0

[6] 스프링 MVC

목록 보기
12/13
post-thumbnail

HTTP 메시지 컨버터

[ 역할 ]

  • HTTP response가 아닌 데이터를 담아서 보내는 경우
    • viewResolver대신 HttpMessageConventer동작 (다양한 종류의 컨버터존재함)
    • 기본 문자 --> StringHttpMessageConverter가 처리
    • 기본 객체 --> MappingJackson2HttpMessageConverter가 처리
  • HTTP request가 오거나 HTTP response데이터를 body에 담아서 보낼 때 우리는 별 생각 없이 했다
    --> 스프링모든 메시지 내용알맞게 변환해주었기 때문
    --> 이러한 역할을 해주는 것이 바로 HTTP 메시지 컨버터

[ 사용 원리 ]

( HTTP 메시지 컨버터 핵심 코드 )

  • canRead() / canWrite() --> 메시지 컨버터가 해당 클래스, 미디어타입을 지원하는지 체크
  • read() / write() --> 메시지 컨버터를 통해서 메시지읽고 쓰는 기능

( HTTP 컨버터가 사용되는 경우 )

  • 스프링 MVC는 다음의 경우에 HTTP 메시지 컨버터를 적용
    : 메시지 컨버터가 필요한 경우 --> HTTP request Body데이터가 있는 경우
    • HTTP 요청 : @RequestBody / HttpEntity(RequestEntity)
    • HTTP 응답 : @ResponseBody / HttpEntity(ResponseEntity)

( 주요 메시지 컨버터 )

  • 메시지 컨버터2가지를 통해 조합해서 매칭
    • 요청 파라미터의 클래스 타입
    • HTTP request 특정 필드(Content-Type / Accept)의 미디어 타입
  • ex) 요청 파라미터객체가 왔는데, 미디어 타입application/json이 아니다 ?
    --> 매핑되는 컨버터가 없음 --> 오류 발생

( HTTP 요청 / HTTP 응답 흐름 )

  • HTTP 요청 흐름
    • HTTP Request 요청
    • Controller에서 @RequestBody 혹은 HttpEntity 파라미터사용
    • 메시지 컨버터메시지를 읽을 수 있는지 확인하기 위해 canRead()를 호출
      • 대상 클래스 타입 확인
        : ex) @RequestBody로 받은 대상 클래스 타입(byte[] / String 등등)
      • HTTP requestConent-Type에 해당하는 미디어 타입을 지원하는지 확인
        : ex) text/plain, application/json 등등
    • canRead()를 만족하면 read()를 호출해서 객체를 읽어서 우리가 쓸 수 있도록 생성하고 반환
  • HTTP 응답 흐름
    • Controller에서 @ResponseBdy / HttpEntity로 값이 반환
    • 메시지 컨버터가 메시지를 쓸 수 있는지 확인하기 위해 canWrite()를 호출
      • 대상 클래스 타입 확인
      • HTTP requestAccept에 해당하는 미디어 타입지원하는지 확인
    • canWrite()을 만족하면 write()를 호출해서 HTTP Response Body데이터 생성

( 추가 정보 )

  • 그렇다면 스프링 MVC구조에서 HTTP 메시지 컨버터어디쯤에서 수행이 되는가?
    • 정답은 핸들러 어댑터실제 핸들러(Controller)호출하는 과정에서 일어난다
    • 정확한 위치를 알기 위해서Argument Resolver / ReturnValue Handler알아야 한다!

Argument Resolver & ReturnValue Handler ?

[ 설명 ]

  • 스프링 MVC 구조에서 핸들러 어댑터를 통해 실제 핸들러(컨트롤러)호출하는 과정을 자세히 알 필요가 있다

  • 생각해보면, 어노테이션 기반의 컨트롤러정말 많은 종류의 파라미터사용했다
    (HttpSErvletRequest / Model / @RequestParam / @ModelAttribute 등)
  • 이렇게 유연하게 파라미터를 사용할 수 있던 비밀은 바로 중간에 Argument Resolver가 있기 때문이다.

[ Argument Resolver ]

( 설명 )

  • 유연하게 다양한 파라미터를 처리하기 위한 것
  • 핸들러 어댑터Argument Resolver호출해서 미리 들어갈 매개변수를 파악 & 생성
  • 스프링30개가 넘는 ArgumentResolver기본으로 제공
  • 정확히는 HandlerMethodArgumentResolver 이다.

( 동작 원리 )

  • 핸들러 어댑터Argument Resolver호출
  • Argument Resolver는 내부에 supportsParameter()호출하며 어떤 파라미터를 지원하는지 확인
  • 지원하는 파라미터를 찾은 뒤 resolveArgument()호출해서 실제 객체를 생성
    (실제 객체를 생성할 때 HTTP 메서드 컨버터를 통해 메시지를 변환하여 사용)

[ ReturnValue Handler ]

( 설명 )

  • ArgumentResolver비슷한데, 이것은 응답 값을 변환하고 처리
  • 컨트롤러에서 String으로 뷰 이름을 반환해서 동작하는 이유가 바로 ReturnValueHandler 덕분
  • 스프링10개가 넘는 RetrurnValueHandler지원

스프링 MVC 구조에서 HTTP 메시지 컨버터

  • 스프링 MVC 구조에서 HTTP 메시지 컨버터사용되는 시점
    • ArgumentResolver / ReturnValueHandler가 대응되는 파라미터 / 반환값만들어주는 과정에서
      HTTP 메시지 컨버터호출해서 사용
  • 스프링ArgumentResolver / ReturnValueHandler / HttpMessageConverter 모두 인터페이스로 제공
    • 실제 확장이 필요할 때 이러한 내부 원리를 알고있어야 확장 포인트를 알 수 있음!
profile
Developer & PhotoGrapher

0개의 댓글