티스토리 뷰

반응형

(참고: Spring Boot를 기준으로 작성된 글입니다)

 

Controller (Controller와 RestController)와 RequestMapping의 글을 정리하면서

클래스와 메서드를 스프링 빈으로 등록하고 매핑이 되는지 살펴보았다

 

이번에는 RequestMapping이 요청과 응답시에 데이터를 어떻게 다루는지에 대하여 살펴보고자 한다

(@RequestMapping은 RequestMappingHandlerAdapter를 어노테이션화 한 것이다)

 

클라이언트가 요청을 할 때 그리고 서버가 응답을 할때

단순히 요청과 응답뿐이 아닌 각종 데이터를 함께 넘겨주고 반환받는다

 

이때 이 데이터를 처리하는 인터페이스가 바로 Argument Resolver와 ReturnValue Handler이다

 

Argument Resolver

컨트롤러의 메서드의 인자로 사용자가 임의의 값을 전달하는 방법을 제공하고자 할 때 사용한다

즉 HttpServletRequest, Model, @RequestParam, @ModelAttribute 등으로 작성된 전달 데이터를 기반으로

매우 다양한 파라미터 값을 사용할 때 필요한 인터페이스이다

(정확히는 HandlerMethodArgumentResolver이나 줄여서 Argument Resolver라고 부른다)

RequestParam을 다이어그램으로 까보면 실제로 위에 Argument Resolver가 있는 것을 확인할 수 있다

 

이렇게 파라미터를 유연하게 처리할 수 있게 해주는 것이 바로 Argument Resolver이다

Argument Resolver의 동작 방식은 아래와 같다

1. Handler를 호출하여 파라미터 값을 확인하여 정보를 전달받는다

(Handler = Controller)

 

2. Argument Resolver를 호출하여 해당 파라미터의 객체 생성을 요구한다

//ArgumentResolver 인터페이스의 실제 코드
public interface HandlerMethodArgumentResolver {

      boolean supportsParameter(MethodParameter parameter);

@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable 
			ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, 
            @Nullable WebDataBinderFactorybinderFactory) throws Exception;
}

Argument Resovler가 호출되면 supportsParamter를 호출하여 해당 파라미터를 지원하는지 체크한다,

지원하게 되면 resolveArgument를 호출하여 실제 객체를 생성하고 다시 Handler를 호출한다

 

3. Parameter의 객체를 생성하여 Handler를 호출함과 동시에 객체 또한 같이 전달한다

 

스프링은 30개가 넘는 ArgumentResolver를 전달한다 (공식문서에 자세히 나와있다)

https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-arguments

 

Return Value Resolver

ArgumentResovler가 요청 데이터를 처리하듯 Return Value Resolver는 그와 반대로 응답 데이터를 처리한다

(정확히는 HandlerMethodReturnValueHandler이나 줄여서 Return Value Handler라고 한다)

 

ResponseBody의 다이어그램을 까보면 위에 ReturnValueHandler가 있는 것을 확인 할 수 있다

 

Controller와 RestController의 가장 큰 차이점은 반환값의 차이다 (Controller와 RestController의 글)

Controller의 경우 String을 반환 값으로 적을 시 자동으로 뷰 리졸버를 호출하여 뷰로 반환하고

RestController의 경우 반환 값을 데이터 그 자체로 반환한다

 

이를 가능하게 해주는 것이 바로 Return Value Resolver이다

//Return Value Handler 인터페이스의 실제 코드
public interface HandlerMethodReturnValueHandler {

	boolean supportsReturnType(MethodParameter returnType);

	void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
			ModelAndViewContainer mavContainer, 
            NativeWebRequest webRequest) throws Exception;

}

작동원리는 Argument Resolver와 똑같다

반환받은 값을 supportsReturnType을 호출하여 지원하는 타입인지 확인하고

지원한다면 handlerReturnValue를 호출하여 해당 값을 반환해준다

 

스프링은 10개가 넘는 ReturnValueHandler를 지원한다(공식문서에 자세히 나와있다)

https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-return-types

 

MessageConverter

위의 Argument Resolver와 Return Value Handler만 있다고 객체를 생성하여 전달하고, 반환 값을 반환할 수는 없다

이 값들이 어떠한 클래스, 미디어타입인지 확인하는 절차가 필요한데 이를 수행하는 것이 바로 MessageConverter이다

예를 들어 @Controller 라면 String 값을 뷰리졸버를 호출하지만 @ResponseBody가 붙어 있다면 메시지 컨버터를 호출한다

 

메시지 컨버터는 아래의 글에서 자세히 살펴보겠다

(MessageConverter의 글)

 

(Argument Resolver , Return Value Handler는 결국 인터페이스이기 때문에 개발자가 필요에 따라 기능을 추가하여 확장할 수도 있다, 하지만 대부분의 기능을 이미 제공하고 있기 때문에 확장에 대해서는 이번에 다루지 않았다)

 

핵심정리

(Handler == Controller)

@Controller로 빈 등록이 되어 매핑된 값들을 RequestMapping으로 찾아 각각의 메서드들을 호출한다

이때 메서드만을 호출하는 것이 아니라 클라이언트가 전달하는 데이터

그리고 메서드를 반환할 때의 반환 값을 클라이언트와 서버는 주고받는다

 

이때 이 데이터를 다루는 인터페이스가 바로 ArgumentResolver와 ReturnValueHandler이다

이들이 파라미터와 반환 값을 체크할 때 MesageConverter라는 것을 사용하여

지원하는 값인지 체크하여 객체를 생성하여 전달하고 반환한다

반응형
댓글