IT일상

GitHub Actions: Webpack 빌드 + GitHub Pages 배포 자동화하기 본문

프론트엔드

GitHub Actions: Webpack 빌드 + GitHub Pages 배포 자동화하기

solo5star 2023. 2. 24. 16:02
리뉴얼 된 블로그로 보기: https://solo5star.dev/posts/26/

 

$ webpack --mode production
$ git commit -m "build: 웹 페이지 Webpack 빌드"
$ git push origin main # 이러한 과정을 매 커밋마다 반복

커밋할 때 마다 빌드를 하고, 배포를 하시나요?

 

더 이상 그러지 않아도 됩니다.

 

 

GitHub Actions

GitHub에서 제공하는 CI/CD 도구입니다. CI/CD는 간단하게 말하자면 빌드, 테스트, 배포를 자동화하는 것을 뜻합니다. 지금 이 글에서 하고자 하는 것입니다.

 

workflow가 성공적으로 수행되었을 때
workflow가 진행중일 때, 실패했을 때

 

GitHub 에서 커밋 오른쪽에 ✔ 체크 아이콘을 본 적 있나요? GitHub에 커밋이 push될 때 마다 자동으로 GitHub Actions가 수행되고, 만약 성공적으로 수행된 경우 표시되는 아이콘입니다. (실패하면 ❌ 표시가 뜨겠죠?)

 

위의 사진은 webpack 빌드 + gh-pages 브랜치에 배포를 수행하도록 되어 있습니다.

 

 

GitHub Actions workflow 추가하기

수행하는 GitHub Actions 작업을 workflow라고 합니다. 이 글에서는 webpack 빌드 + gh-pages 브랜치에 파일을 올리는 workflow를 만드는 과정을 진행할 것입니다.

 

GitHub 레포지토리에서 Actions 탭으로 이동하세요.

 

Webpack 을 선택하세요.

 

.github/workflows/webpack.yml 이라는 파일을 추가하는 창이 뜰텐데, 위에서 부터 하나씩 설정해볼까요?

 

 

workflow 실행 조건 설정

name: NodeJS with Webpack

on:
  # step2 라는 브랜치에 커밋을 push할 때 마다 실행되도록 합니다.
  push:
    branches: [step2]
  # PR이 생성될 때 마다 실행되게 하려면 아래의 주석을 지우세요!
  #pull_request:
  #  branches: [step2]

on 부분은, 어떤 조건에서 workflow를 실행할 것인지 설정합니다. 저는 step2 브랜치에 커밋이 올라올 때 마다 수행되도록 설정하였습니다.

 

on:
  schedule:
    - cron: '*/20 * * * *' # 20분 주기로 실행

20분, 1시간 같은 ⏰ 시간 주기로 실행하는 것도 가능합니다.

 

최소 5분 주기로 설정할 수 있긴 하지만, 5분이라는 시간이 정확히 지켜지진 않습니다. 가끔씩 지연이 심해서 2배, 3배 늦게 수행될 수도 있습니다. (경험담)

 

 

workflow jobs 구성하기

jobs:
  build-prepare-1:
    name: Build Prepare 1
  build-prepare-2:
    name: Build Prepare 2
  deploy:
    name: Deploy
    needs: [build-prepare-1, build-prepare-2]

jobs 에는 수행할 작업(job)들을 정의할 수 있습니다. 기본적으로 병렬로 수행되지만, needs 를 추가하면 해당 job들이 완료된 후 수행됩니다!

 

jobs:
  # deploy 라는 job 입니다.
  # 안에는 배포에 필요한 과정들을 기술하면 됩니다!
  deploy:
    runs-on: ubuntu-latest # 우분투에서 실행
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}

    steps:
    # 레포지토리의 코드를 사용하기 위해 씁니다. 이게 없으면 빈 폴더에요!
    - uses: actions/checkout@v3

    # node.js 를 사용합니다.
    - uses: actions/setup-node@v3
      with:
        node-version: 18 # 버전은 입맛대로 바꾸세요

    - run: npm ci # package-lock.json 에 적혀있는 패키지를 그~대로 설치합니다.
    - run: npm run build-step2 # package.json에 빌드 스크립트를 여기 적으세요
    
    # publish_dir에 들어있는 파일들을 gh-pages 브랜치에 올려줍니다.
    - uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./dist

job을 하나만 정의했습니다. job 안에는 여러 개의 step으로 구성되어 있는데요, 상세한 내용은 주석을 참고해주세요.

 

저의 경우 npm run build-step2 명령으로 빌드하고 /dist 폴더에 빌드된 파일들이 생성되는데, 이는 각자 다를 수 있으니 개인의 프로젝트 설정에 따라 바꿔서 사용하면 됩니다!

 

 

workflow 전체 코드

name: NodeJS with Webpack

