SPRING/Gradle

[Gradle] implementation와 api의 차이

앵낄낄 2024. 2. 21. 14:41
반응형

목차

  • 전의 의존성이란 (transitive dependency)
  • implementation와 api의 차이
  • implentation과 api의 사용
  • implentation과 api의 차이 요약

 

전의 의존성이란

개발을 하다 보면 외부 도구(라이브러리 또는 프레임워크 등)를 사용하기 위해 의존성을 끌어 와야 하는 경우가 빈번한데, 이때 빌드 도구로 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의 차이

[implentation]

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

[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가 사용 가능하다. 

 

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와 implementation을 왜 사용하는지를 파악하고 알맞게 사용해보자!

 

참고 링크

출처: https://mangkyu.tistory.com/296 [MangKyu's Diary:티스토리]

반응형