1. Background
Gradle 에서는 Compile, Runtime, Test 등 상황에 맞게 의존성(dependency)을 가져오도록 지원합니다.
이 때 가져오는 방식에 따라 방법이 다른데 그 부분을 이해하고자 이 글을 정리합니다.
2. Usage
아래 글은 claude의 도움을 받아 작성하였습니다. (95%는 클로드 + Grok 작성)
Implementation
일반적으로 사용되는 방법
모듈 내부에서만 사용되며, 다른 모듈에 노출되지 않는다.
API 은닉성이 좋아, 빌드 성능 향상
라이브러리의 "내부 로직"에만 사용되거나, private 클래스에 쓰는 의존성입니다. 위 내용을 숨기면 클래스패스를 가볍게 하고, 내부 변경이 있어도 클라이언트가 재 컴파일 할 필요가 없습니다.
라이브러리가 섞여 런타임에 에러가 발생할 수 있지만, 호환되는 버전이라면 에러가 나지 않을 수 있습니다 버전이 호환되면 문제 없습니다.
라이브러리 버전이 충돌나면 높은 버전으로 설정됩니다.
API
해당 모듈을 의존하는 다른 모듈에도 전이적으로 노출합니다.
의존성이 변경되면 연쇄적으로 모든 하위 모듈 재컴파일 됩니다.
라이브러리 모듈 개발 시에 외부에 노툴해야되는 의존성에 사용됩니다.
라이브러리의 "외부" 인터페이스에 사용 라이브러리가 제공하는 클래스나 메서드의 시그니처, 다른 라이브러리의 타입을 사용한다면 그건 api로 선언해야됩니다. 왜냐하면 소비자가 내 라이브러리를 컴파일 할 때 그 타입을 "알아야" 합니다.
컴파일 타임에 에러가 날 수 있는 상황은 A -> B -> C 에 의존하고 A -> C 에 의존할 때, 각각 의존하는 버전이 다르면 에러가 발생합니다.
A -> B (1.0.0) -> C(1.0.0) A -> C (2.0.0) 이면, C (1.0.0 / 2.0.0)이 동시에 필요한 경우가 생겨 충돌됩니다.
compileOnly
- 실제 APK/JAR에 포함되지 않습니다.
- 주로 annotation processor나 제공된 환경의 라이브러리에 사용
- Android provided와 유사합니다.
runtimeOnly
- 컴파일 시에는 사용할 수 없음
- 주로 로깅 구현체, JDBC 드라이버 등에 사용
testImplementation
- 테스트 소스셋에서만 사용 가능
- 프러덕션 코드에는 포함되지 않습니다.
annotationProcessor
- 컴파일 클래스 패스에는 포함되지 않습니다.
- Lombok, Dagger 등의 코드 생성 라이브러리에만 사용
- 먼저 코드를 생성하고 추후에 컴파일됩니다.