[Gradle] compile vs implementation

JD_S·2022년 10월 21일
0

Gradle

목록 보기
1/1

공식 문서에서 보면 compile이 붙은 것을 알 수 있다. 하지만 다른 인터넷을 뒤져보면 내가 하는 프로젝트의 아래 코드와 같이 implementation이 붙어 있는 것을 알 수 있다. 왜 일까?

    //Spring Security
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.security:spring-security-test'

일단 compile은 Gradle7.0에서 제거됐다. 처음에 Gradle은 dependencies에서 compile로 선언했다. 그러나 종속 항목의 세분화된 범위를 지원하지 않았다. 그래서 Gradle3.4에서 더 나은 기능이 나왔다. 바로 implementationapi이다.

implementaion은 라이브러리의 구현 세부 사항인 종속 항목을 선언하는데 사용해야 한다. 종속 항목은 컴파일 시간 동안 라이브러리를 사용하는 사람에게 표시되지 않는다.

java-library플러그인을 적용한 경우에만 사용할 수 있는 api는 컴파일 시 소비자에게 노출되어야 하는 라이브러리의 API 일부인 종속성을 선언하는 데 사용해야 한다.

이걸 해석해도 잘 와닿지가 않았다. 하지만 다음 글을 보면 알 수가 있다.

종속 항목 구성

implementation

Gradle이 컴파일 클래스 경로에 종속 항목을 추가하고 빌드 출력에 종속 항목을 패키징합니다. 그러나 모듈에서 implementation 종속 항목을 구성하면 모듈이 컴파일 시간에 종속 항목을 다른 모듈에 누출하기를 바라지 않는다는 것을 Gradle에 알려주는 것입니다. 즉 종속 항목은 런타임에만 다른 모듈에서 이용할 수 있습니다.
api 또는 compile(지원 중단됨) 대신 이 종속 항목 구성을 사용하면 빌드 시스템에서 다시 컴파일해야 하는 모듈 수가 줄어들기 때문에 빌드 시간이 크게 개선될 수 있습니다. 예를 들어 implementation 종속 항목이 API를 변경하면 Gradle은 이 종속 항목과 이에 직접적으로 종속된 모듈만 다시 컴파일합니다. 대부분의 앱과 테스트 모듈은 이 구성을 사용해야 합니다.

api

Gradle은 컴파일 클래스 경로와 빌드 출력에 종속 항목을 추가합니다. 모듈에 api 종속 항목이 포함되면 모듈이 다른 모듈로 종속 항목을 이전하여 다른 모듈에서 런타임과 컴파일 시간에 사용할 수 있도록 한다는 것을 Gradle에 알려주는 것입니다.
이 구성은 compile(현재는 지원 중단됨)처럼 작동하지만 주의해서 다른 업스트림 소비자에게 이전해야 하는 종속 항목과만 사용해야 합니다. 그 이유는 api 종속 항목이 외부 API를 변경하면 Gradle이 컴파일 시 종속 항목에 액세스 권한이 있는 모든 모듈을 다시 컴파일하기 때문입니다. 따라서 api 종속 항목 수가 많으면 빌드 시간이 크게 증가할 수 있습니다. 종속 항목의 API를 별도의 모듈에 노출하지 않으려면 라이브러리 모듈에서 implementation 종속 항목을 대신 사용해야 합니다.

compileOnly

Gradle은 컴파일 클래스 경로에만 종속 항목을 추가합니다(즉 빌드 출력에는 추가되지 않음). 이는 Android 모듈을 만들고 있으며 컴파일하는 동안 종속 항목이 필요한 경우 유용하지만 런타임에 이를 표시하는 것은 선택사항입니다.
이 구성을 사용하는 경우 라이브러리 모듈에 런타임 조건을 포함하여 종속 항목을 사용할 수 있는지 확인한 다음 종속 항목이 제공되지 않는 경우에도 작동할 수 있도록 동작을 적절하게 변경해야 합니다. 이렇게 하면 중요하지 않은 임시 종속 항목을 추가하지 않으므로 최종 앱의 크기를 줄일 수 있습니다. 이 구성은 provided(현재는 지원 중단됨)와 동일하게 작동합니다.

runtimeOnly

Gradle은 런타임 동안 사용하기 위해 빌드 출력에만 종속 항목을 추가합니다. 즉 컴파일 클래스 경로에는 추가되지 않습니다. 이 구성은 apk(현재는 지원 중단됨)와 동일하게 동작합니다.

compile

Gradle은 컴파일 클래스 경로와 빌드 출력에 종속 항목을 추가하고 다른 모듈로 종속 항목을 내보냅니다. 이 구성은 지원 중단되었습니다(AGP 1.0~4.2에서 사용 가능).

위에 뿐만 아니라 더있다.

A <- B <- C 이런 식으로 모듈 구조가 되어있다고 한다면 compile이나 api 사용 시에는 A라는 모듈을 수정하면 이 모듈을 직접 혹은 간접 의존하고 있는 B와 C는 모두 재빌드 되어야 한다. 하지만 implementation을 사용 할 경우에는 A라는 모듈을 수정하면, 이 모듈을 직접 의존하고 있는 B만 재빌드 된다. 재빌드(rebuild)의 의미는 recompile과 동일하다.

implementation를 써야하는 이유

구조만 봐도 연결된 dependency가 줄어들고, 변경이 일어나도 recompile을 적게 하여 소요 시간이 줄어든다. 그리고 apicompile을 사용하게 되면 연결된 모든 모듈의 API가 노출되는데 implementation을 사용하면 그럴 일이 없어진다.

Reference

profile
Whatever does not destroy me makes me stronger.

0개의 댓글