[Android] Gradle api vs implementation

이승우·2023년 5월 30일
1
post-custom-banner

📌 implementation, api, compile

implementation과 api는 모두 build.gradle에서 사용하며 라이브러리를 적용시키는 키워드이다.

오래된 Gradle 버전에는 implementation이 없어서 compile을 사용했었고, 새로운 버전(6.x 이후 버전)에서 compile이 deprecated되면서 compile 대신 api 키워드가 사용되게 되었다.

이 때문에 오래된 프로젝트의 build.gradle 파일들을 보면 implementation 대신 api와 compile을 사용하는 것을 볼 수 있다.

즉, api와 compile은 같은 역할을 한다. 하지만 Gradle은 api나 compile을 사용하는 걸 권장하지 않는다. api를 통해 라이브러리를 가져올 경우 라이브러리가 적용되는 범위 때문이다.

api, compile의 라이브러리 적용 범위

모듈에서 api나 compile을 사용해 라이브러리를 가져오게 되면, 해당 라이브러리는 해당 모듈을 의존하는 모듈에도 가져와진다.

예를 들어, ModuleA에서 api를 사용해 Library를 가져온 다음, ModuleB에서 api를 사용해 ModuleA를 가져올 경우 Library도 같이 가져와진다.

이것은 프로그램의 유지보수성 측면에서 매우 좋지 않다. Module을 사용할 때는 Module의 인터페이스만이 외부에 노출되어야 하는데, Library의 인터페이스까지 같이 노출되기 때문이다. 또한, Leak이 일어나는데, ModuleA를 빌드하면서 이미 들어간 Library가 중복으로 ModuleB에도 추가되기 때문이다.

특히 Clean Architecture 측면에서 Entity 모듈은 비즈니스 로직을 만드는 애플리케이션의 UseCase 모듈에서만 사용되고, UseCase 모듈은 Controller 모듈에서만 사용되는 구조로 이루어져 있어 각 레이어별로 분리가 확실하게 일어난다. 만약, Controller에서 Entity 모듈을 알게 된다면 모듈 계층을 건너뛴 참조가 일어날 수 있게 되어 레이어를 나누는 이유가 없어지게 된다.

따라서 이를 해결하기 위해 한 모듈에서 사용하는 라이브러리는 그 모듈에서만 사용될 수 있도록 implementation을 써야 한다.

implementation의 적용 범위

모듈에서 implementation을 사용해 가져오는 라이브러리는 해당 모듈을 의존하는 모듈에는 가져와지지 않는다.

예를 들어, ModuleA에서 implementation을 이용해 Library를 가져온 다음, ModuleB에서 implementation을 사용해 ModuleA를 가져오면 Library는 가져와지지 않는다. Library는 ModuleA에 캡슐화되어 ModuleB에 노출되지 않는다.

이 방식을 이용하면 모듈 수준에서 공개되는 코드를 모듈의 인터페이스로 제한할 수 있어 모듈간 의존성을 줄이게 된다. 그림 1에서는 ModuleB가 ModuleA와 Library에 모두 의존했지만, 그림2에서는 ModuleB가 ModuleA에만 의존하는 것을 볼 수 있다. 프로그래밍 유지보수의 핵심은 모듈간 의존성을 줄이는 것이 중요하다. 모듈간 의존성을 줄여서 유지보수를 용이하게 해보자.

Ref

profile
Android Developer
post-custom-banner

0개의 댓글