implementaion vs api/compile

고럭키·2020년 12월 23일
0

gradle을 이용할 때, module dependency를 선언할 때, api 혹은 compile을 사용하는 경우와 implementaion을 사용하는 경우가 있다. 이 둘의 차이가 무엇인지 알아보자 !

현재 compile은 지원이 중단된 상태이며, api가 compile과 동일한 방식으로 동작한다. 먼저 공식 문서에서를 살펴보면 api와 implementaion을 아래와 같이 설명하고 있다.

공식문서 링크 : https://docs.gradle.org/current/userguide/dependency_management_for_java_projects.html#sec:configurations_java_tutorial


  • api ( compile ) :
    The dependencies required to compile the production source of the project which are part of the API exposed by the project. For example the project uses Guava and exposes public interfaces with Guava classes in their method signatures.

  • implementation :
    The dependencies required to compile the production source of the project which are not part of the API exposed by the project. For example the project uses Hibernate for its internal persistence layer implementation.


부족한 영어실력이지만, 해석을 해보면 노출된 API의 부분이냐 부분이 아니냐.. ( 아니 이게 뭔 말이야.. )

이해를 위해 조금 더 찾아보니 Android Developer 사이트에서 아래와 같은 내용을 찾아볼 수 있었다.

안드로이드 개발자 링크 : https://developer.android.com/studio/build/dependencies?utm_source=android-studio#dependency_configurations


  • api :
    Gradle은 컴파일 클래스 경로와 빌드 출력에 종속 항목을 추가합니다. 모듈에 api 종속 항목이 포함되면 모듈이 다른 모듈로 종속 항목을 이전하여 다른 모듈에서 런타임과 컴파일 시간에 사용할 수 있도록 한다는 것을 Gradle에 알려주는 것입니다.
    이 구성은 compile(현재는 지원 중단됨)처럼 작동하지만 주의해서 다른 업스트림 소비자에게 이전해야 하는 종속 항목과만 사용해야 합니다. 그 이유는 api 종속 항목이 외부 API를 변경하면 Gradle이 컴파일 시 종속 항목에 액세스 권한이 있는 모든 모듈을 다시 컴파일하기 때문입니다. 따라서 api 종속 항목 수가 많으면 빌드 시간이 크게 증가할 수 있습니다. 종속 항목의 API를 별도의 모듈에 노출하지 않으려면 라이브러리 모듈에서 implementation 종속 항목을 대신 사용해야 합니다.

  • implementaion :
    Gradle이 컴파일 클래스 경로에 종속 항목을 추가하고 빌드 출력에 종속 항목을 패키징합니다. 그러나 모듈에서 implementation 종속 항목을 구성하면 모듈이 컴파일 시간에 종속 항목을 다른 모듈에 누출하기를 바라지 않는다는 것을 Gradle에 알려주는 것입니다. 즉 종속 항목은 런타임에만 다른 모듈에서 이용할 수 있습니다.
    api 또는 compile(지원 중단됨) 대신 이 종속 항목 구성을 사용하면 빌드 시스템에서 다시 컴파일해야 하는 모듈 수가 줄어들기 때문에 빌드 시간이 크게 개선될 수 있습니다. 예를 들어 implementation 종속 항목이 API를 변경하면 Gradle은 이 종속 항목과 이에 직접적으로 종속된 모듈만 다시 컴파일합니다. 대부분의 앱과 테스트 모듈은 이 구성을 사용해야 합니다.


위의 내용을 이해하기 쉽게, 아래와 같이 정리할 수 있다.


  • api : 의존 라이브러리 수정시, 해당 라이브러리 모듈을 의존하고 있는 모듈들 역시 재빌드된다. 즉, 수정된 라이브러리 모듈을 직접 그리고 간접적으로 의존하고있는 모든 모듈이 재빌드된다.

    ex ) A <- B <- C 와 같은 의존관계에서, A가 수정되면, B와 C가 모두 재빌드된다. C에서 A에 접근할 수 있다.

  • implementation : 의존 라이브러리 수정시, 본 모듈까지만 재빌드된다. 즉, 수정된 라이브러리를 직접적으로 의존하고있는 모듈만 재빌드된다.

    ex ) A <- B <- C 와 같은 의존관계에서, A가 수정되면, B만 재빌드된다. C에서 A에 접근할 수 없다.


일반적으로 implementation의 사용을 권장하는 이유로는, recompile이 덜 발생하므로 당연하게도 속도가 빠르다는 것이 하나의 이유일 것이다. 또한 api는 종속성이 전이되어 불필요한 모듈까지 노출되어 class path에 포함되기 때문이라는 이유가 있을 것이다.

즉, 의도적으로 종속성 전이를 발생시키고자 하는 경우에는 api를 사용한다고 생각하면 될 것 같다 !

0개의 댓글