Spring Web MVC는 서블렛 API 기반의 웹 프레임워크로, 다른 프레임워크와 마찬가지로 중앙 서블릿인 DispatcherServlet
이 요청 처리를 담당하는 프론트 컨트롤러 패턴으로 구성된다. DispatcherServlet
이 요청 처리의 책임을 지지만 실제 처리는 역할에 따라 컴포넌트에 위임한다. 따라서, Spring MVC의 요청 처리 흐름을 이해하기 위해서는 DispatcherServlet
의 이해가 선행되어야 한다.
DispatcherServlet
은 요청을 순서에 따라 컴포넌트에 처리를 위임한다. DispatcherServlet
도 서블릿 컨테이너가 관리하는 서블릿의 하나다. 이는 DispatcherServlet
의 상속 관계를 통해 확인할 수 있다. 상속 관계는 다음과 같다.
따라서, 다른 서블릿과 마찬가지로 자바 설정파일이나 web.xml
을 통한 서블릿 명세에 따라 호출, 매핑되고 서블릿 컨테이너가 생명 주기를 관리한다.
다음 그림은 서블릿의 생명 주기를 보여준다.
다음 코드는 자바로 DispatcherServlet
로 등록하는 코드다.
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletCxt) {
// Load Spring web application configuration
AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
ac.register(AppConfig.class);
ac.refresh();
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(ac);
ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
다음과 같이 web.xml
파일에 작성할 수도 있다.
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-context.xml</param-value>
</context-param>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
위 두 예제는 Spring을 기준으로 필요한 작업이다. Spring Boot를 사용하면 자체 내장된 서블릿 컨테이너(톰켓)가 서블릿과 필터를 등록한다.
DispatcherServlet
은 구성을 위해 WebApplicationContext
가 필요하다. 서블릿은 하나의 WebApplicationContext
를 포함하고, 여러 서블릿에서 공유해서 사용하는 서비스와 리포지토리와 같은 인프라 빈은 Root WebApplicationContext
에포함된다.
DispatcherServlet
은 다음의 순서로 요청을 처리한다.
DispatcherServlet
에 들어오면 해당 요청을 처리하기 위한 핸들러를 찾기 위해 HandlerMapper
에 요청을 위임한다.HandlerMapper
가 핸들러를 반환하면 해당 핸들러를 실행하기 위한 HandlerAdapter
를 찾는다.HandlerAdapter
를 통해 핸들러를 실행한다.HandlerAdapter
가 실행 결과로 ModelAndView
를 반환한다.ModelAndView
를 ViewResolver
로 전달하여 뷰로 변환한다.서블릿 컨테이너는 서블릿의 생명 주기를 관리한다.
서블릿의 생명 주기는 init() → service() → destroy()
순서로 진행된다. 스프링에서는 서블릿 컨테이너 역할을 Tomcat이 맡고 있다.
따라서, 톰캣을 Servlet Container로 볼 수 있다.
서블릿 컨테이너는 서블릿의 생명 주기 관리 뿐만 아니라 요청이 들어왔을 때 요청을 처리하기 위한 서블릿 인스턴스를 생성하고 이를 싱글톤으로 관리한다. 또한, 다수의 요청을 멀티 쓰레드로 처리하도록 지원한다.
2.2 Spring MVC 요청 처리 과정
이 수행된다.