Bepoz
파즈의 공부 일기
Bepoz
전체 방문자
오늘
어제
  • 분류 전체보기 (232)
    • 공부 기록들 (85)
      • 우테코 (17)
    • Spring (85)
    • Java (43)
    • Infra (17)
    • 책 정리 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Bepoz

파즈의 공부 일기

Spring

[Spring] Gradle 파일 implementation, api, runtimeOnly, compileOnly... 등에 대해

2021. 6. 6. 23:19

Gradle 파일 implementation, api, runtimeOnly, compileOnly ... 등에 대해

아무 생각없이 gradle을 사용해왔는데 우테코 미션에 대한 리뷰 중 다음과 같은 것이 달렸다.

image

그래서 공부해보았다!

먼저, Classpath에 대해서 알아야 할 것 같다. Classpath는 클래스나 jar 파일이 존재하는 위치라고 볼 수 있다.
Classpath는 Compile-time classpath 와 Run-time classpath로 나누어진다.

Compile-time classpath는 에러없이 컴파일을 하기위해 필요한 클래스와 jar들의 위치를 나타낸다. 이렇게 컴파일을 하고 난 뒤에 애플리케이션의 실행이 당연히 될 것이라고 생각할 수 있는데 그것은 오산이다. 런타임에서 필요한 다른 클래스와 jar 가 필요할 수도 있기 때문이다.

Run-time classpath는 애플리케이션이 정상적으로 실행하기위해 필요한 클래스들과 jar들의 경로다.
Intellij에서 우측의 gradle 탭을 누르면 다음과 같이 나오는 것을 확인할 수가 있다.

image

선수 지식은 이정도면 될 것 같다. 이제 gradle의 dependency configurations 들을 알아보자.

image

test를 제외한 대표적인 종류는 다음과 같다. gradle 3.0 이후 위와 같이 변한 것인데 무엇이 변했는지 간략히 말하겠다.
compile이 사라지고 implementation과 api로 나뉘었다.
testCompile -> testImplementation, debugCompile -> debugImplementation, provided -> compileOnly
우선 api와 implementation의 차이점을 설명해보겠다.

class A{
  public static void main(String[] args){
    B b = new B();
  }
}

class B {
  public int asdf() {
    return new C().sum();
  }
}

class C {
  public int sum(){
    return 5;
  }
}

위와 같이 클래스 A,B,C 가 있다고 하자. 내가 정의한 클래스는 A이고, 외부 라이브러리 B를 호출한 상황이라고 가정하자.
A -> B -> C 의 상황이라고 볼 수 있다. 컴파일을 위해서는(컴파일 타임) 나는 A와 B에 대한 경로만 가지고 있으면 될 것이다. 그러나 런타임을 위해서는 C에 대한 정보도 가지고 있어야 할 것이다. A와 B에 대한 컴파일 타임 의존성을 가지고 있는 것이며, A, B, C에 대해 런타임 의존성을 가지고 있는 것이다.

컴파일 타임 의존성과 런타임 의존성에 대한 추가적인 예시를 들어보겠다.
위 코드의 예시는 A가 B를 호출하고 B가 C를 호출할 때에, 컴파일 타임 의존성은 A, B이고, 런타임 의존성은 A, B, C 인 것이다.
만약, A가 Class.forName()으로 B를 호출하는 경우에는 컴파일 시에는 B에 대한 정보가 필요하지 않으므로(컴파일 타임에서는 B의 존재를 모름), 컴파일 타임 의존성은 A 인 것이고, 런타임 의존성은 A, B라고 볼 수 있다.

만약 B에 대한 dependency를 implementation으로 설정하게 되면 compile path에는 B만 들어가게 된다.
즉, 컴파일 타임에서 사용자(A를 정의한 이용자)는 C를 알 수가 없다. 그리고 C가 수정되었다고 하더라도 A를 다시 컴파일 할 필요가 없다. 오직 B만 컴파일을 하면 된다.

그렇다면 api로 설정하면 어떻게 될까?? implementation과는 다르게 compile path에 C도 들어가게 된다.
즉, 컴파일 타임에서 사용자는 C를 알고 있는 상태이고, C가 수정이 돼서 재빌드 해야되는 상황이 오면 A 또한 해주어야 하게 된다.

그렇다면 compileOnly와 runtimeOnly의 차이점은 무엇일까? 간단히 말하자면 전자는 compileClassPath에만 추가하겠다는 뜻이고, 후자는 runtimeClassPath에만 추가하겠다는 뜻이다.

이렇게 나누게되면 compileOnly의 경우에는 빌드 결과물의 사이즈가 줄어들 것이고, runtimeOnly의 경우에는 해당 클래스에서 코드 변경이 일어나도 컴파일을 다시 할 필요가 없게될 것이다.

compileOnly의 대표적인 예는 lombok이라고 할 수 있다. 컴파일 시에 getter, setter 등 필요한 것을 생성시키고, 런타임 때에는 사용하지 않기 때문이다. runtimeOnly는 DB관련이나 로그관련 dependency 이다. 이외에도 위의 코드 예시를 생각해보고 컴파일 타임에는 필요없는데 런타임에서는 의존하는 것들은 runtimeOnly로 설정해줘야 겠다~ 라고 알아두면 된다.

image

정리하자면 위의 표와 같다. test에 관련한 것도 동일한 개념을 띈다.

image

애매하면 implementation으로 만사해결이다!!
그렇다면 다시 한 번 첫 번째 사진을 살펴보자.

image

이제 좀 이해가 갈 것이다. implementation 은 compile path, runtime path 에 둘 다 들어가게 되니 저렇게 화살표를 다 받고 있는 것이고, compileOnly와 runtimeOnly 는 각각 1개에만 속하니 화살표를 저렇게 받고 있는 것이다. 지금까지 배운 내용을 통해 compileOnlyApi와 compileOnly의 차이점 또한 유추할 수 있을 것이다.


Reference

https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_configurations_graph

https://www.geeksforgeeks.org/how-is-compiletime-classpath-different-from-runtime-classpath-in-java/

https://tomgregory.com/gradle-implementation-vs-compile-dependencies/

https://stackoverflow.com/questions/4270950/compile-time-vs-run-time-dependency-java/4271013

https://ichi.pro/ko/gradle-jongsogseong-guseong-i-naebueseo-jagdonghaneun-bangsig-256411970261733

https://stackoverflow.com/questions/44493378/whats-the-difference-between-implementation-and-compile-in-gradle

'Spring' 카테고리의 다른 글

[Spring] BindingResult와 Errors의 차이점에 대해  (0) 2021.06.27
[Spring] HttpMessageConverter가 적용되는 시점에 대해  (3) 2021.06.14
[Spring] @Profile, @ActiveProfiles 에 대해  (0) 2021.05.23
[Spring] @ConfigurationProperties 에 대해  (0) 2021.05.23
[Spring] Mockito.mock() vs @Mock vs @MockBean  (0) 2021.05.19
    'Spring' 카테고리의 다른 글
    • [Spring] BindingResult와 Errors의 차이점에 대해
    • [Spring] HttpMessageConverter가 적용되는 시점에 대해
    • [Spring] @Profile, @ActiveProfiles 에 대해
    • [Spring] @ConfigurationProperties 에 대해
    Bepoz
    Bepoz
    https://github.com/Be-poz/TIL

    티스토리툴바