Spring MVC 구조를 학습하게 되었습니다.
스프링 MVC는 아래와 같은 흐름으로 진행됩니다.
처음엔 그림만 보면 이해하기 어렵다고 느낄텐데요.
차근차근 따라가면 흐름은 그렇게 어렵지 않습니다.
Dispatcher Servlet
클라이언트로부터 HTTP 요청이 오면 먼저 Dispatcher Servlet에 도달하게 됩니다.
(흐름 편의상 filter는 생략)
스프링 공식문서에서 Dispatcher Servlet은 아래와 같이 설명합니다.
Spring MVC, as many other web frameworks, is designed around the front controller pattern where a central Servlet, the DispatcherServlet, provides a shared algorithm for request processing, while actual work is performed by configurable delegate components. This model is flexible and supports diverse workflows.
The DispatcherServlet, as any Servlet, needs to be declared and mapped according to the Servlet specification by using Java configuration or in web.xml. In turn, the DispatcherServlet uses Spring configuration to discover the delegate components it needs for request mapping, view resolution, exception handling, and more.
간단히 정리해보면,
스프링 MVC는 다른 많은 웹 프레임워크와 마찬가지로 중앙 서블릿인 디스패처 서블릿이 요청 처리를 위한 공유 알고리즘을 제공하는 front-controller-pattern을 중심으로 설계되어 있으며, DispatcherServlet은 Spring config을 사용하여 전반적인 http 요청에 대한 처리(request mapping, view, 예외 처리등)에 대한 기능을 제공합니다.
Dispatcher Servlet 은 request에 대한 전반적인 요청을 처리한다고 볼 수 있습니다.
(화살표를 잘 보면 대부분의 요청은 Dispatcher Servlet으로부터 화살표가 시작하는 것을 볼 수 있습니다.)
Handler Mapping
핸들러 매핑은 말그대로 요청에 맞는 핸들러(=컨트롤러)를 찾는 기능입니다.
Dispatcher Servlet은 요청 url에 맞는 컨트롤러를 핸들러 매핑을 통해 찾습니다.
스프링은 대부분의 핸들러 매핑을 구현해 놓았기 때문에 개발자가 직접 핸들러 매핑을 만들 필요는 없습니다.
Handler Mapping
0 = RequestMappingHandleMapping : 애노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
1 = BeanNameUrlHandlerMapping : 스프링 빈의 이름으로 핸들러 찾음
스프링이 구현한 핸들러 매핑은 우선순위에 따라 요청 url에 맞는 컨트롤러(핸들러)를 찾습니다.
0순위로는 애노테이션 기반의 컨트롤러 (@RequestMapping)이 붙어있는 컨트롤러를 먼저 찾습니다.
1순위로는 스프링 빈의 이름으로 핸들러를 찾습니다.
우리는 대부분 애노테이션 기반의 컨트롤러 (@RequestMapping)를 사용하기 때문에 @RequestMapping이 붙은 컨트롤러 중에서 찾게 되겠죠.
Handler Adapter
핸들러 매핑을 통해서 찾은 핸들러를 실행하기 위해서는 핸들러 어댑터가 필요합니다.
차례대로 핸들러 어댑터들을 돌면서 맞는 어댑터를 찾으면 Dispatcher Servlet이 해당 어댑터의 handler를 실행합니다.
핸들러 어댑터가 필요한 이유
다양한 형태의 핸들러(컨트롤러)가 존재하기 때문입니다.
어떤 개발자는 Controller 인터페이스를 구현하는 방식의 핸들러를 구현하고 싶을 수 있고, 또 다른 개발자는 애노테이션 기반의 핸들러를 구현하고 싶을 수 있습니다.
이와같이 개발자마다 컨트롤러(핸들러)를 구현하는 방식이 다를 수 있는데, 이 모든 요구 사항을 맞추기 위해서 어댑터가 필요한 것입니다.
Handler Adapter
0 = RequestMappingHandleAdapter : 애노테이션 기반의 컨트롤러인 @RequestMapping에서 사용
1 = HttpRequestHandlerAdapter : HttpRequestHandler 처리
2 = SimpleControllerHandlerAdapter : Controller 인터페이스 처리
스프링이 구현해 놓은 핸들러 어댑터들을 돌면서 맞는 어댑터를 찾습니다.
0순위로는 우리가 평소에 사용하는 애노테이션 기반의 핸들러를 실행시킬 수 있는 어댑터입니다.
1순위로는 HttpReqeustHandler 인터페이스를 통해 구현된 핸들러를 실행시킬 수 있는 어댑터입니다.
2순위로는 Controller 인터페이스를 통해 구현된 핸들러를 실행시킬 수 있는 어댑터입니다.
실제로 SimpleControllerHandlerAdapter에서 해당 Controller 인터페이스의 인스턴스가 맞는지 확인하는 코드도 볼 수 있습니다.
지금까지
Http Request -> Dispatcher Servlet -> HandlerMapping -> Dispatcher Servlet -> HandlerAdapter 목록조회 -> Dispatcher Servlet -> HandlerAdapter를 통해 핸들러 실행
까지의 흐름을 정리해 보았습니다.
개인적으로 중요한 포인트는
- Spring MVC 전체적인 흐름
- Dispatcher Servlet에서 전반적인 요청을 처리한다. (핸들러 매핑후에 바로 실행하는 것이 아닌 Dispatcher Servlet이 매핑된 핸들러를 받고 어댑터를 찾고 실행시킴)
- Handler를 실행하기위해 Handler Adapter가 필요하다
정도로 볼 수 있었습니다.
감사합니다.
'Web > Spring' 카테고리의 다른 글
[Tomcat 구현하기] 2. HttpRequest, HttpResponse, RequestMapper, Controller (0) | 2022.09.15 |
---|---|
[Tomcat 구현하기] 1. Tomcat, Connector, Socket (0) | 2022.09.14 |
[Spring] CORS 관련 405에러 해결방법 (1) | 2022.06.02 |
[Spring] Bean 등록의 이점 (3) | 2022.05.12 |
Spring Bean Validation 적용하기 (2) | 2022.05.10 |