본문 바로가기
  • 실행력이 모든걸 결정한다
Spring Series/Document

[SpringBoot] 공식 문서 요약(5) - 내장 서블릿 컨테이너

by 김코더 김주역 2021. 11. 25.
반응형

SpringBoot Document Review 5

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/

 

 

 

Embedded Servlet Container Support

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-developing-web-applications.html#boot-features-embedded-container

 

0) 들어가기 앞서...

- Spring Boot는 내장된 Tomcat, Jetty, Undertow 서버들을 지원하며, 완전히 설정된 인스턴스를 얻기 위해 적절한 Starter을 사용하면 된다.

- CentOS 운영체제에서 Tomcat을 사용하는 경우에 주의할 점이 있다. 컴파일된 JSP 파일들을 저장해두는 임시 디렉토리가 애플리케이션 실행중에 tmpwatch에 의해 삭제될 수 있다. 이를 방지하기 위해, tomcat.* 디렉토리들이 사라지지 않도록 tmpwatch 설정을 커스터마이징하거나 server.tomcat.basedir을 따로 설정해주는 방법이 있다.

 

1) Servlets, Filters, and Listeners

* Spring Beans로 등록하기

- 내장 서블릿 컨테이너를 사용하게 되면 Bean들로 서블릿, 필터, 모든 리스너들을 등록할 수 있다.

- application.properties으로부터 값을 참조할 수도 있다.

- 기본적으로 context가 하나의 Servlet을 포함하면 "/"에 매핑이 되고, 여러 Servlet을 포함한다면 Bean의 이름이 경로의 prefix로 사용된다.

- Filter은 모든 요청 "/*"에 매핑이 된다.

- 커스터마이징 클래스 : ServletRegistrationBean, FilterRegistrationBean, ServletListenerRegistrationBean

- Filter들의 우선순위는 다음과 같고, Order의 값이 낮을수록 우선순위가 높다. 

- Request body를 읽는 필터를 Ordered.HIGHEST_PRECEDENCE로 설정한다면, character encoding 설정이 제대로 이루어지지 않을 것이다. Servlet 필터가 Request를 래핑한다면, Order을 FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER와 같거나 낮게 설정해야 한다.

※ 예시) Filter에서 요청 URL 출력하기 - https://stackoverflow.com/questions/4389596/how-can-i-get-the-request-url-from-a-java-filter

 

 

2) Servlet Context 초기화

- 내장 서블릿 컨테이너는 javax.servlet.ServletContainerInitializer 인터페이스와 org.springframework.web.WebApplicationInitializer 인터페이스를 직접적으로 실행하지 않도록 설계되었다. 그 이유는 war의 내부에서 동작하는 제 3자 라이브러리가 Spring Boot 애플리케이션을 깨뜨리는 위험성을 줄이기 위함이다.

※ ServletContainerInitializer, WebApplicationInitializer : web.xml없이 서블릿 등록/매핑, 리스너 등록, 필터 등록 등을 수행할 수 있다.

- Servlet Context 초기화를 진행하려면 org.springframework.web.servlet.ServletContextInitializer 인터페이스를 구현해서 Bean으로 등록한다. 하나의 onStartup 메소드가 ServletContext로의 접근을 제공하고, 기존의 WebApplicationInitializer의 어댑터로 쉽게 사용할 수 있다.

※ ServletContextInitializer : Servlet container가 아닌 Spring에 의해 관리될 수 있도록 설계된 인터페이스로, Servlet Context를 프로그래밍적으로 설정할 수 있도록 도와준다. WebApplicationInitializer와 달리 해당 인터페이스의 구현체는 SpringServletContainerInitializer에 의해 탐지되지 않는다.

 

* Scanning for Servlets, Filters, and Listeners

- 내장 컨테이너를 사용한다면, @Bean으로 직접 등록하는 방법 외에도 @WebServlet, @WebFilter, @WebListener 클래스들을 만들어서 @ServletComponentScan 어노테이션을 통해 자동 등록시키는 방법을 쓸 수도 있다.

 

 

3) The ServletWebServerApplicationContext

- Spring Boot는 내장 서블릿 컨테이너를 사용할 때, 다른 종류의 ApplicationContext를 사용한다. ServletWebServerApplicationContext는 WebApplicationContext의 특수 타입으로, 하나의 ServletWebServerFactory bean을 찾음으로써 스스로 동작한다.

- 보통 TomcatServletWebServerFactory, JettyServletWebServerFactory, UndertowServletWebServerFactory 중에서 하나는 자동 설정되어 있다. 보통 이 구현체들은 알 필요가 없고, 개발자를 대신해서 적절한 ApplicationContext와 ServletWebServerFactory가 생성된다. 

 

 

4) Embedded Servlet Container 커스터마이징

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-developing-web-applications.html#boot-features-embedded-container

- Environment 프로퍼티들을 사용해서 공통 서블릿 컨테이너가 설정될 수 있으며, 보통 application.properties을 사용하여 프로퍼티들을 정의하게 된다.

- 공통 서버 설정은 네트워크, 세션, Error 관리, SSL, HTTP compression(압축)에 관한 설정들을 포함한다. 자세한 설정들은 문서 참조.

 

프로그래밍적 커스터마이징 예제 - 서버 포트를 9000으로 설정

우선 순위가 매우 높은 설정 방식이다.

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;

@Component
public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
	@Override
	public void customize(ConfigurableServletWebServerFactory server) {
		server.setPort(9000);
	}
}

 

직접적인 ConfigurableServletWebServerFactory 커스터마이징 예제

ConfigureableServletWebServerFactory의 변형들로는 TomcatServletWebServerFactory, JettyServletWebServerFactory, UntowServletWebServerFactory가 있으며, 각 서버별로 추가적인 커스터마이징 설정 메소드들이 있다.

@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
	TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
	factory.setPort(9000);
	factory.setSessionTimeout(10, TimeUnit.MINUTES);
	factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
	return factory;
}

 

 

5) JSP의 한계들

- Tomcat 혹은 Jetty 사용 시 배포 가능성 : war 가능, jar 불가능(Tomcat의 hard-coded file pattern 때문)
- Undertow는 아예 JSP를 지원하지 않는다.
- error.jsp를 따로 생성하는 것으로 에러 핸들링에 대한 default view를 override하지 않는다. Custom error pages를 사용해야 한다.

반응형

댓글