본문 바로가기

더 나은 엔지니어가 되기 위해/지금은 안쓰는 자바

[스프링 부트 개념과 활용] 내장 웹서버 이해와 .JAR 생성

이 글은 인프런에서 백기선님의 스프링부트 개념과 활용 강의를 듣고, 개인적으로 공부하며 핵심만 정리한 글입니다.

내장 웹 서버 이해

스프링 부트는 서버가 아니다.
스프링 부트의 자동 설정에, 톰캣의 설정과 구동이 포함되어 있다.

외부 라이브러리로 포함된 org.springframework.boot.autoconfigure.web.servlet 에서 ServletWebServerFactoryAutoConfiguration.java 를 열어보면,

...

@Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class})

...

위와 같이 내장 Tomcat 을 사용할지, Jetty 를 사용할지, Undertow 를 사용할 지에 대한 설정이 있음.

또 이번에는 org.springframework.boot.web.embedded.tomcat 에서 TomcatServletWebServerFactory.java 를 열어보면,

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);
  connector.setThrowOnFailure(true);
  tomcat.getService().addConnector(connector);
  this.customizeConnector(connector);
  tomcat.setConnector(connector);
  tomcat.getHost().setAutoDeploy(false);
  ...

위와 같이 톰캣을 생성하고, 서블릿 및 디스패처 설정 등을 하는 코드가 있음.

즉, 자동 설정 안에 톰캣과 서블릿 등 웹 서버 기본 설정들이 포함되어 있음.

내장 웹 서버 응용

스프링 부트 공식 도큐먼트를 보면 다음과 같이 내장 웹 서버 설정을 바꾸는 일을 할 수 있음.

1) 내장 웹 서버 변경

spring-boot-starter-web 에 기본 내장된 Tomcat 을 Jetty 로 바꾸려면, pom.xml 에서 다음 부분만 수정하면 된다.

<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>

만약 어떤 웹 서버도 사용하고 싶지 않으면 resources/application.properties 에 다음을 추가해주면 된다.

spring.main.web-application-type=none

2) 포트 변경

마찬가지로 resources/application.properties 에 다음을 추가해주면 된다.

server.port=7070 // 7070 포트로 변경
server.port=0    // 랜덤 포트로 변경

3) HTTPS 적용

Mac 의 경우 keytool 로 인증키를 생성할 수 있다.
다음 명령어를 입력하면

keytool -genkey -alias spring -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 4000

Enter keystore password: 123456
Re-enter new password: 123456
What is your first and last name?
  [Unknown]:  heumsi
What is the name of your organizational unit?
  [Unknown]:  heumsi
What is the name of your organization?
  [Unknown]:  heumsi
What is the name of your City or Locality?
  [Unknown]:  heumsi
What is the name of your State or Province?
  [Unknown]:  heumsi
What is the two-letter country code for this unit?
  [Unknown]:  heumsi
Is CN=heumsi, OU=heumsi, O=heumsi, L=heumsi, ST=heumsi, C=heumsi correct?
  [no]: yes

keystore.p12 라는 파일이 생기는데, 이를 프로젝트 경로 (최상단 경로) 에 두자.
그리고 resources/application.properties 에 다음을 추가해준다.

server.ssl.key-store=keystore.p12
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=123456
server.ssl.key-alias=spring

이제 Application.java 를 구동하면, https 로만 접근이 가능하다.

4) HTTP2 적용

해당 내용은 스킵.

독립적으로 실행 가능한 JAR

스프링부트는 이렇게 작성한 코드를 하나의 .jar 파일로 묶고, 이 하나의 파일을 그냥 실행만 하면 해당 프로젝트 코드 전체가 돌아가게 한다.

먼저, pom.xml 을 보면 build 에 다음과 같은 코드가 있다.

<!-- Package as an executable jar -->
<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>

spring-boot-maven-plugin 이라는 스프링 부트 자체 메이븐 플러그인 인데, 바로 이 플러그인이 mvn package 실행 시 해당 메이븐 프로젝트를 하나의 .jar 파일로 묶어주는 역할을 한다.

만들어진 .jar 파일은 target/ 디렉토리 안에 webservershowcase-1.0-SNAPSHOT.jar 와 같은 이름으로 존재한다.
unzip -t webservershowcase-1.0-SNAPSHOT.jar 를 하면 이 .jar 파일이 풀리는데 이 안에 프로젝트에 들어간 모든 파일과 코드들(외부 라이브러리를 포함한)이 들어가있음을 확인할 수 있다.
여기서

  • org.springframework.boot.loader.jar.JarFile 가 내장 .jar 파일들, 즉 외부 라이브러리 파일들을 읽고
  • org.springframework.boot.loader.Launcher 가 이 .jar 실행한다.