• gradlew가 무엇인가?
    • Gradle Wrapper is a script that invokes a declared version of Gradle, downloading it beforehand if necessary.

 

Gradle이 maven보다 좋나?

  • https://docs.gradle.org/current/userguide/build_cache.html  
    • gradle은 빌드 정보 등을 캐싱 해두고 사용하기 때문에 성능 이점이 있음
  • gradle daemon을 띄워 두고, 여기서 Task를 수행하기 때문에 프로세스 띄우는 시간을 절약할 수 있음
    • 별도 설정 없는 경우 daemon은 2시간 동안 작업이 없으면 죽음

 

gradlew 명령어 종류 (build VS bootJar)

 

```

> Task :compileKotlin
> Task :compileJava NO-SOURCE
> Task :processResources
> Task :classes
> Task :bootJar

------ 여기까지가 bootJar 실행했을 때 ------
> Task :inspectClassesForKotlinIC
> Task :jar SKIPPED
> Task :assemble
> Task :compileTestKotlin
> Task :compileTestJava NO-SOURCE
> Task :processTestResources NO-SOURCE
> Task :testClasses UP-TO-DATE

> Task :test

> Task :check
> Task :build

------ 여기까지가 build 실행했을 때 ------

```

 

깃에 올려놓은 gradlew가 실행 권한이 없다고 permission error가 뜰 때

```bash

git update-index --chmod=+x gradlew

```

 

IntelliJ에서 사용할 때

  • https://www.jetbrains.com/help/idea/gradle.html
  • The recommended way to execute any Gradle build is with the help of the Gradle Wrapper.
    • Gradle Wrapper를 쓰는게 기본 설정으로 되어 있고, 프로젝트 마다 독립적인 Gradle을 자동으로 내려받고 실행하기 때문에 Gradle version으로 인한 문제를 피할 수 있음.
    • 어떤 버전을 내려받을지는 `` gradle-wrapper.properties ``에 명시.

 

자주 뜨는 에러

```

Could not determine Java version using executable

```

gradle 버전에 따라서 java -version 파싱에 문제가 있어 이런 에러가 뜰 수도 있는데, gradle-wrapper.properties에 명시된 gradle버전을 바꿔주어 새로운 버전을 내려받아 사용하도록 하면 해결됨. 

 

 

```

$ ./gradlew

오류: 기본 클래스 org.gradle.wrapper.GradleWrapperMain을(를) 찾거나 로드할 수 없습니다.

```

IntelliJ에서 빌드하면 default gradle wrapper를 사용하도록 설정해놓은 경우 아무 문제없이 실행이 되는데, 콘솔에서 직접 접근해서 실행하면 저런 오류가 발생한다. 이는 gradle-wrapper.jar가 없어서 발생하는 오류임.

 

이렇게 오류뜨면 로컬에 gradle 설치하고 gradle wrap 치면 ./gradle/wrapper/gradle-wrapper.jar 가 생성되면서 해결이 되기는 하는데... 문제는 로컬 gradle 버전에 맞게 gradle-wrapper.properties 파일이 수정돼버려서, 여러 프로젝트에서 각각 다른 gradle 버전을 사용하는 경우 커밋할 때 몹시 거슬린다...

 

IntelliJ가 default gradle wrapper라고 깔아놓은 gradle은 다음 경로에 있다.

```bash

$GRADLE_USER_HOME/wrapper/dists/gradle-<version>...

환경변수가 정의되어 있지 않은 경우 ~/.gradle임.

```

이를 사용할 수 있지만 그래도 gradlew에 뭔가 주석이 더 추가된다.

 

그냥 로컬에서 쓰는거 따로, IntelliJ에서 만든 프로젝트는 IntelliJ에서 빌드하는걸로...

 

bootJar와 Jar의 차이

  • 기본적으로 SpringBoot에서 Build를 실행하면 다음과 같이 bootJar 태스크는 실행하고 jar 태스크는 스킵해서, BootJar를 만들도록 되어 있다.

```

> Task :bootJar
> Task :jar SKIPPED

```

  • 이 스킵은 단독으로 Jar 태스크를 실행 했을 때도 마찬가지인데, build.gradle.kts에 다음과 같이 추가하면 Jar를 스킵하지 않을 수 있다.

