[스프링 부트 개념과 활용] 내장 웹 서버 (Embedded web server)
인프런에서 백기선님의 스프링 부트 개념과 활용을 수강하고 개인적으로 공부한 내용을 정리한 글입니다.
스프링 부트 ≠ 서버
Spring 프레임워크를 쉽게 사용할 수 있게해주는 Tool일 뿐, 스프링 부트 자체는 웹 서버가 아니다.
내장 서블릿 컨테이너 개요
spring-boot-starter-web을 사용한 프로젝트엔 톰캣(Tomcat)이 기본적으로 내장되어 있다. 톰캣은 데이터를 동적으로 처리하기 위한 서블릿 컨테이너로, JSP, 서블릿 처리, HTTP 요청과 응답 등을 처리한다.
자동 설정이 없다고 가정하고 Servlet을 만들어서 톰캣에 등록해보자.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
Tomcat tomcat = new Tomcat(); // 톰캣 객체 생성
tomcat.setPort(8080); // 포트 설정
Context context = tomcat.addContext("/", "/"); // 톰캣에 컨텍스트 추가
// 서블릿 객체 생성
HttpServlet servlet = new HttpServlet() {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.println("<h1>Hello world!</h1>");
}
};
final String servletName = "myServlet";
// 톰캣에 서블릿 추가
tomcat.addServlet("/", servletName, servlet);
// 컨텍스트에 서블릿 매핑
context.addServletMappingDecoded("/home", servletName);
try {
// 톰캣 실행 및 대기
tomcat.start();
tomcat.getServer().await();
} catch (LifecycleException e) {
e.printStackTrace();
}
}
}
웹 브라우저를 켜서 http://localhost:8080/home
으로 접속해보면 doGet()에서 작성한 내용이 HTML 문서로 반환된다.
스프링에서는 이렇게 Tomcat에 Servlet을 등록하고 실행하는 일련의 작업이 자동 설정으로 정의되어 있다. 자동 설정 덕분에 이 모든 작업을 상세하고 유연하게 설정 후 실행해준다.
-
ServletWebServerFactoryAutoConfiguration
: 서블릿 웹 서버 생성하는 설정 파일-
TomcatServletWebServerFactory
를 들어가보면 톰캣을 생성하고 서블릿, 디스패처 설정을 하는 코드가 있다.public WebServer getWebServer(ServletContextInitializer... initializers) { Tomcat tomcat = new Tomcat(); File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat"); tomcat.setBaseDir(baseDir.getAbsolutePath()); Connector connector = new Connector(this.protocol); tomcat.getService().addConnector(connector); this.customizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false); this.configureEngine(tomcat.getEngine()); // ... }
ServletWebServerFactoryAutoConfiguration
에서는TomcatServletWebServerFactory
를 사용하는TomcatServletWebServerFactoryCustomizer
를 반환한다.@Configuration @AutoConfigureOrder(-2147483648) @ConditionalOnClass({ServletRequest.class}) @ConditionalOnWebApplication( type = Type.SERVLET ) @EnableConfigurationProperties({ServerProperties.class}) @Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class}) public class ServletWebServerFactoryAutoConfiguration { // ... public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) { return new TomcatServletWebServerFactoryCustomizer(serverProperties); } // ... }
-
-
DispatcherServletAutoConfiguration
: 서블릿을 만들고 등록해주는 설정 파일
내장 서블릿 컨테이너 활용 방법
내장 웹 서버 변경
spring-boot-starter-web는 기본적으로 spring-boot-starter-tomcat
을 포함하고 있다. Tomcat 대신 Jetty를 내장 서버로 사용하도록 설정을 변경해보자.
pom.xml
에서 dependencies
를 아래와 같이 변경한다. tomcat의 include를 제거하기 위해 <exclusion>
태그를 추가했다.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- Exclude the Tomcat dependency -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Use Jetty instead -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>
다시 프로젝트를 빌드하고 로그를 확인해 보면 jetty를 사용하고 있다.
포트 변경하기
HTTP는 기본적으로 8080 포트를 사용하지만, resources/application.properties
을 사용해서 포트 번호를 변경할 수 있다.
server.port=7070
포트가 잘 바뀌었는지 확인해보자. ServletWebServerInitializedEvent
의 onApplicationEvent
는 Application이 생성되면 호출되는 콜백 메서드다.
@Component
public class PortListener implements ApplicationListener<ServletWebServerInitializedEvent> {
@Override
public void onApplicationEvent(ServletWebServerInitializedEvent servletWebServerInitializedEvent) {
WebServer webServer = servletWebServerInitializedEvent.getApplicationContext().getWebServer();
System.out.println("port: " + webServer.getPort());
}
}
포트 번호를 고정하는 대신 랜덤 포트를 사용하고 싶다면 값을 0으로 설정하면 된다.
server.port=0
References
'if (study) > Spring' 카테고리의 다른 글
[스프링 부트 개념과 활용] 내장 웹 서버에 HTTPS, HTTP2 적용하기 (0) | 2020.07.29 |
---|---|
[스프링 부트 개념과 활용] 자동 설정 (Auto Configuration) (0) | 2020.07.20 |
[스프링 부트 개념과 활용] 의존성 관리 (dependency management) (0) | 2020.07.20 |