JAR 파일 실행 명령어
java -jar ossapp.jar
JAR 실행과정
1. JVM(Java Vitual Machine) 실행
- java -jar ossapp.jar 명령어를 입력하면, JVM이 실행됨
2. JAR 파일 해석 & 압축 해제(Mainfest 파일 확인)
- JVM은 JAR 내부의 META-INF/MANIFEST.MF에서 Main-Class를 확인하고, 애플리케이션의 시작업을 찾는다.
- 일반 JAR : Main-Class에 지정된 main() 메서드를 실행
- Spring Boot JAR : JarLauncher가 먼저 실행되고, Start-Class로 지정된 클래스를 찾아 실행
3. 클래스 로드 & 클래스 로더 동작
- JVM은 Main-Class의 main() 메서드를 실행하기 위해 ClassLoader를 사용하여 .class 파일을 메모리에 로드함
- 일반 JAR : AppClassLoader가 Main-Class를 로드하고 실행함
- Spring Boot JAR : LaunchedURLClassLoader가 Fat JAR(애플리케이션의 실행에 필요한 모든 클래스 및 의존 라이브러리를 하나의 JAR 파일에 포함) 내부의 라이브러리와 클래스를 동적으로 로드함
4. main() 메서드 실행
- Spring Boot JAR의 경우, main() 메서드가 실행되면서 내장 웹 서버(Tomcat/Jetty)가 시작되거나 Spring Context가 초기화
5. 프로그램 실행 & 종료
일반 JAR vs Spring Boot JAR
일반 Java JAR | Spring Boot Jar(Fat JAR) | |
실행 명령어 | java -jar ossapp.jar (외부 라이브러리를 사용한다면 별도 지정 필요) |
java -jar ossapp.jar |
Main-Class | com.example.MainApplication | org.springframework.boot.loader.JarLauncher |
의존성 관리 | classpath로 관리 | Fat JAR로 내부에 포함 |
내장 웹 서버 | 없음 | Tomcat/Jetty 포함 가능 |
실행 방식 | JVM이 직업 Main-Class 실행 | JarLauncher가 Start-Class 실행 |
일반 JAR 예제
- 프로젝트가 여러 개의 외부 라이브러리를 사용했더라도, 빌드 시 ossapp.jar 하나만 만들어짐
- 의존성을 따로 지정해야함
JAR 빌드
javac -cp "libs/*" MainApplication.java
jar cf ossapp.jar com/example/MainApplication.class
실행
java -cp "libs/*:ossapp.jar" com.example/MainApplication
Spring Boot JAR(Fat JAR)
- Spring Boot는 Fat JAR을 기본적으로 생성함
- 실행에 필요한 Spring Boot 라이브러리, 애플리케이션 코드, 의존성, JAR 모두 포함됨
- java -jar build/libs/springBootTest-0.0.1-SNAPSHOT.jar 한줄로 실행 가능
Fat JAR 빌드(Gradle)
./gradlew build
실행
java -jar build/libs/springBootTest-0.0.1-SNAPSHOT.jar --server.port:9911
Spring Boot Fat JAR 내부구조
- BOOT-INF/lib/에 모든 라이브러리가 포함되므로, 추가적인 classpath 설정 없이 실행 가능
springBootTest-0.0.1-SNAPSHOT.jar
├── META-INF/
├── BOOT-INF/ <== Spring Boot의 실행 파일 영역
│ ├── classes/ <== 애플리케이션의 클래스 파일
│ ├── lib/ <== 모든 의존성 JAR 포함됨
│ └── layers.idx (Spring Boot Layered JAR)
├── org/springframework/boot/loader/ <== Spring Boot의 실행 로더 (JarLauncher)
└── META-INF/MANIFEST.MF <== 실행할 `Start-Class` 지정
Fat JAR을 사용하는 이유
- JAR 하나만 있으면 실행이 가능하므로 배포가 간편함
- 추가 라이브러리 설치 없이 독립적인 실행 환경 제공
- 따른 웹 서버를 설치하지 않아도 Spring Boot 내장 톰캣 지원
gradlew(Gradle Wrapper)
- Gradle이 설치되어 있지 않아도 프로젝트에서 Gradle을 실행할 수 있도록 도와주는 스크립트 파일
- 프로젝트 내부에 있는 특정 버전의 Gradle을 자동으로 다운로드하고 실행하는 역할
Gradle Wrapper(gradlew) | Gradle(gradle) | |
설치 필요 여부 | 별도 설치 필요 없음 | 시스템에 Gradle 설치 필요 |
버전 고정 가능 | 프로젝트 내에서 특정 Gradle 버전 유지 | 시스템에 설치된 버전 사용 |
실행 방식 | ./gradlew [task] | gradle [task] |
(./gradlew)bootJar vs (./gradlew)build
- 둘 다 JAR 파일을 생성하지만, 동작 방식이 다름
1. ./gradlew bootJar (Spring Boot 실행 가능한 JAR 생성)
- Spring Boot에서 실행 가능한 Fat JAR을 생성하는 TASK
- 내부적으로 의존성을 포함한 실행 가능한 JAR이 만들어짐
2. ./gradlew build (일반적인 빌드)
- build TASK는 전체 프로젝트를 빌드하는 작업을 수행
- bootJar를 포함해서, 필요하면 test도 실행하고 JAR을 생성
- 즉, ./gradlew build 실행 시 내부적으로 bootJar도 실행됨
Gradle 기타설정..
ext가 Gradle파일 맨 위에 있으면 안되는 이유
- Gradle 스크립트(build.gardle.kts 또는 build.gradle)은 다음과 같은 실행순서를 따른다.
- 플러그인(plugins{} 또는 apply plugin)이 먼저 로드
- 프로젝트 관련 속성(grop, version, repositories, dependencies)이 설정
- 빌드 테스크(bootJar, jar 등)가 설정
- 빌드 실행(gradlew build 등)
- 그래서 ext 속성을 Gradle 파일의 최상단에 두면, 아직 프로젝트 객체가 로드되기 전에 선언되어 오류가 발생한다.
-> ext 속성은 plugins {} 이후에 배치해야함 - Groovy DSL에서 "(더블 쿼테이션)은 변수치환을 하고 '(싱클 쿼테이션)은 변수치환을 하지 않는다.
build.gradle 예제
ext {
appName = 'ossapp'
appVersion = '2.0.0'
}
bootJar {
archiveBaseName = appName // 기본 이름
archiveVersion = appVersion // 버전 (기본값: build.gradle의 version 속성)
archiveClassifier = 'release' // 추가 라벨 (예: beta, release)
}
jar {
archiveBaseName = "${appName}-lib"
archiveVersion = appVersion
}
build 결과물

'백엔드 면접준비 > Java' 카테고리의 다른 글
객체지향 (0) | 2025.03.19 |
---|---|
JAVA 기본 (1) | 2025.03.16 |
7. 동기,비동기, 블로킹, 논블록킹 (1) | 2025.03.08 |
6. Garbage Collection(GC) (1) | 2025.03.07 |
4. Java Annotation (0) | 2025.03.07 |