Spring Boot 웹 애플리케이션을 WAR로 배포할 때 왜 SpringBootServletInitializer를 상속해야 하는걸까?

Yoo Young-mo
9 min readSep 22, 2017

Spring Boot로 웹 애플리케이션을 만들고 이를 WAR로 배포할 때에는(Apache Tomcat 같은 Servlet Container에) SpringBootServletInitializer를 상속 하도록 가이드 하고 있다.

The first step in producing a deployable war file is to provide a SpringBootServletInitializer subclass and override its configure method. This makes use of Spring Framework’s Servlet 3.0 support and allows you to configure your application when it’s launched by the servlet container. Typically, you update your application’s main class to extend SpringBootServletInitializer:

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-traditional-deployment.html

@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}

왜 SpringBootServletInitializer를 상속해야 하는 걸까?

사라진 web.xml

5년전 쯤으로 기억 한다. 필자는 Apache Tomcat을 기반으로 Spring 3 웹 애플리케이션을 개발 했었다.

당시에 web.xml에 Spring 웹 애플리케이션 컨텍스트(WebApplicationContext) 구성 하는 작업을 했다. 그 중에 대표적인 것이 서블릿 애플리케이션 컨텍스트(DispatcherServlet)를 web.xml에 등록 하는 것이었다.

<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>example</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

결국 이러한 작업은 Spring을 Apache Tomcat 같은 Servlet Container 에서 동작하도록 하기 위한 것이었다.

다시 현재로 돌아와서 필자는 Spring Boot 애플리케이션을 만들 때 Bootstrap 도구인 SPRING INITIALIZR를 즐겨 사용하는데 SPRING INITIALIZR 에서 자동 생성해준 코드에서는 web.xml을 찾을 수 없었다.

그렇다면 누가 어떻게 Servlet Container에 Spring 웹 애플리케이션 컨텍스트를 구성해 주는 걸까? 왜 web.xml은 보이지 않을까? 힌트는 SpringBootServletInitializer 문서 중에서 찾을 수 있다.

This makes use of Spring Framework’s Servlet 3.0 support and allows you to configure your application when it’s launched by the servlet container.

Servlet 3.0

Servlet 3.0 스펙에 새로운 기능 중 하나는 web.xml 없이 배포가 가능해진 것이다.(상세한 내용은 Asynchronous processing support in Servlet 3.0 의 Ease of configuration 절 참조)

그리고 Apache Tomcat 의 경우 Servlet 3.0 스펙을 7.0 버전 부터 지원한다.(https://en.wikipedia.org/wiki/Apache_Tomcat)

결국 과거에 필자가 web.xml 에 Spring 관련 설정을 등록했던 것은 Spring 3를 사용해서가 아니라 당시에 사용 했던 Tomcat 버전에서 Servlet 3.0을 지원하지 않아서 였다.

Spring Framework와 Servlet 3.0

Spring Framework는 Servlet 3.0 이상 환경에서 web.xml 대신하여 ServletContext를 프로그래밍적으로 다룰 수 있게 WebApplicationInitializer 인터페이스를 제공 한다.

Interface to be implemented in Servlet 3.0+ environments in order to configure the ServletContext programmatically — as opposed to (or possibly in conjunction with) the traditional web.xml-based approach.

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/WebApplicationInitializer.html

아래 처럼 web.xml 역할을 WebApplicationInitializer 인터페이스를 구현하여 프로그래밍적으로 ServletContext에 Spring IoC 컨테이너(AnnotationConfigWebApplicationContext)를 생성하여 추가할 수 있다.

public class MyWebAppInitializer implements WebApplicationInitializer {@Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext =
new AnnotationConfigWebApplicationContext();
dispatcherContext.register(DispatcherConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}

SpringBootServletInitializer는 WebApplicationInitializer 인터페이스의 구현체

SpringBootServletInitializer는 웹 애플리케이션 컨텍스트를 생성하여 ServletContext 에 추가한다. 이 과정에서 웹 애플리케이션 컨텍스트로는 AnnotationConfigEmbeddedWebApplicationContext 를 사용한다.

참고. 오렌지 색상은 org.springframework 패키지이고, 회색은 org.springframework.boot 패키지이다
SpringBootServletInitializer

결론

SpringBootServletInitializer 상속 한다는 결국 Tomcat 같은 Servlet Container 환경에서 Spring Boot 애플리케이션 동작 가능 하도록 웹 애플리케이션 컨텍스트 구성 한다는 의미 이다.

--

--