다운로드 용량 26.7MB 짜리 앱이 빌드는 12분 가량 된다는 게 가장 큰 문제이다.
로컬 빌드는 3분 47초 걸리는데 CI가 3배나 걸리면 CI빌드를 도입한 보람이 없다고 생각했다. 그래서 CI빌드 속도 개선을 시작했다!
아직 빌드를 위한 전처리와 빌드 밖에 없는 기본 상태이다.
name: Android develop CI
on:
push:
branches: [ "feature_github_action" ]
pull_request:
branches: [ "feature_github_action" ]
jobs:
build:
runs-on: ubuntu-latest
env:
HMOA_ANDROID_SECRET_TOKEN: ${{secrets.HMOA_ANDROID_SECRET_TOKEN}}
RELEASE_KEYSTORE: ${{secrets.RELEASE_KEYSTORE}}
steps:
- uses: actions/checkout@v4
- name: set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: gradle
- name: Grant execute permissions for scripts
run: |
chmod +x copy-hmoa-android-secrets.sh
- name: Generate release.keystore
run: echo '${{ secrets.RELEASE_KEYSTORE }}' | base64 --d > ./app/release.keystore
- name: Run copy secrets
run: ./copy-hmoa-android-secrets.sh
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
빌드 캐시, 빌드 캐시 키 2가지가 있다.
빌드 캐시는 캐시 키값이 일치해야 사용할 수 있다.
빌드 캐시 키는 의존성이 바뀔 때마다 값이 달라진다. 이 점을 기억하면 이해하기 쉽다.
아래 3가지만 사용했다. 나머지 Input에 대해서는 공식 repository를 참고하면 좋다.
key - 캐시 항목의 명시적인 키.
path - 캐시하고 복원할 파일, 디렉터리 및 와일드카드 패턴의 목록. 지원되는 패턴에 대해서는 @actions/glob를 참조해야 함.
restore-keys - 캐시 적중이 발생하지 않았을 때 오래된 캐시를 복원하기 위해 사용하는 접두사 일치 키의 순서가 있는 목록.
path: |
~/.gradle/caches
~/.gradle/wrapper
실행하는 운영체제와 gradle파일, gradle-wrapper.properties의 내용이 변경될 때마다 고유한 해시 값을 생성하여 캐시 키에 포함시킨다. 캐시 키값을 대조해서, 값이 일치하지 않을 경우 의존성을 다시 설치하고 새로운 캐시를 생성한다.
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-key를 쓰는 이유는 의존성 변경이 일어났을 때 key값이 달라지고, 캐시가 적용되지 않을 경우를 대비하는 것이다.
아래와 같이 restore-key를 사용하면 같은 운영체제, runner.os-gradle또는 runner.os-로 시작하는 유사한 캐시를 사용하게 된다.
restore-keys: |
${{ runner.os }}-gradle-
...생략(위의 코드와 동일함)...
- name: Gradle Caching
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
빌드 캐시 추가를 하고나서의 첫 yml파일 실행이기 때문에 생성된 캐시 키와 일치하는 키가 없다고 나온다.
생성된 캐시 크기는 885MB이고, path로 지정한 디렉토리에 저장되었을 것이다.
설치된 의존성 파일이 캐시된 것을 볼 수 있다.
빌드 캐시를 적용했더니 6분 54초로 줄어들었다. 거의 2배 단축했지만 이게 최선인지는 모르겠다. 🤔
이제 1.0.0 버전으로 배포했고 앞으로 핵심 서비스가 더 들어올텐데 더 빌드시간을 줄일 필요가 있겠다.
불필요한 의존성을 삭제하고, 빌드 프로파일링을 해보는 등 더 최적화를 거쳐야 한다.
6분 54초도 너무 길다고 생각해 방법을 고민한 찰나에 CD가 아니고 그냥 CI라는 점에 가벼운 빌드 명령어를 사용하기로 했다.
./gradlew build에서 ./gradlew assembleDebug로 수정했다.
그 결과 3분 54초로 더 빠르게 수행되었다.
물론 배포브랜치에서는 Debug용이 아닌 Release용 빌드를 해야하겠지만! 우리팀의 CI 도입 이유는 개발과정에서의 test와 build로 지속적인 통합을 하는 거니까 이 정도면 일단 도입 가능한 정도라고 생각한다. (test가 늘어난다면 분명 시간이 더 걸릴테니 개선해야 한다.)
너무 간단한 해결방법...그 효과는 굉장했다.
https://github.com/actions/cache?tab=readme-ov-file
https://pozafly.github.io/dev-ops/cache-and-restore-keys-in-github-actions/
https://devjem.tistory.com/76
https://hellorennon.tistory.com/22