본문 바로가기
공부/프로그래밍

[gradle] intellij 에서 gradle을 이용해 runnable jar 만들기

by demonic_ 2021. 10. 22.
반응형

jar를 만드는 방법은 두가지가 있다.

 

1) gradle 에 설정한 뒤, tasks -> jar 를 실행하여 만드는 방법

2) intellij 프로젝트 Settings 에서 artifacts를 등록하여 만드는 방법

 

2번의 경우 새로운 Intellij 환경마다 지정해야하는 번거로움이 있다. 때문에 gradle에 등록함으로써 어느 컴퓨터의 어느 Intellij 환경에서도 작동할 수 있도록 하는게 목표다.

 

 

build.gradle 파일을 열어보면 다음처럼 기본으로 구성되어 있을 것이다

plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    ... 필요한 library 추가

    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}

test {
    useJUnitPlatform()
}

 

그리고 메인클래스가 com.test.gradle.AppStart 라는 클래스 내에 있다고 해보자.

public class AppStart {
    public static void main(String[] args) {
        System.out.println("================== 어플리케이션 시작");
    }
}

 

Runnable jar를 만들기 위해서는 메인클래스를 등록해줘야 한다.

build.gradle 파일에 다음을 설정한다.

...
jar {
    manifest {
        attributes 'Main-Class': 'com.test.gradle.AppStart'
    }
}

 

이제 gradle tasks 에 jar를 실행해보자

생성된 jar 파일이 build -> libs -> [이름].jar 로 생성되어 있을 것이다.

 

빌드된 경로를 보면 파일이 생성됨을 확인할 수 있다

 

jar를 실행해보면 다음처럼 로그가 보인다

& [프로젝트 경로]/build/libs  ls -al
total 21680
drwxr-xr-x  3 dgpark  staff        96 10 21 07:32 .
drwxr-xr-x  6 dgpark  staff       192 10 21 07:31 ..
-rw-r--r--  1 dgpark  staff  10243752 10 21 07:32 test-gradle-v1-1.0-SNAPSHOT.jar

 

jar를 실행해보면 Main 클래스에 설정한 로그가 보인다

& java -jar test-gradle-v1-1.0-SNAPSHOT.jar
================== 어플리케이션 시작

 

한가지 문제는 이 jar에는 gradle 에서 의존성으로 설정한 라이브러리들이 포함되어 있지 않다는 것이다.

 

그래서 이번엔 의존성이 연결된 파일들을 포함되게 설정하려 한다

build.gradle 파일을 열어 from 구절을 추가한다

참고로 여기서 설정은 gradle 7.x 버전이고, 다른 버전에선 다른 방법으로 설정하는 듯 하다

jar {
    manifest {
        attributes 'Main-Class': 'com.test.gradle.AppStart'
    }
    // 이 부분 추가
    from {
        configurations.runtimeClasspath.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
}

만약 위 설정이 안된다면 다음으로 수정해보자

jar {
    manifest {
        attributes 'Main-Class': 'com.test.gradle.AppStart'
    }
    // 이 부분 추가
    from {
        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
}

 

 

이제 다시 tasks -> jar 를 다시 실행해보자.

다음의 에러가 발생할 것이다.

Execution failed for task ':jar'.
> Entry META-INF/LICENSE.txt is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/7.1/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

 

 

라이브러리끼리 동일한 이름의 파일이 추가되어 중복문제가 발생해 생긴 문제다.

다음 설정을 통해 중복파일은 제외하는 것을 추가한다.

jar {
    manifest {
        attributes 'Main-Class': 'com.test.gradle.AppStart'
    }
    from {
        configurations.runtimeClasspath.collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
    // 이 부분 추가
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

 

jar 압축을 풀어보면 다음처럼 구성되어 있다.

 

추가한 라이브러리들이 [라이브러리 명].jar 형태가 아닌 각각의 압축이 모두 풀려 하나의 폴더를 구성하고 있다.

 

마찬가지로 실행하면 잘 작동한다.

& java -jar test-gradle-v1-1.0-SNAPSHOT.jar
================== 어플리케이션 시작

 

 

 

끝.

 

반응형

댓글