-
Spring Boot 핵심 기능 1 - 내장 톰캣BackEnd/Spring Boot 2023. 3. 25. 11:30반응형
이전에는 웹 애플리케이션을 구동하고 싶으면 웹 애플리케이션 서버(WAS)를 별도로 설치하고, 웹 애플리케이션 빌드 파일(WAR)을 배포해야 했습니다.
WAR 배포 방식의 단점
- 톰캣 같은 WAS를 별도로 설치해야 합니다.
- 개발 환경 설정이 복잡합니다.
- 배포 과정이 복잡합니다.
- 톰캣의 버전을 변경하려면 톰캣을 다시 설치해야 합니다.
이런 문제를 해결하기 위해 톰캣을 라이브러리로 제공하는 내장 톰캣(embed tomcat) 기능을 제공합니다.
외장 서버 vs 내장 서버
- 외장 서버: 웹 애플리케이션 서버에 WAR 파일을 배포하는 방식으로 WAS를 실행해서 동작합니다.
- 내장 서버: 애플리케이션 JAR 안에 다양한 라이브러리들과 WAS 라이브러리가 포함되는 방식으로 main() 메서드를 실행해서 동작합니다.
스프링 부트와 웹 서버
스프링 부트는 내장 톰캣을 사용해서 빌드와 배포를 편리하게 해주며, 빌드 시 하나의 Jar를 사용합니다. spring-boot-starter-web를 사용하면 내부에서 내장 톰캣을 사용합니다. 라이브러리 의존 관계를 따라가보면 내장 톰캣(tomcat-embed-core)이 포함된 것을 확인할 수 있습니다.
스프링 부트와 웹 서버 실행 과정
package hello.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class BootApplication { public static void main(String[] args) { SpringApplication.run(BootApplication.class, args); } }
- 스프링 부트를 실행할 때는 자바 main() 메서드에서 SpringApplication.run()을 호출해주면 됩니다.
- 여기에 메인 설정 정보를 넘겨주는데, 보통 @SpringBootApplication 애노테이션이 있는 현재 클래스를 지정해주면 됩니다.
- @SpringBootApplication 애노테이션 안에는 컴포넌트 스캔을 포함한 여러 기능이 설정되어 있는데, 기본 설정은 현재 패키지와 그 하위 패키지 모두를 컴포넌트 스캔합니다.
단순해 보이는 코드 한줄 안에는 수 많은 일들이 발생하지만 핵심은 2가지 입니다.
- 스프링 컨테이너 생성
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContextFactory
- WAS(내장 톰캣) 생성
org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory
스프링 부트와 웹서버 빌드와 배포
내장 톰캣이 포함된 스프링 부트를 빌드하면 build/libs/boot-0.0.1-SNAPSHOT.jar 파일이 만들어집니다.
[jar 빌드]: ./gradlew clean build [Window OS]: gradlew clean build
jar 파일이 있는 폴더로 이동 후 다음 명령어로 jar 파일을 실행하면 스프링 부트 애플리케이션이 실행됩니다.
java -jar boot-0.0.1-SNAPSHOT.jar
Note. 빌드 결과를 보면 boot-0.0.1-SNAPSHOT-plain.jar 파일도 보이는데, 이것은 우리가 개발한 코드만 순수한 jar로 빌드한 것입니다.
스프링 부트 jar 분석
build/libs 폴더로 이동하여 다음 명령어를 사용해서 압축을 풉니다.
jar -xvf boot-0.0.1-SNAPSHOT.jar
Note. WAR와 다르게 JAR 파일은 내부에 라이브러리 역할을 하는 JAR 파일을 포함할 수 없습니다. 포함한다고 해도 인식이 되지 않습니다(JAR 파일 스펙의 한계). 대안으로 Fat Jar가 있으나 어떤 라이브러리가 포함되어 있는지 확인하기 어려우며, 파일명 중복을 해결할 수 없습니다. 스프링 부트는 이런 문제를 해결하기 위해 jar 내부에 jar를 포함할 수 있는 특별한 구조의 jar를 만들고 동시에 만든 jar를 내부 jar를 포함해서 실행할 수 있게 합니다. 이것을 실행 가능 Jar(Executable Jar)라고 합니다.
Jar 실행 정보
[META-INF/MANIFEST.MF]
Manifest-Version: 1.0 Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: hello.boot.BootApplication Spring-Boot-Version: 3.0.2 Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx Spring-Boot-Layers-Index: BOOT-INF/layers.idx Build-Jdk-Spec: 17
- java -jar xxx.jar를 실행하게 되면 우선 META-INF/MANIFEST.MF 파일을 찾습니다.
- Main-Class가 JarLauncher를 실행합니다. JarLauncher는 스프링 부트가 빌드 시에 넣어주며, org/springframework/boot/loader/JarLauncher에 포함되어 있습니다(스프링 부트는 jar 내부에 jar를 읽어들이는 기능이 필요하며, 특별한 구조에 맞게 클래스 정보도 읽어들여야 하는데 이런 일을 JarLauncher가 처리합니다).
- Start-Class에 지정된 main() 메서드를 호출합니다.
Note. Main-Class를 제외한 나머지는 자바 표준이 아닙니다. 스프링 부트가 임의로 사용하는 정보입니다.
Note. 실행 가능 Jar가 아니라, IDE에서 직접 실행할 때는 BootApplication.main()을 바로 실행합니다. IDE가 필요한 라이브러리를 모두 인식할 수 있게 도와주기 때문에 JarLauncher가 필요하지 않습니다.
[참고정보]
반응형'BackEnd > Spring Boot' 카테고리의 다른 글
Spring Boot 핵심 기능 3 - 자동 구성(Auto Configuration) (0) 2023.04.20 Spring Boot 핵심 기능 2 - 라이브러리 관리 (0) 2023.04.19 REST API (0) 2022.05.25 HAL Browser (0) 2022.05.25 Actuator (0) 2022.05.20