티스토리 뷰

Server

[Gradle] Gradle Java 플러그인과 implementation와 api의 차이

망나니개발자 2023. 5. 16. 10:00
반응형

이번에는 Gradle(그레이들)이 제공하는 Java 플러그인과 implementation와 api의 차이에 대해 알아보도록 하겠습니다.

 

 

 

 

1. Gradle Java 플러그인, Java-Library 플러그인


[ Java 플러그인이란? ]

Gradle(그레이들)에서 Java 프로젝트를 빌드하려면 기본적으로 java 플러그인이 필요하다. java 플러그인을 통해 컴파일, 테스트, jar 파일 생성 등의 작업들(tasks)이 수행 가능하다.

plugins {
    id 'java'
}

 

 

Java 플러그인이 제공하는 작업들은 아래의 그림에 나와있다. 자세한 내용은 공식 문서를 참고하도록 하자.

 

 

 

자바로 작성된 프로그램은 먼저 Java 파일들을 컴파일하여 바이트 코드(.class)로 만들어내고, 이를 JVM이 읽어들인다. 그리고 애플리케이션이 실행되면서 바이트 코드를 기계어로 번역한다. 자바로 작성된 프로그램을 컴파일(compile)하고 실행(run)할 때 특정 경로에서부터 시작하여 클래스 파일과 패키지를 탐색하게 되는데, 이를 클래스 패스(class path)라고 한다.

 

 

자바를 컴파일할 때 탐색하는 경로와 실행할 때 탐색하는 경로를 각각 compile class path, runtime class path라고 한다.

  • Compile classpath: Java 코드를 class 파일로 컴파일 할 때 탐색하는 경로
  • Runtime classpath: 컴파일된 자바 코드(class 파일)을 JVM이 실행할 때 탐색하는 경로

 

 

컴파일 시점에만 필요로 하는 의존성도 있고, 실행 시점에만 필요로 하는 의존성도 있다. 그래서 Gradle에서 의존성(dependency)를 추가할 때 어느 범위로 노출시킬 것인지 결정할 수 있도록 도와준다.

  • complieOnly: 컴파일 경로에만 설정
  • runtimeOnly: 런타임 경로에만 설정
  • implementation: 두 경로에 모두 설정
  • api: 두 경로에 모두 설정

 

 

[ Java-Library 플러그인이란? ]

Java-Library 플러그인은 기존의 java 플러그인에 추가적인 정보를 제공함으로써 기능을 확장한 플러그인이다. 이를 활용하면 Java 플러그인에 의해 노출되는 모든 source sets, tasks, configurations를 암시적으로 사용할 수 있다.

plugins {
    id 'java-library'
}

 

 

그리고 추가적으로 dependency에서 api 기능이 노출된다는 차이가 있다. api를 사용하면 implementation과 마찬가지로 두 경로에 모두 설정된다. 하지만 둘 사이에는 중요한 차이가 있는데, 이에 대해 살펴보도록 하자.

dependencies {
    api 'org.apache.httpcomponents:httpclient:4.5.7'
    implementation 'org.apache.commons:commons-lang3:3.5'
}

 

 

 

 

 

2. Gradle implentation과 api의 차이


[ 전이 의존성 또는 추이 의존성(transitive dependency)이란? ]

개발을 하다 보면 외부 도구(라이브러리 또는 프레임워크 등)를 사용하기 위해 의존성을 끌어 와야 하는 경우가 빈번한데, 이때 빌드 도구로 Gradle(그레이들)을 사용하면 크게 api 또는 implementation을 사용할 수 있다. 참고로 Gradle6 이전에는 compile도 사용 가능했는데, compile이 deprecated 되고 나온 것이 api이다. 그리고 runtime 대신 나온 것은 implementation이다.

그리고 앞서 설명하였듯 implementation과 api를 사용하면 모두 컴파일 경로와 런타임 경로에 노출된다. 하지만 둘 사이에는 전이 의존성(transitive dependency)의 컴파일 경로 노출 여부에서 차이가 있다. (런타임 경로에는 Project C에서 Project B를 사용할 때, Project B에서 Project A를 사용하므로 당연히 노출된다.)

 