```kt

tasks.getByName<Jar>("jar") {
    enabled = true
}

```

  • 이렇게 하고 java -jar로 실행해보면, bootJar 태스크로 만든 .jar는 부트 앱이 잘 뜨는 반면, 그냥 Jar 태스크로 만든 .jar는 "기본 Manifest 속성이 없습니다." 라고 뜬다.

 

Dependency 를 Exclude 했는데 제대로 되지 않을 때?

```kt

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-webflux") {
        exclude(group = "org.springframework.boot", module = "spring-boot-starter-logging")
    }

    ...

}

```

  • 이렇게 명시했으나 제대로 exclude가 되지 않을 수 있는데, 이는 타 모듈에서도 spring-boot-starter-logging에 대한 의존성을 가지고 있어 그렇다. (다른애들 다 주석처리 하고 해보면 됨.)
  • 그래서 뭔가를 exclude할거면, 이렇게 하는 방법 보다는 configurations를 사용하는 방법이 좋다.

 

Gradle Kotlin DSL

 

src/main/kotlin 으로 되어 있으면 exclude 불가능한 문제

```kt

sourceSets {
  main {
    java {
      exclude '**/Kakao*'
    }
  }
}

```

이렇게 쓰면 된다는데... stackoverflow 찾아봐도 된다고 헛소리만 많은데 안된다.

gradle 6.3버전 기준 안되는거 맞고

경로를 `` src/main/java`` 로 변경해주면 exclude가 동작한다. (clean 잘 해줄 것)

 

docs.gradle.org/current/samples/sample_building_kotlin_libraries.html  

 

직접 jar library 만들고 사용하기

jar library 만들기

  1. Running `` gradle build`` from terminal, 
  2. switching to /build/libs and then running 
  3. `` java -jar artifactname`` works just fine. (runnable jar 인 경우 실행)

 

local jar library 사용하기

```kt

// 분명 둘은 같은 jar인데, files로 로컬에서 불러오면 하위 dependencies가 resolve되지 않고,

implementation files("local-jar/spring-boot-starter-2.4.3.jar")

// 아래처럼 maven central에서 가져오면 하위 dependencies도 자동으로 resolve 된다.
implementation group: 'org.springframework.boot', name: 'spring-boot-starter', version: '2.4.3'

```

그러면 어디엔가 하위 dependencies가 적혀있다는 거고...

maven central에서 가져오는 경우 하위 dependencies를 자동으로 resolve하는 반면 로컬에서 가져오면 그렇지가 않다?

 

1. 로컬에 있는 jar는 jar대로 가져오고, 그 안의 dependencies는 maven에서 받아오는 방법(옵션)이 존재하나?

  • manifest에 Class-Path 명시? -- X
  • 느낌에 없을 것 같음.

 

2. fat jar로 만들어서 그냥 .jar 하나에 dependencies 다 포함하게 하면 되나?

*** Class-Path든 fat jat든 다음과 같은 구문을 사용하는데, compile로 잡히려면 dependencies에 implementation이 아니라 compile로 명시되어 있어야 한다.

```kt

from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }

```

 

3. 그냥, library 사용하는 측에서 직접 의존성 손수 추가해주도록 하는게 맞나?

당연히 되는 방법이긴 한데... 괜찮은 방법인가?

 

결론) 여러모로 최선의 방법은 mavenCentral 같은 곳에 올리는거네.

  • 다른 dependencies를 받아온 mavenCentral에 해당 library도 올려서 자동으로 dependencies가 resolve 될 수 있게끔 하는게 최선.
  • fat jar를 사용하는 방법은 충돌 가능성이 있어서, runnable jar 패키징에는 괜찮은 방법이나 library jar 패키징하는데는 좋은 방법은 아닌 것 같고
  • 그냥 직접 dependencies 추가해주는 3번 방법이 그나마 나아보인다.

'DevOps & Server' 카테고리의 다른 글

[tomcat] 톰캣, jvm 실행 인자  (0) 2020.03.05
[CI/CD] 젠킨스 Jenkins  (0) 2019.05.09
[Gradle] build, jar 배포, IntelliJ 설정  (0) 2019.04.10
vagrant  (0) 2018.11.02
ansible 앤서블 설명  (0) 2018.10.30
docker  (0) 2018.10.27