본문 바로가기
허브 살리기 프로젝트

Gradle Java plugin API and Implementation

by jay-choe 2024. 1. 31.

 

 

멀티모듈을 사용하다보면 종종 build.gradle에서 의존성을 추가할 때 API, Implementation을 확인 할 수 있고 여러 자료들을 찾아보다보면 헷갈려서 둘의 차이를 공식 문서를 보고 정리했다.

 

 

 

우선 헷갈리지 않게 둘의 의존성 관리 주체는 gradle이다.

 

즉, gradle에서 제공하는 의존성 관리 기능을 사용하는데 API, Implementation이 있고 이 차이를 확인하는 것이다.

 

 

API

This is where you declare dependencies which are transitively exported to consumers, for compile time and runtime.

 

 

api는 사용하는 측에 컴파일 시점과 런타임 시점에 전이 된다고 한다.

 

예를 들어서 A 라는 모듈이 있고 B가 A를 api로 사용하며

 

C라는 모듈이 B를 어떤 경로든 사용하게 된다면 A라는 의존성이 B에 전파 되었고

 

C(consumer)에 해당 의존성이 전이 되었기 때문에 

 

C에서 컴파일 시점과 런타임 시점에 A를 사용할 수 있게 되는 것이다.

 

 

Implementation

This is where you declare dependencies which are purely internal and not meant to be exposed to consumers (they are still exposed to consumers at runtime).

 

외부 모듈에 노출되지 않는다고 한다.

 

즉 A라는 모듈을 B가 implementation으로 사용한다면

 

C라는 모듈이 B를 사용할 때 A가 노출되지 않았기 때문에 A에 접근할 수 없다.

 

즉 컴파일 타임에 A가 없기 때문에 A쪽에 구현된 코드를 C에서 접근할 수가 없게 된다.

다만 런타임시에는 존재하기 때문에 실행은 된다.

 

 

그럼 이 둘은 왜 나누어져 있을까?

위 내용으로 추론해보면 2가지로 확인 할 수 있다.

 

1. 컴파일시간 최적화

 

api로 모듈을 추가하는 경우 컴파일 타임에도 존재해야 한다는 점을 볼 수 있다.

위의 예시에서 C를 빌드하면 A까지 전부 컴파일 해야 한다.

 

 

2. 모듈 격리

 

api로 모듈을 추가하는 경우 위의 예시에서 C에서 A로 접근이 가능하게 된다.

그렇다면 A의 변경은 C까지 전파가 된다.

 

역으로 생각하면 A를 수정하려면 B, C까지 고려해야한다.

 

이 말은 수정하기가 어려워지게 된다.

 

수정하기 어렵다는 것은 그만큼 시간이 든다는 말이고 개발에서 시간은 곧 비용이다.

 

즉 모듈 격리가 잘 되어 있지 않은 것은 비싸다.

 

Implementation을 사용하게 되면 C는 A의 존재를 알 필요가 없어지게 되며

 

A의 변경은 B에만 영향을 미치게 된다.
(물론 연쇄적으로 C까지 영향을 줄 수는 있지만 C에서 직접 A에 접근하는 것에 비해 비용이 싸다.)

 

 

 

 

 

 

참고

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