I. CICD 속도 개선 필요성
1. 인프라 비용 절감
•
GitHub Actions 기반 CICD의 속도를 향상시키면 인프라 비용을 절감할 수 있습니다. 만약 GitHub Actions로 한 번의 CICD workflow를 실행할 때마다 9분이 소요된다면, 개발자 20명이 하루에 10번의 workflow를 실행한다는 가정하에 연 410만원이 과금됩니다. 만약 CICD 시간을 5분으로 줄인다면 연비용을 210만원으로 낮출 수 있습니다.
•
위의 비용은 다음과 같은 조건에 따라 계산되었습니다. ‘GitHub Team’ Plan을 사용한다고 가정할 때 GitHub Actions 사용 시간이 월 3,000분을 넘으면 초과 사용시간에 대해 과금합니다. 리눅스 환경으로 workflow를 구성한다고 가정하면 초과된 사용시간에 대해 분당 0.008$로 비용이 책정됩니다. CICD workflow 실행 시간이 9분이고, 개발자 20명이 하루에 10번의 workflow를 실행한다면 하루 사용시간은 1800분입니다. 한 달의 근무일을 20일을 가정하면 월별 사용시간은 36,000분입니다. 무료 제공 시간 3000분을 제외하면 33,000분이므로 월별 사용시간에 분당 10.4원(0.008$ * 1300)을 적용하면 월 34만원, 연 410만원이 됩니다.
2. 제품 개발 생산성 향상
•
CICD 속도를 개선하면 코드 변경사항 반영 시간이 단축되기 때문에 이슈 대응 속도가 향상됩니다. 이슈 대응 뿐만 아니라 제품 개발 간 협력 시에도 보다 빠르게 피드백을 제품에 반영할 수 있으므로 전체적인 제품 개발 생산성이 향상됩니다.
II. 속도 개선: 의존성 캐싱
1. Gradle 의존성 캐싱
•
GitHub Actions는 반복적으로 사용되는 의존성에 대해 캐싱하는 기능을 제공합니다. 캐싱된 의존성은 재사용되어 workflow 전체 시간을 단축할 수 있습니다. 레시피의 특정 옵션을 사용하면 workflow에서 반복적으로 사용하는 의존성을 간단하게 캐싱할 수 있습니다.
•
이하 workflow 예시의 Set Up JDK 스텝에서 cache 옵션을 사용하여 gradle 의존성을 캐싱합니다. 참고로 Gradle 의존성은 $HOME/.gradle/caches/ 경로에 저장됩니다. Build with Gradle 스텝에서 위에서 캐싱된 의존성을 바탕으로 소소코드를 빌드합니다.
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Git Checkout
uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
cache: gradle
- name: Grant Execute Permission for Gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
YAML
복사
2. Docker 의존성 캐싱
•
Docker Image 빌드 과정에 필요한 의존성도 GitHub Actions에서 캐싱할 수 있습니다. 이를 위해 docker에서 제공하는 두 개의 레시피(docker/setup-buildx-action, docker/build-push-action)가 필요합니다.
•
docker/setup-buildx-action 을 실행하여 buildx으로 GitHub Actions의 Cache를 활용할 수 있도록 사전 작업을 합니다. 이후 docker/build-push-action 으로 docker image를 빌드할 때 cache-from, cache-to 옵션을 활용하여 캐싱된 의존성을 가져오고 의존성을 저장합니다.
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Docker Build and Push
uses: docker/build-push-action@v4
with:
context: .
push: true
cache-from: type=gha
cache-to: type=gha,mode=max
YAML
복사
III. 속도 개선: 도커 이미지 변경
1. 도커 베이스 이미지 변경
•
기존에 사용하던 도커 이미지가 불필요하게 큰 것은 아닌지 의심해야 합니다. AWS 기반으로 서비스를 운영한다면 amazoncoreetto를 사용하는 것도 좋은 선택입니다.
•
openjdk:11 와 비교했을 때 amazoncorretto:11 장점은 두 가지가 있습니다. 하나는 이미지 크기가 작다는 것입니다. 또 하나는 AWS에서 amazoncorretto:11 을 기준으로 2027년까지 성능과 보안 이슈에 대해 장기간 보증 기간을 갖고 지속적인 업데이트를 제공한다는 것입니다.
2. 베이스 이미지별 빌드 속도 테스트
1) docker image 크기 비교
•
amazoncorretto:11
: 200MB
•
openjdk:11
: 250MB
•
빌드된 도커 이미지 사이즈 비교
2) 베이스 이미지별 빌드 시간 비교 In Local
•
amazoncorretto:11
: 1.8s, 1.5s
: docker build --no-cache -t dam-server-before .
•
openjdk:11
: 3.9s, 3.4s
: docker build --no-cache -t dam-server-after .
3) 베이스 이미지별 빌드 시간 비교 in GitHub Actions
•
amazoncorretto:11
: 30s, 31s
•
openjdk:11
: 38s, 36s
IV. 속도 개선: 빌드 명령 수정
1. 빌드 명령 옵션
•
build --parallel
: 멀티 모듈 프로젝트의 각 모듈을 병렬적을 빌드할 수 있습니다. 병렬 빌드 옵션은 gradle 4.8 버전부터 지원합니다.
•
build --daemon
: gradle 6.0 이상부터 해당 옵션 기본 활성화되어 있습니다. dam-server의 경우 gradle version 7.0.2 사용 중이므로 --daemon 옵션은 기본적으로 활성화되어 있습니다.
2. 빌드 명령 옵션별 테스트
1) Local 환경 테스트
•
clean build --parallel
: 1m 30s, 1m 25s, 1m 29s
•
clean build
: 2m 24s, 2m 16s, 2m 9s
2) GitHub Actions 테스트
•
clean build --parallel
: 2m 45s, 2m 58s
•
clean build
: 7m 17s, 3m 5s, 4m 6s
참고
•
(공식문서) GitHub Actions 의존성 캐싱 원리, https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows
•
(공식 문서) Gradle 기반 빌드 속도 개선 방법, https://docs.gradle.org/current/userguide/performance.html#performance_gradle
•
(카카오 기술 블로그) Docker Caching in GitHub Actions, https://fe-developers.kakaoent.com/2022/220414-docker-cache/