[NextJS] Github Actions 빌드 속도 개선기

Katie·2024년 2월 15일
2

사이드프로젝트

목록 보기
12/13

문제 상황 & 결과

github actions로 dev 브랜치에 머지될 때 빌드 테스트와 도커/스토리북 배포를 자동화하였다. 프로젝트 규모가 커지다 보니 속도가 너어무 느려져서 6분이 넘어갔다..😭 거의 7분..

개선 전

개선 후 (결과)

기존 build-and-test

기존 build-storybook

개선 후 대략 3분 정도로 총 시간이 거의 절반이 줄었다!! 두 개의 워크플로우가 각각 돌아가기 때문에 약 7분 -> 약 2분으로 줄었다.
npm run build가 여전히 많은 시간을 차지하고 있지만 해결해가는 중이라 추후에 다시 다룰 예정!

해결과정

원인 파악

먼저, build-and-test는 Next 프로젝트를 빌드/테스트하는 과정이다.
npm run test:ci npm run build를 순서대로 진행하는데 프로젝트 패키지 설치 부분과 빌드 부분에서 제일 긴 시간이 걸렸다.

두번째 build-storybook는 현재 프로젝트에서 사용 중인 스토리북을 빌드하는 과정이다. 여기서 또한 package.json 설치 부분과 스토리북 빌드 시간이다.


마지막으로 프로젝트를 Docker의 이미지로 저장하고 스토리북을 github-pages로 배포하는 과정이다.
스토리북을 재빌드하고 도커 이미지로 저장하는 과정에서 많은 시간을 잡아먹고 있었다.

개선 과정

워크플로우 분리

먼저, Next 프로젝트 워크플로우와 스토리북 빌드 배포 워크플로우를 분리하였다.
프로젝트 구조가 대략


    src
     ├── app
     │    
     ├── components
     │ 

이런 식으로 되어 있는데 스토리북을 사용하는 컴포넌트는 components폴더 내부에만 존재한다. 스토리북에 영향이 없는 app 안에 파일들을 변경하더라도 스토리북 빌드 및 배포가 되어있기 때문에 비효율적이라고 생각되어 타켓 path를 지정해주어 분리하였다.

on:
  push:
    paths:
      - '.storybook/**'
      - 'src/components/**'

  pull_request:
    paths:
      - '.storybook/**'
      - 'src/components/**'

중복 빌드 개선

스토리북 빌드 테스트 후 배포 과정에서 빌드 과정이 중복되는 것을 해결하면서 시간을 더 단축하였다.
artifact를 사용하여 빌드 파일을 업로드 후 배포 과정에서 다운로드하여 사용하였다.
기존 72s -> 0s

 - name: Build Storybook
        run: npm run build-storybook

      - name: Upload Storybook build
        uses: actions/upload-artifact@v4
        with:
          name: storybook
          path: ./storybook-static
          
## ...

- name: Download Storybook build
        uses: actions/download-artifact@v4
        with:
          name: storybook
          path: ./storybook-build/storybook

패키지 설치 시간 단축

매 워크플로우마다 패키지를 설치하여 많은 시간이 소요되었다. package-lock.json이 변경될 때만 패키지 설치를 진행하여 패키지 설치 시간을 줄였다. NextJS와 스토리북 워크플로우에 모두 적용하여 시간을 단축하였다.
기존 39s -> 5s

 - name: Cache dependencies
        id: cache
        uses: actions/cache@v4
        with:
          path: '**/node_modules'
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - name: Install dependencies
        if: steps.cache.outputs.cache-hit != 'true'
        run: npm ci

도커 이미지 캐싱 적용

Docker 이미지 빌드 후 캐싱을 하여 다음 이미지 생성 시 이전에 빌드된 Docker 이미지를 캐시로 사용하도록 설정하였다.
기존 93s -> 6s

cache-fromcache-to를 사용하여 이전에 빌드된 레이어 재사용

- name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/connection-frontend:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max

결론

약 7분 정소 소요되었던 워크플로우가 약 2분 + 1분 이내로 절반 이상 시간이 단축되었다.
두 워크플로우가 독립적으로 돌아가니 체감시간으로는 7분 -> 2분
Github Actions 전체코드

profile
이것 저것 코딩일지 쓰는 프론트엔드 코린이

0개의 댓글