예를 들어 다음과 같은 구조의 3개의 프로젝트가 있다고 하자. Project C는 Project B에 의존하고 있고, Project B는 Project A에 의존하고 있다. 그러면 Project C도 Project A에 의존하게 되는데, 이를 전이 의존성 또는 추이 의존성(transitive dependency)이라고 한다.

 

 

 

 

 

[ implentation과 api의 차이 ]

api는 전이 의존성을 허용한다. 예를 들어 Project A가 있고, Project B에서는 api를 사용하여 Project A에 의존한다고 하자.

 

Project C에서는 Project B에 implementation를 통해 의존하기 때문에, Project B에 있는 컴파일 경로, 런타임 경로들이 노출된다. 그리고 Project B는 api를 통해 Project A에 의존하고 있으므로, Project C에서도 Project A가 사용 가능하다.

 

 

하지만 implementation으로 선언된 전이 의존성은 사용이 불가능하다. 아래의 경우에는 Project B에서 implementation를 사용하여 Project A에 의존하고 있으므로, Project C에서는 Project A의 코드에 접근이 불가능하다. 만약 Project A의 코드에 접근하려고 하면 컴파일 에러가 발생한다.

 

 

api와 implementation의 차이에 대해 정확히 이해하기 위해 몇 가지 사례를 더 추가하였다. 직접 확인해보도록 하자.

 

 

 

[ implentation과 api의 사용 ]

이러한 implementation은 api에 비해 몇 가지 장점이 있다.

  • 의존성이 해당 모듈을 사용하는 컴파일 클래스 경로에 노출되지 않으므로, 실수로 전이 종속성에 빠지지 않음
  • 줄어든 클래스 패스 덕분에 컴파일이 빨라짐
  • implementation하는 의존성들이 변경되었을 때, 재컴파일을 하지 않아도 되므로 재컴파일 횟수가 줄어듬
  • 새로운 maven-publish 플러그인을 함께 사용하면, java 라이브버리는 컴파일하는데 필요한 것과 런타임에 사용하는데 필요한 것을 정확히 구분하는 POM 파일을 생성하여 더욱 깔끔하게 publish 할 수 있음

 

 

따라서 가능하다면 api 보다는 implementation을 우선시하는 것이 좋다. 이렇게 하면 모듈을 사용하는 곳의 컴파일 클래스 경로에서 종속성을 유지할 수 있다. 또한 implemeantion으로 선언된 라이브러리가 사용되려고 하면 컴파일 에러가 발생하며 실패하게 된다.

api는 애플리케이션 바이너리 인터페이스(ABI, Application Binary Interface)로 아래와 같은 경우에 사용하면 좋다.

  • 부모 클래스 또는 인터페이에 사용되는 타입
  • 제너릭 타입을 포함하여 public 메소드 파라미터로 사용하는 타입
  • 퍼블릭 필드에 사용되는 타입
  • 퍼블릭 애노테이션 타입

 

 

반면에 아래와 같은 경우는 ABI에 해당하지 않으므로 implementation을 사용해야 한다.

  • 메소드의 바디에서만 사용되는 타입
  • 프라이빗 멤버로 사용되는 타입
  • 내부 클래스에서 발견되는 타입

 

 

 

[ implentation과 api의 차이 요약 ]

  • api
    • 추이 의존성을 허용함, C <- B(api a) <- A 일 때, C에서 A를 접근할 수 있음
    • A가 변경될 경우, B와 C까지 모두 재빌드되어야 함
  • implementaion
    • 추이 의존성을 허용하지 않음, C <- B(implementation a) <- A 일 때, C에서 A를 접근할 수 없음
    • A가 변경될 경우 B만 재빌드되면 됨

 

 

implementation을 사용하면 각 모듈들에서 불필요한 추의 의존성을 방지할 수 있고, 성능적인 이점을 얻을 수 있는 등의 장점이 있다. 따라서 최대한 implementation을 사용하고, api는 사용하지 않는 것이 좋다. 직접 관리하는 프로젝트에서도 처음에 api를 사용하기도 했다가, 현재는 api를 사용하는 부분을 모두 제거하였다.

 

 

 

 

참고 링크

 

 

 

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함