지금까지 우리는 HTTP의 요청과 응답을 알아봤다. Spring에서 우리가 요청하는 내용과 응답하는 값들을 자동으로 설정을 해준다고 하는데 이것은 어떻게 작동하는 것일까? 그 자동으로 변환시켜주는 것이 HTTP 메세지 컨버터이다.
HTTP API처럼 JSON 데이터를 HTTP 메세지 바디에 직접 읽거나 쓰는 경우 HTTP 메세지 컨버터를 사용하면 편리하다. 우리가 HTTP 메세지 바디에 데이터를 전달하기 위해 사용했던 @ResponseBody를 사용했을 때 viewResolver 대신 HttpMessageConverter가 동작하여 데이터를 그대로 전달받을 수 있는데 그 예시로
우리가 사용했던 예시의 컨버터들만 나열했다. 다음과 같은 컨버터들을 통해
package org.springframework.http.converter;
public interface HttpMessageConverter<T> {
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
List<MediaType> getSupportedMediaTypes();
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
void write(T t, @Nullable MediaType contentType, HttpOutputMessage
outputMessage) throws IOException, HttpMessageNotWritableException;
}
위의 메서드들을 사용하여 컨버터에서 지원하는 class인지 미디어 타입인지 체크 후 메세지를 읽고 쓰고가 가능하다. 요청이 들어오면 canRead()와 canWrite()를 통해 컨버터에서 사용할 수 있는지 체크 후 지원하지 않는다면 다음 메세지 컨버터로 넘어가고 모든 컨버터에서 지원하지 않는다면 exception이 발생한다.
그렇다면 HTTP 메세지 컨버터는 언제 동작하는 걸까?
다음 그림에서 우리가 그동안 보지 못했던 ArgumentResolver와 ReturnValueHandler가 생겼다. 그 둘을 각각 살펴보면
ArgumentResolver
client의 요청에서 파라미터를 유연하게 처리해주는 부분으로 내부의 supportParameter() 메서드를 통해 해당 파라미터를 지원하는지 체크하고 지원한다면 실제 객체를 생성하여 컨트롤러에 객체를 넘겨준다.
ReturnValueHandler
HandlerMethodReturnValueHAndler로 파일을 프로젝트 내부에서 검색해보면 확인할 수 있고 client의 요청 후 응답하는 과정에서 응답 값을 변환하고 처리한다.
두개의 공통점은 값을 체크하고 변환해준다. 이 부분인데 이 부분에 위에서 공부한 HTTP Message Converter가 동작하는 것이다. 자세히 공부하려면 엄청 복잡하다... 우선 동작 원리를 이해하는게 중요하다고 생각해서 이정도로 학습하고 넘어가려고 한다. spring을 직접 사용해보면서 동작 구조에 대해 더 생각해보자!