개발이군고구마

build gradle의 상세 과정 본문

SERVER/Java

build gradle의 상세 과정

김구황 2026. 5. 13. 07:40
728x90

 

1. 전체 흐름

 

2. 1단계 : JVM — "Write Once, Run Anywhere"의 비밀

 

Java 코드는 **컴파일하면 .class 파일(바이트코드)**

이 바이트코드는 특정 OS의 언어가 아니라 JVM만 이해하는 중간 언어

서버에 JVM(Java가 설치된 것)만 있으면, 어디서든 같은 JAR 파일을 실행할 수 있는 이유

 

3. 2단계: Gradle이 하는 일

Gradle이 ./gradlew build 명령 하나로 이 4단계를 순서대로 자동 처리

특히 ④ 패키징 단계가 핵심인데, 여기서 만들어지는 것이 바로 "Fat JAR" 또는 "Executable JAR"

 

4. 3단계: JAR 파일 안에 뭐가 들어있나?

app.jar 내부 구조 (사실 zip 파일!) 

JAR 파일의 핵심은 MANIFEST.MF.

이 안에 Main-Class: com.example.App이라고 적혀 있어서, JVM이 "어디서부터 시작해야 하는지"를 알 수 있음

java -jar app.jar  =  "JVM아, 이 JAR 열어서 MANIFEST 읽고 Main-Class 실행해"라는 뜻.

 

요약 : 

  1. 소스코드 .java → Gradle이 javac로 컴파일 → 바이트코드 .class
  2. .class + 라이브러리 + 설정 → Gradle이 하나로 묶음 → app.jar
  3. app.jar → S3에 업로드 → 서버에서 다운로드
  4. 서버에서 java -jar app.jar → JVM이 시작 → MANIFEST 읽어서 main() 실행 → 서버 프로세스 시작!

 

5. MANIFEST.MF?

MANIFEST.MF는 JAR 파일의 "설명서 첫 페이지". 책으로 치면 "1장은 몇 페이지부터 시작합니다"라고 적힌 목차 같은 것.

Main-Class가 없으면 JVM 입장에서는 수백 개의 .class 파일 중 어디서 시작해야 할지 알 방법이 전혀 없음.

그래서  Main-Class가 없으면 java -jar가 아예 실행이 안 됨.

 

 

java -jar 실행 시 JVM이 MANIFEST.MF를 읽는 과정을 단계별로 설명하는 인터랙티브 설명

1단계: 명령어 입력
2단계: JAR 탐색
3단계: MANIFEST 읽기
4단계: main() 호출
5단계: 결과
 
터미널 입력
사용자가 명령어를 입력
$ java -jar app.jar
이 명령어는 사실 세 가지 정보를 JVM에 전달해요.

java → JVM을 시작해
-jar → 이 JAR 파일을 실행 모드로 열어
app.jar → 이 파일이야

-jar 플래그가 핵심이에요. 이게 있어야 JVM이 "MANIFEST.MF를 읽어서 Main-Class를 찾아야겠다"고 결정해요.
JVM 내부 동작
JAR를 열어 META-INF 폴더 탐색
app.jar (사실 zip 파일)
├── META-INF/
│ └── MANIFEST.MF ← JVM이 제일 먼저 여기 옴
├── com/
│ └── example/
│ └── App.class
└── BOOT-INF/
└── lib/ (라이브러리들)
JAR는 실제로 zip 압축 파일이에요. JVM은 -jar 옵션을 보는 순간, 가장 먼저 META-INF/MANIFEST.MF 경로로 직행해요. 다른 파일은 아직 건드리지 않아요.
MANIFEST.MF 읽기
Main-Class 항목을 찾아 읽음
Manifest-Version: 1.0
Main-Class: com.example.App ← 이것만 있으면 됨
Spring-Boot-Version: 3.2.0
Build-Jdk: 17.0.8
JVM은 이 파일을 한 줄씩 읽으면서 Main-Class:로 시작하는 줄을 찾아요. 찾는 순간 com.example.App이라는 문자열을 메모리에 저장하고 다음 단계로 넘어가요.

나머지 줄들(Spring-Boot-Version, Build-Jdk 등)은 참고 정보일 뿐, JVM 실행에는 영향을 주지 않아요.
클래스 로딩
App.class를 로드하고 main() 호출
// com/example/App.class 안에 이런 메서드가 반드시 있어야 함

public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
JVM은 com.example.App 클래스를 JAR에서 꺼내 로드한 다음, 정확히 이 시그니처를 가진 메서드를 찾아요.

public static void main(String[] args)

이 4개 키워드가 하나라도 다르면 실행 실패예요. JVM이 약속한 "진입점 계약"이거든요.
성공 케이스
Main-Class가 있고 main()도 있을 때
. ____ _
/\\ / ___'_ __ _ _(_)
( ( )\___ | '_ | '_| |
\\/ ___)| |_)| | | |
' |____| .__|_| |_|
:: Spring Boot ::

Started App in 2.341 seconds
서버가 포트를 열고 요청 대기 시작!
실패 케이스
Main-Class가 없을 때
no main manifest attribute,
in app.jar
해결법: build.gradle에
mainClass = 'com.example.App'
추가 후 재빌드
← 이전 1 / 5 2 / 5 3 / 5 4 / 5 5 / 5 다음 →