엔지니어로 가는 길

Gradle 멀티 모듈 프로젝트 빌드타임 단축하기(30분 -> 2분) 본문

private note/한 일, 할 일, 하고싶은 일

Gradle 멀티 모듈 프로젝트 빌드타임 단축하기(30분 -> 2분)

탐p슨 2022. 11. 21. 21:19
728x90

* 한 두 달 전쯤 진행했던 업무

빌드 타임 30분

담당하고 있는 서비스에서 의존성을 추가하거나 수정할 때마다 30분이 소요됐다. 처음엔 '원래 그런가 보다' 하고 넘어갔는데, 해당 서비스에 대해 알게 될수록 30분은 너무 과하다는 생각이 들었다. 의존성을 하나 추가하거나 수정하는 아주 간단한 수정이었고, 프로젝트도 그렇게 거대하고 복잡하지 않은 데 너무 오랜 시간이 걸린다고 생각했다. 그러던 차에 의존성을 수정할 일이 있는 업무를 맡게 되었고, 빌드 타임부터 개선해보기로 했다.

원인이 뭘까

해당 서비스는 gradle 멀티 모듈 프로젝트였고, gradle 버전은 4.X였다. 처음에는 build.gradle 파일을 보며 빌드 타임이 느린 원인을 몇 가지 추측해보았다.

- deprecated 저장소
- 불필요한 저장소(해당 저장소에 있는 의존성에 의존하고 있지 않음)
- 중복된 저장소
- 중복된 의존성(루트 build.gradle에서 명시한 의존성 서브 build.gradle에서 명시)

위의 작업이 크리티컬한 영향을 줄 것 같지는 않았다. 느린 빌드 타임의 원인이라기보다는 그냥 코드 스멜에 가깝다고 생각했다. 검색을 통해 개선할 수 있는 다른 방법을 찾아보았고, 아래 글을 참고하여 추가 개선을 진행하였다.

Improving the Performance of Gradle Builds

When using build scans in the context of profiling a build, the main area of interest in the early stages of diagnosis is the performance page. To get there, click "Performance"  in the left hand navigation menu, or follow the link highlighted in the foll

docs.gradle.org

버전을 올려보자

위의 글에서는 gradle과 JVM 최신 버전을 사용하는 것만으로 손쉽게 성능을 개선할 수 있다며 가장 먼저 추천했다. 그래서 가장 먼저 gradle 버전부터 올렸다.

Gradle 4.X에서 최신 버전인 7.X로 버전을 올렸는데 gradle 7.X로 올렸을 때 문제가 되는 gradle plugin이 있어서 당장 최신 버전을 사용할 수는 없었고, 다른 수정 없이 올릴 수 있는 버전인 5.X로 버전을 올렸다.

5.X 버전부터 compile()이 deprecated 되었는데, 우리 프로젝트의 모든 build.gradle에서 의존성을 추가할 때 compile()을 사용하고 있었다. compile()은 api() 또는 implementation()으로 수정해야 했기 때문에 api()와 implementation()이 각각 어떤 차이인지 확인해봤다.

검색하면 많은 자료들이 나오는 데 그중 내게 가장 간결하고 명확한 설명으로 다가오는 것은 다음과 같았다.

api()로 추가한 의존성은 public 의존성으로, 다른 프로젝트에서 나에 의존할 때 사용할 때 나의 api() 의존성까지 코드(compile)에서 사용할 수 있다.

implementation()으로 추가한 의존성은 private 의존성으로, 다른 프로젝트에서 나에 의존할 때 나의 implemenation() 의존성은 runtime에 존재하기는 하지만 코드에서 사용할 수는 없다.

위의 내용을 참고하여 compile()을 implementation()과 api()로 수정하였다(대부분이 implementation()으로 수정되었다). 그리고 숨을 고를 겸 의존성을 하나 추가하여 빌드 타임이 얼마나 단축됐는지 테스트했다.

30분 걸리던 빌드 타임이 1분 30초 내외로 단축되었다.

뭐가 가장 핵심적인 이슈였을까?

쉽게 개선할 수 있을 거라고 기대하지 않았고, 이렇게 극단적으로 개선될 수 있으리라고도 기대하지 않았기 때문에 기쁜 동시에 당황스럽기도 했다. 많지 않은 부분을 수정했는데 그중 가장 결정적으로 빌드 타임을 느리게 만들었던 핵심 원인이 무엇인지 궁금해서 다시 하나씩 확인해보았다.

모든 것을 원상복구 한 뒤 compile()만 api()와 implementation()으로 수정해보았다. 빌드 타임에 큰 차이가 없었다. Deprecated 저장소, 불필요한 저장소, 중복된 저장소, 중복된 의존성만 제거해보았을 때도 빌드 타임에 큰 차이가 없었다.

버전을 5.X로 올리자(compile()이 deprecated 되어서 api()와 implementation() 사용까지 같이 수행했다) 빌드 타임이 2분으로 단축됐다. 여기에 앞서 말한 다른 개선까지 모두 적용해보니 2분에서 1분 30초 내외로 단축되었다.

정리

낮은 gradle 버전을 사용한다면 버전업만으로 엄청난 빌드 타임 단축을 기대할 수 있다

Gradle 뿐만 아니라 다른 모든 라이브러리 및 프레임워크 역시 일반적으로 버전이 올라갈 때마다 퍼포먼스가 개선되리라고 기대할 수 있는데, 적어도 중요한 몇 가지 라이브러리 및 프레임워크는 동향?을 잘 추적하고 있으면 좋을 것 같다(현재 최신 버전이 무엇이고, 어떤 버전에서 메이저한 변화가 있었는지 등).

동향 추적을 아무리 빠삭하고 꼼꼼하게 해도 새로운 버전으로 올리지 못한다면 큰 의미가 없다. 프로젝트를 어떻게 관리해야 큰 비용 없이 새로운 버전을 잘 적용할 수 있을까? 서비스 자체에 대한 풍부하고 커버리지 높은 테스트가 있고, 해당 라이브러리 또는 프레임워크 자체에 대한 테스트도 작성되어 있다면 새로운 버전을 도입하는 비용을 줄일 수 있을 것 같다.

728x90
Comments