티스토리 뷰

과거에는 톰캣 같은 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-Classcom.hyuuny.boot.BootApplication가 아니라 JarLauncher인 이유는 스프링 부트는 jar 내부에 jar를 읽어들이는 기능이 필요하다. 또 특별한 구조에 맞게 클래스 정보도 읽어들여야 한다. 바로 JarLauncher가 이런 일을 처리한 다음 Start-Class:에 지정된 main()을 호출한다.


실행 과정

  1. java -jar xxx.jar
  2. MANIFEST.MF 인식
  3. JarLauncher.main() 실행
    3-1. BOOT-INF/classes/ 인식
    3-2. BOOT-INF/lib/ 인식
  4. BootApplication.main() 실행



Reference

김영한. 스프링 부트 - 핵심 원리와 활용. 인프런.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함