on:
  # step2 라는 브랜치에 커밋을 push할 때 마다 실행되도록 합니다.
  push:
    branches: [step2]

jobs:
  # deploy 라는 job 입니다.
  # 안에는 배포에 필요한 과정들을 기술하면 됩니다!
  deploy:
    runs-on: ubuntu-latest # 우분투에서 실행
    permissions:
      contents: write
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}

    steps:
    # 레포지토리의 코드를 사용하기 위해 씁니다. 이게 없으면 빈 폴더에요!
    - uses: actions/checkout@v3

    # node.js 를 사용합니다.
    - uses: actions/setup-node@v3
      with:
        node-version: 18 # 버전은 입맛대로 바꾸세요

    - run: npm ci # package-lock.json 에 적혀있는 패키지를 그~대로 설치합니다.
    - run: npm run build-step2 # package.json에 빌드 스크립트를 여기 적으세요
    
    # publish_dir에 들어있는 파일들을 gh-pages 브랜치에 올려줍니다.
    - uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./dist

 

 

GitHub Pages 설정

gh-pages 브랜치에 있는 파일들을 GitHub Pages로 배포될 수 있도록 레포지토리 > Settings > Pages > Build and deployment 에서 스크린샷과 같이 설정해주세요.

 

gh-pages 브랜치의 / 디렉토리 파일들을 사용한다는 뜻입니다.

 

레포지토리에 커밋을 올릴 때 마다 workflow가 잘 실행되는지도 확인하시구요~! 혹여나 문제가 발생했다면 터미널 출력을 확인하여 문제를 해결하면 됩니다.

 

gh-pages 브랜치에 빌드된 파일들이 잘 올라갔는지도 확인하구요,

 

마지막으로 GitHub Pages 배포까지 확인하면 완료입니다! 간단하죠?

 

 

심화: 의존성(node_modules) 캐싱하기

Run npm ci 가 9초 걸립니다. (전체 수행 시간의 약 40%)

위의 내용대로 진행해도 빌드가 잘 진행될겁니다. 다만, GitHub Actions가 실행될 때마다 매번 npm ci 명령을 통해 의존성들을 설치하는데, 이것 때문에 workflow 수행 시간이 오래 걸릴겁니다. (즉 node_modules 폴더가 매번 생성된다고 생각하면 됩니다.)

 

의존성(npm 패키지)을 추가하는 일은 그렇게 많지 않을텐데, 그럼 이전에 썼던 node_modules를 재활용하는 방법은 없을까요? 그.럴.때 쓰는 것이 바로 cache 입니다!

 

jobs:
  deploy:
    runs-on: ubuntu-latest
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}

    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-node@v3
      with:
        node-version: 18
 
    - uses: actions/cache@v3
      id: cache
      with:
        path: '**/node_modules' # node_modules 폴더를 캐싱합니다
        # package-lock.json 파일이 변경되었을 때 캐시될 수 있게 합니다
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
        # cache hit이 발생하지 않았을 경우, restore-keys 에 있는 것을 꺼냅니다.
        # 단, npm ci 명령은 실행됩니다. 기존의 node_modules 캐시를 기반으로
        # 추가된 패키지만 설치할테니, 아예 처음부터 node_modules 폴더를 생성하는 것보다
        # 시간이 적게 걸릴 겁니다.
        restore-keys: |
          ${{ runner.os }}-node-

    - run: npm ci # 이게 무거운 작업입니다.
      # cache hit이 발생한 경우 (즉 package-lock.json이 변경되지 않은 경우)
      # npm ci 실행은 skip합니다.
      if: steps.cache.outputs.cache-hit != 'true'

    - run: npm run build-step2

    - uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./dist

actions/cache@v3를 추가하였습니다. 설명은 주석으로 상세히 설명하였으니 참고해주세요!

 

위와 같이 설정하면 node_modules가 캐싱될 겁니다.

 

Actions 탭에 Caches 에서 캐시된 내용을 확인할 수 있습니다.

 

package-lock.json 파일을 변경하지 않는 한, 위의 캐시를 사용할 겁니다.

 

actions/cache@v3 을 추가한 후 커밋을 하면, Cache를 사용하고 npm ci 단계를 건너뛴 것을 확인할 수 있습니다. (만약 처음 실행하는 것이라면 캐시를 생성하기 위해 Install Dependencies 단계를 수행할 것입니다)

 

 

맺음말

GitHub Actions를 잘 활용하면 개발자 삶의 질을 높일 수 있습니다. 수동으로 빌드, 배포하는 것이 여간 귀찮은 일이 아닙니다 ... 이 글에서는 빌드와 배포만 다루었지만 테스트 같은걸 넣기도 합니다. 테스트를 추가하면 커밋 했을 때 이게 제대로 된 커밋✔인지 확인할 수 있겠죠?

 

읽어주셔서 감사합니다!

Comments