본문 바로가기
학습/Spring

[spring] 스프링부트의 내장 WAS 이해와 응용

by KKambi 2020. 4. 8.

스프링부트의 내장 WAS

  • 기본 = Apache Tomcat
  • @SpringBootApplication를 실행하면 자동으로 웹 서버가 실행
    - 스프링부트가 웹 서버 자체인 것은 아님
    - 스프링부트는 스프링을 편하게 사용하기 위한 툴에 불과
    - 내장된 웹 서버를 구동할 뿐

 

당연히, 순수 자바 코드로도 톰캣 구축 가능

  1. 톰캣 객체 생성
  2. 포트 설정
  3. 톰캣에 컨텍스트 추가
  4. 서블릿 생성
  5. 톰캣에 서블릿 추가
  6. 컨텍스트에 서블릿 맵핑
  7. 톰캣 실행 및 대기

 

스프링 부트는 자동으로 구축

  • Class ServletWebServerFactoryAutoConfiguration (서블릿 웹 서버 생성)
  • Class DispatcherServletAutoConfiguration (서블릿 생성 후, 등록)
  • Class TomcatServletWebServerFactoryCustomizer (서버 커스터마이징)
  • cf) @Import를 통해 다른 Conifguration을 사용할 수 있음

 

왜 서블릿 웹 서버 생성과, 서블릿 생성이 분리되어 있을까?

  • 서블릿 기반의 스프링MVC -> DispatcherServlet 필수
  • 서블릿 컨테이너(=Tomcat)은 바뀔 수 있다. 다른 WAS를 사용할 수 있다.
  • 서블릿은 변하지 않는다. 어떤 WAS를 사용하든 필요하다.
  • 결론) 어떤 서블릿 컨테이너를 사용하든
    DispatcherServlet을 생성해서 등록하는 Bean이 바로 DispatcherServletAutoConfiguration

 


 

스프링부트의 내장 WAS 변경하기

  1. spring-boot-starter-web 라이브러리가 spring-boot-starter-tomcat을 포함
  2. gradle의 exclude를 통해 spring-boot-starter-tomcat을 제외
  3. spring-boot-starter-undertow 의존성을 추가

 

스프링부트의 내장 WAS 사용하지 않기

  1. 서블릿 컨테이너 의존성을 참조하고 있으면, 스프링부트는 웹 어플리케이션으로 실행된다.
  2. properties 파일을 사용해서 web-application-type을 none으로 할당
  3. 서블릿 컨테이너 의존성이 있어도 무시되고 None-web-application으로 실행
//application.properties
spring.main.web-application-type=none

 

포트 변경하기

  • properties 파일에서 server.port를 할당
  • 0으로 할당하면 랜덤
//application.properties
server.port=8070

 

Properties의 WAS 설정 값을 어플리케이션 내에서 사용하기

  1. 이벤트리스너 역할의 빈을 생성해야 한다
  2. ApplicationListener<ServletWebServerInitializedEvent> 인터페이스를 구현하는 리스너 클래스 생성
  3. @Component로 등록
  4. WAS가 생성되면 이벤트리스너의 onApplication 콜백 메소드가 호출이 될 것
  5. 인자로 받은 event에서 applicationContext를 getApplicationContext( )로 가져온다
  6. 서블릿 웹서버 어플리케이션 컨텍스트로 getWebserver( )로 웹 서버 객체를 가져올 수 있다
  7. 웹 서버 객체의 getPort( )로 포트 값을 가져온다
@Component
public class PortListener implements ApplicationListener<ServletWebServerInitializedEvent> {
    @Override
    public void onApplicationEvent(ServletWebServerInitializedEvent event) {
        ServletWebServerApplicationContext servletWebServerApplicationContext = event.getApplicationContext();
        System.out.println(servletWebServerApplicationContext.getWebServer().getPort());
    }
}

 


내장 WAS에 HTTPS 적용하기

  1. 키스토어 만들기 (java의 keytool 명령어를 이용해서 로컬용 인증서 생성)
  2. application.properties에 ssl key store 정보 입력
//keytool 예시
keytool -genkey 
  -alias tomcat 
  -storetype PKCS12 
  -keyalg RSA 
  -keysize 2048 
  -keystore keystore.p12 
  -validity 4000
//application.properties 예시
server.ssl.key-store=keystore.p12
server.ssl.key-store-password=123456
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=tomcat

 

내장 톰캣 기본 설정 -> 모든 요청이 HTTPS 프로토콜로!

  • 내장 톰캣의 커넥터는 기본적으로 1개
  • 커넥터에 SSL을 적용하므로, 모든 요청은 https 프로토콜을 통해 전송
    1. 브라우저가 요청을 보낸다.
    2. 웹 서버는 응답과 함께 SSL인증서를 전송한다.
    3. 공인이 아닌 사설 인증서이므로, 브라우저는 인증서의 Public Key를 알아보지 못한다.
      (사설 인증서의 한계 -> 안전하지 않은 연결로 표시)

 

내장 톰캣 커넥터 1개 -> 커넥터를 추가해 http 요청을 받아보자!

  1. properties파일에 기본 포트 설정 ex. https 포트 443
  2. 메인 어플리케이션 클래스 내 커넥트 생성 메소드 구현 - http 프로토콜 커넥터 생성 / 포트 추가 / 커넥터 반환
  3. 메인 어플리케이션 클래스 내 서블릿웹서버팩토리 생성 메소드 구현 - TomcatServletWebServerFactory를 생성하고, 2번 메소드를 통해 커넥터를 붙이고, 반환하는 메소드 생성
  4. 3번 메소드가 @Bean으로 빈 컨테이너에 등록될 때 톰캣 커넥터 추가됨

 

내장 WAS에 HTTP2 프로토콜 적용하기

  • properties 파일에 server.http2.enabled=true 만 적어주면 OK

 

프로퍼티를 통한 HTTP2 적용의 유의점

  • WAS마다 제약사항이 다름
  • Tomcat 8.5 : 복잡한 추가설정 요구
  • Tomcat 9.0 + JDK9 : HTTPS만 적용되어 있으면 추가 설정 필요 없음
  • Undertow : HTTPS만 적용되어 있으면 추가 설정 필요없음

댓글