티스토리 뷰
과거에는 톰캣 같은 WAS를 별도로 설치하고, IDE에 복잡한 설정을 거쳐 개발이 완료된 코드를 WAR로 만들고 이것을 또 WAS에 전달해서 배포하는 과정이 필요했다. 하지만 스프링 부트는 WAS가 라이브러리로 jar 내부에 포함되어 있기 때문에 복잡한 설정이 필요 없고, 배포는 JAR로 만들어서 원하는 위치에서 실행하기만 하면 된다.
간단한 프로젝트를 통해 스프링 부트가 어떻게 톰캣 서버를 내장해서 실행하는지 알아보자!
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.2'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'com.hyuuny.boot'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
spring-boot-starter-web
를 사용하면 내부에서 내장 톰캣을 사용한다.- 스프링 부트는 현재 부트 버전에 가장 적절한 외부 라이브러리 버전을 자동으로 선택해준다.
- 라이브러리 의존관계를 확인해보면 내장 톰캣(tomcat-embed-core)이 포함된 것을 확인할 수 있다.
스프링 부트 실행 과정
package com.hyuuny.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
애노테이션이 있는데, 이 애노테이션 안에는@ComponentScan
을 포함한 여러 기능이 설정되어 있다. 기본 설정은 현재 패키지(com.hyuuny.boot)와 그 하위 패키지 모두를 컴포넌트 스캔한다.
SpringApplication.run(BootApplication.class, args);
코드 한 줄에서 수 많은 일들이 발생하지만, 핵심은 두 가지다.
- 스프링 컨테이너 생성
- WAS(내장 톰캣) 생성
스프링 부트 내부에서 스프링 컨테이너를 생성하는 코드 (ServletWebServerApplicationContextFactory)
new AnnotationConfigServletWebServerApplicationContext()
: 스프링 부트가 생성하는 스프링 컨테이너- 이름 그대로 애노테이션 기반 설정이 가능하고, 서블릿 웹 서버를 지원하는 스프링 컨테이너이다.
스프링 부트 내부에서 내장 톰캣을 생성하는 코드 (TomcatServletWebServerFactory)
Tomcat tomcat = new Tomcat()
: 내장 톰캣 생성
다음으로 터미널을 이용해 프로젝트 폴더로 이동한 다음 ./gradlew build
명령으로 빌드하면, build/libs
폴더 밑에 jar 파일이 생성된다.
build/libs/boot-0.0.1-SNAPSHOT.jar
명령으로 jar 파일을 실행하면 정상적으로 스프링 부트 애플리케이션이 동작하는 것을 확인할 수 있다.
스프링 부트는 jar 내부에 jar를 포함할 수 있는 특별한 구조의 jar를 만들고, 동시에 만든 jar를 내부 jar를 포함해서 실행할 수 있게 했는데, 이것을 실행 가능 Jar(Executable Jar)라 한다.
META-INF/MANIFEST.MF
Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.hyuuny.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
를 읽어서 main()
메서드를 실행하게 된다.
Main-Class
가 com.hyuuny.boot.BootApplication
가 아니라 JarLauncher
인 이유는 스프링 부트는 jar 내부에 jar를 읽어들이는 기능이 필요하다. 또 특별한 구조에 맞게 클래스 정보도 읽어들여야 한다. 바로 JarLauncher
가 이런 일을 처리한 다음 Start-Class:
에 지정된 main()
을 호출한다.
실행 과정
- java -jar xxx.jar
- MANIFEST.MF 인식
- JarLauncher.main() 실행
3-1. BOOT-INF/classes/ 인식
3-2. BOOT-INF/lib/ 인식 - BootApplication.main() 실행
Reference
'Spring' 카테고리의 다른 글
[Spring] 외부설정과 프로필 1 (0) | 2023.04.02 |
---|---|
[Spring] build.gradle 라이브러리 관리 (0) | 2023.03.13 |
[Spring] WAR VS JAR (0) | 2023.03.10 |
[Spring] 트랜잭션 전파 옵션 REQUIRES_NEW를 사용해서 문제를 해결해보자 (0) | 2022.11.23 |
[Spring] 스프링 트랜잭션 전파 옵션 REQUIRES_NEW에 대해 알아보자 (0) | 2022.11.22 |
- Total
- Today
- Yesterday
- leetcode
- 김영한
- 코틀린
- 알고리즘
- 스프링 부트
- 백준
- 그리디
- 구현
- 노마드코더
- 정렬
- spring boot
- 파이썬
- 스프링
- 자료구조
- 인프런
- Algorithm
- kotlin
- mysql 8.0
- 코테
- Refactoring
- 문자열
- 데이터베이스
- 북클럽
- 리팩토링
- Spring
- 릿코드
- 노마드
- Real MySQL
- MySQL
- webflux
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |