JAR(Java Archive), WAR(Web Application Archive)는 Java 애플리케이션을 패키징하는 두 가지 형식이다. 그렇다면 두 형식은 어떤 차이가 있을까?
WAR
웹 애플리케이션을 배포하는 데 사용되는 파일로 JAR는 JVM에서 실행된다면 WAR 파일은 WAS에서 실행된다.
WAR 파일은 정적 리소스, 클래스 파일을 모두 함께 포함하므로 JAR보다 복잡한 구조를 가진다.
WAR 파일의 구조는 다음과 같다.
- WEB-INF/: 웹 애플리케이션의 구성 파일과 비공개 리소스가 포함됩니다.
- classes : 실행 클래스 모음
- web.xml: 웹 애플리케이션의 배치 설명서.
- lib/: 애플리케이션에서 사용하는 JAR 파일.
- JSP, HTML, CSS 파일과 같은 리소스
즉 WEB-INF 폴더 하위는 자바 클래스와 라이브러리, 설정 정보가 포함되며 나머지 영역은 HTML, CSS 같은 정적 리소스가 포함된다.
하지만 WAR 배포를 위해서는 WAS를 연동하기 위한 복잡한 설정이 필요하고 배포를 위해 WAS를 별도로 설치해야 하는 번거로움이 있다.
JAR
Java 클래스나 라이브러리를 패키징을 하기 위한 표준 형식으로 클래스 파일, 메타 데이터(META-INF 디렉토리의 MANIFEST.MF 파일), 리소스 파일로 구성된다.
주로 JAR 파일은 JVM 위에서 직접 실행되거나 라이브러리로 제공된다.
JRE(JAVA Runtime Environment)가 있다면 java -jar filename.jar 명령어로 실행할 수 있다.
위처럼 직접 실행하는 경우 JAR 파일 내부엔 main() 메서드가 필요하고, MANIFEST.MF 파일에 실행할 메인 메서드가 있는 클래스를 지정한다.
JAR 파일의 구조는 다음과 같다.
- META-INF/
- MANIFEST.MF
- com/
- example/
- MyClass.class
- example/
- resources/
- config.properties
여기서 WAR와는 다르게 JAR 파일은 내부에 라이브러리 역할을 하는 JAR 파일이 없다는 것을 확인할 수 있다.
즉 JAR 파일은 다른 JAR파일을 포함할 수 없다는 한계가 있다.
Fat JAR
위 JAR 파일의 단점을 해결하기 위한 대안으로 fat jar(uber jar)라는 방법이 있다.
해당 방식은 jar를 풀면 나오는 자바 클래스들을 새로 만드는 jar에 모두 포함하는 방식이다.
수많은 라이브러리에서 나오는 자바 클래스를 모두 포함하므로 fat jar 라고 한다.
해당 방식은 하나의 jar 파일 안에 필요한 라이브러리들을 모두 내장할 수 있다는 장점이 있지만 여러 라이브러리에서 클래스명이 같은 파일이 존재할 경우 정상적으로 동작되지 않는다는 단점이 있다.
스프링 부트 JAR
스프링 부트를 사용해서 JAR 파일로 빌드한다면 위 문제를 모두 해결할 수 있다.
→ 스프링 부트의 플러그인을 사용하면 실행 가능한 JAR를 빌드하기 때문
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.5'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
}
@SpringBootApplication
public class BootApplication {
public static void main(String[] args) {
SpringApplication.run(BootApplication.class, args);
}
}
위 코드는 스프링 부트를 통해 프로젝트를 생성할 때 실행 시킬 수 있는 메인 메서드이다.
해당 main() 메서드의 run()은 크게 2가지 기능을 한다.
- 스프링 컨테이너를 생성
- 내장 톰캣 생성
- 톰캣도 자바로 만들어져 있음
- 따라서 톰캣을 마치 하나의 라이브러리처럼 포함해서 사용
(스프링 부트는 spring-boot-starter-web의 라이브러리에서 내장 톰캣 기능을 지원)
따라서 WAR와는 다르게 복잡한 설정없이 배포가 가능하다.
스프링 부트의 JAR 구조는 다음과 같다.
- META-INF
- MANIFEST.MF
- org/springframework/boot/loader
- JarLauncher.class
- BOOT-INF
- classes : 우리가 개발한 class 파일과 리소스 파일
- lib : 외부 라이브러리
- classpath.idx : 외부 라이브러리 경로
- layers.idx: 스프링 부트 구조 경로
위에서 설명한 JAR 구조와는 약간 다른 것을 확인할 수 있다.
보통 JAR 파일을 실행하면 메타 데이터가 있는 MANIFEST.MF 파일에서 main() 메서드가 있는 클래스를 찾고 실행한다.
하지만 스프링 부트가 생성한 MANIFEST.MF에는 Main-Class로 JarLauncher 라는 클래스를 실행한다.
해당 클래스는 스프링 부트 로더(org/springframework/boot/loader 하위에 있는 클래스)로 스프링 부트가 제공하는 실행 가능 Jar를 실제로 구동시키는 클래스들이 포함되어 있다.
즉 JarLauncher를 통해 BOOT-INF 하위의 classes, lib에 있는 다른 jar를 읽어들인다.
읽어들인 후 MANIFEST.MF 파일에 Start-Class: hello.boot.BootApplication 를 읽어들여 실제 프로젝트의 main()을 호출한다.
이러한 JAR를 실행 가능 Jar(Executable Jar)라 하며 스프링 부트는 실행 가능 Jar를 통해 여러 라이브러리를 하나의 jar에 포함할 수 있고 배포 또한 쉽게 할 수 있도록 지원한다.
참고
스프링 부트 - 핵심 원리와 활용 강의 | 김영한 - 인프런
김영한 | 실무에 필요한 스프링 부트는 이 강의 하나로 모두 정리해드립니다., 백엔드 개발자를 위한 스프링 부트 끝판왕! 실무에 필요한 내용을 모두 담았습니다. [임베딩 영상] 김영한의 스
www.inflearn.com
'Spring' 카테고리의 다른 글
[Spring] 외부 설정, @Profile (0) | 2024.12.28 |
---|---|
[Spring] Auto Configuration (0) | 2024.12.28 |
[Spring AOP] @Aspect AOP (0) | 2024.12.28 |
[Spring AOP] 스프링 AOP와 용어 (0) | 2024.12.28 |
[Spring AOP] 빈 후처리기 (0) | 2024.12.28 |