GitHub Actions 기반의 CD 속도 개선

Denia·2024년 2월 28일
0

TroubleShooting

목록 보기
21/24
post-thumbnail

며칠 전에는 FrontBuild CI의 속도를 개선해봤습니다.

해당 글을 참조 해주시면 됩니다.

GitHub Actions 기반의 CI 속도 개선 [Vue.js Build]

오늘은 CD쪽의 속도를 개선해보겠습니다.


1. npmnode_modules 캐싱하기

workflow의 로그를 살펴보니, 며칠전에 개선한 npm의존성 캐싱이 적용이 되어있지 않았습니다.

그래서 제일 먼저, npmnode_modules에 캐싱을 적용 해주겠습니다.

기존 yaml 코드

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
	  
      ... 생략 # Set up JDK 17, # Grant execute permission for gradlew

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@ec92e829475ac0c2315ea8f9eced72db85bb337a # v3.0.0

      - name: Build with Gradle Wrapper
        run: ./gradlew build
        working-directory: ./my-garden-be

수정된 yaml 코드

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      ... 생략 # Set up JDK 17, # Grant execute permission for gradlew

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@ec92e829475ac0c2315ea8f9eced72db85bb337a # v3.0.0

      # 캐시 추가
      - name: Check node modules cache
        id: cache
        uses: actions/cache@v4
        with:
          path: '**/node_modules'
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      # 캐시가 존재하므로, npmInstall 과정을 생략
      - name: Build with Gradle Wrapper (skip npm install)
        if: steps.cache.outputs.cache-hit == 'true'
        run: ./gradlew build -x npmInstall
        working-directory: ./my-garden-be

      # 캐시가 존재하지않으므로, npmInstall 진행
      - name: Build with Gradle Wrapper (npm install)
        if: steps.cache.outputs.cache-hit != 'true'
        run: ./gradlew build
        working-directory: ./my-garden-be

이전 글에서 설명드렸던 내용과 거의 비슷합니다.

  1. node_modules를 찾아서 캐싱을 합니다. (캐시 키는 package-lock.json)
  2. 키가 같으면, node_modulesload하고 cache-hittrue로 설정 // 키가 없으면, cache-hitfalse로 설정
  3. cache-hit에 따라서 npmInstall을 생략하거나 포함해서 gradle build가 진행됩니다.

캐싱하기 전에는 보시는 것처럼 vite Build 전에, 무조건 npmInstall이 진행이 되었고 약 10초 정도의 시간이 소모됐습니다.

저장된 캐시가 없다면 캐시를 저장하는 과정에서 시간이 약 6초 정도 더 걸리긴 하지만,
한번 캐싱이 되면 보시는 것처럼 약 10초 정도 되던 npmInstall 과정이 생략됩니다.

캐시가 없을 때, 새로 save하는 step (약 6초 소요)

캐시가 존재할 때, load 하는 step (약 2초 소요)

캐시 load시에 약 2초 정도 걸리긴 하지만,
npmInstallskip함으로써 약 10초의 시간을 아꼈기 때문에 대략 약 7초 ~ 8초의 시간을 절약할 수 있었습니다.


2. Docker 캐시 삭제하기

CD workflow에서 docker image를 빌드하는 순서는 먼저 docker buildx를 설치하고, 해당 buildx를 이용하여 docker imagebuild 합니다.

여기서 Build and push를 살펴보면, 조금 특이한 점이 있습니다.
로그를 살펴보면서 설명을 드리겠습니다.

아래의 이미지는 Build and push의 로그입니다.

1번 내용이 docker imagebuild하는 부분이고,
2번은 해당 image를 캐싱하기 위해 준비하고 추출하는 과정입니다.

imagebuild 하는 시간 (3.3 + 1.0 = 4.3s) 보다, 캐싱을 하는 시간 (5.2s)이 더 긴 것을 보실 수 있습니다.

제 프로젝트에서는 완성된 이미지를 캐싱해도, 다시 재사용할 일이 없기 때문에 캐싱을 사용하지 않는 것이 시간 절약에 더 좋다는 판단을 내렸습니다.

그래서 해당 캐싱을 제거하여 시간을 조금이라도 단축시켜보겠습니다.

완성된 이미지를 재사용 하지 않는 이유에 대해서도 설명을 드리겠습니다.

현재 제 프로젝트는 docker image를 사용하여 CD를 진행하고 있으며, 해당 docker imagejdk17-alpine 위에 jar파일을 복사하여 실행시키는 구조입니다.
(※ jar파일은 GitHub Action Runner Instancedocker image를 만들기 전 step에서 gradlebuild를 합니다.)

매번 CD를 진행할 때마다 새로 jarbuild를 해서 배포하기 때문에, 캐싱된 데이터가 재사용 되지 않습니다.

기존 yaml 코드

# docker buildx 설치
- name: Set up docker buildx
  uses: docker/setup-buildx-action@v3

... 생략 # GitHub Container Registry에 로그인

# Docker 빌드 & GitHub Container Registry에 푸시
- name: Build and push
  uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: ${{ env.DOCKER_IMAGE }}:latest
    cache-from: type=gha
    cache-to: type=gha, mode=min

수정된 yaml 코드

# docker buildx 설치
- name: Set up docker buildx
  uses: docker/setup-buildx-action@v3

... 생략 # GitHub Container Registry에 로그인

# Docker 빌드 & GitHub Container Registry에 푸시
- name: Build and push
  uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: ${{ env.DOCKER_IMAGE }}:latest

build-push-action 액션의 옵션인 cache-fromcache-to를 제거하여, 캐시를 사용하지 않도록 했습니다.

캐시를 추출하던 과정이 사라진 것을 보실 수 있습니다.

캐시를 제거함으로써 캐시를 추출하던 시간을 아꼈기 때문에 대략 약 5초의 시간을 절약할 수 있었습니다.


결과 확인

  • 속도를 개선하기 전과 개선을 완료한 후를 비교하면, 1분 40초1분 25초 (약 15%의 성능 향상)

  • docker imagebuild하는 job 기준 (deploy 하는 시간은 고정적이므로 제외)

    상황npm 의존성 캐싱 Xnpm 의존성 캐싱 O
    도커 캐싱 O1분 40초1분 31초
    도커 캐싱 X측정 안함1분 25초

참고 자료

profile
HW -> FW -> Web

0개의 댓글