자바 애플리케이션을 배포하다보면 항상 .jar라는 확장자를 마주하게 됩니다.
또한 .zip은 정말 많이 사용했기 때문에 익숙할것이라 생각합니다.
.zip파일은 하나의 파일 안에 여러 개의 파일이 들어 있는 파일이며, 이러한 형태를 아카이브(archive)라고 합니다. zip archive
는 여러 파일을 하나의 파일로 편리하게 다루고 보관할 수 있으며 더하여 압축까지 해주어 실제 아카이브들의 각 용량의 합보다 zip 파일의 용량이 더 작아지게 됩니다.
jar 파일은 Java에서 사용되는 특정 유형의 아카이브입니다. 이 또한 여러 파일이 포함된 단일 파일이며 가장 중요한 부분은 파일들은 컴파일된 .class
파일입니다.
결국 jar 파일에는 컴파일된 코드가 포함되어 있으므로 두 가지 방식으로 이를 이용할 수 있게 됩니다.
Java 애플리케이션을 실행할 때 클래스 경로에 jar 파일을 추가하여 안에 포함된 모든 코드를 현재 애플리케이션에서 사용할 수 있다.
jar 파일 자체를 실행 가능한 애플리케이션이되며 이를 실행할 수 있습니다.
결국 jar파일은 Java 코드의 편리한 컨테이너의 역할을 하며 zip과 같이 동일한 방식으로 압축된다.
또한 jar파일은 단일 파일에 코드를 저장하므로 Java library를 jar 형식으로 쉽게 배포할 수 있습니다. 실제로 gradle, maven을 통한 프로젝트의 의존성을 다운로드 받게되면 수많은 jar파일들이 의존성에 포함됨을 알 수 있습니다.
특정 jar 파일을 살펴보면 항상 META-INF 폴더가 포함되는것을 알 수 있습니다.
이는 메타데이터 파일이 저장되는 경로입니다. MANIFEST.MF라는 파일도 볼 수 있는데 이는 패키지 관련 데이터를 정의하는데 중요한 key/value 데이터를 포함하고 있습니다.
예시
Main-Class
: jar 파일 실행시 실행해야 하는 클래스들을 지정Manifest-Version
: 사용 중인 특정 매니페스트 파일 형식을 설명한다.Manifest file이란?
jar 파일에 패키징된 파일에 대한 정보를 포함할 수 있는 특수 파일이며 파일에 포함된 메타 정보를 가지고 jar 파일을 다양한 용도로 사용할 수 있다. 매니페스트 파일은 주로 패키지의 다양한 클래스 중 주요 기능을 보유한 클래스의 이름을 포함한다.또한 jar 파일과 파일에 포함된 클래스에 대한 메타데이터를 보관하고 출처 추적, 변조 방지, 실행 가능한 jar에 필요한 추가 정보 제공에 목적이 있다.
.zip과 .jar의 유사성
jar와 zip은 동일한 보관 및 압축 기술을 사용한다. jar 파일은 특정 유형의 zip 파일이라고 생각하면 된다.
기본적인 방법으로 jar 파일은 JDK에 포함된 jar 명령을 통해 만들 수 있다.
$ jar --create --file my-amazing-application.jar -C build/classes/java/main/ .
--create
: jar도구에 jar 파일을 생성할 것을 알려준다.--file
: 생성된 jar 파일의 이름을 지정한다.-C
: 클래스를 찾을 디렉토리를 설정함.
은 해당 경로의 모든 클래스를 지칭합니다.다음과 같이 Hello.java
를 생성하고 .jar 파일을 만들어 보겠습니다.
Hello.java 컴파일 및 실행하기
jar는 .class 파일의 집합이므로 우선 .java 파일을 수동으로 컴파일해 .class 파일을 생성해야 합니다. 정상적으로 컴파일 및 실행됨을 알 수 있습니다.
jar 파일 생성
현재 경로의 클래스에서 Hello.class
대해 Hello.jar라는 이름의 파일을 생성하도록 명령하면 위와 같이 생성됨을 알 수 있습니다.
MANIFEST.MF 확인 및 jar 실행 하기
Hello.jar를 /unzip 경로에 압축을 풀면 다음과 같습니다.
MANIFEST.MF를 확인하면 다음과 같은 정보가 들어있습니다.
이제 다시 Hello.jar로 돌아가 해당 jar파일을 실행하게 되면 Hello World!의 출력이 예상되지만 오류가 발생합니다.
MANIFEST.MF에 Main-Class 속성의 부재
MANIFEST.MF에는 Java가 실행할 Main-Class
의 정보가 포함되어야 합니다. 하지만 위에서 확인했듯이 Main-Class의 정보가 들어있지 않습니다. 따라서 --main-class
옵션을 통해 Main-Class를 Hello.class
로 지정하고 다시 jar 파일을 생성합니다.
다시 MAINFEST.MF를 확인해보면 Main-Class 속성이 포함됨을 알 수 있습니다.(이때 Main-Class 속성에는 .class 확장자를 제외해야 합니다.
)
jar와 zip의 차이를 간단하게 알아보고 jar만의 차이점을 배울 수 있었습니다.
애플리케이션을 배포하는 단계에서 jar 파일을 다루는 일이 많은데 두루뭉실했던 jar파일에 대해 조금은 이해할 수 있었던 시간이었습니다.