IT일상

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

  • 프론트엔드
  • 인프라
Profile picture

Written by solo5star

2023. 2. 24. 16:02

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

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

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

GitHub Actions

1

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

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

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

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

GitHub Actions workflow 추가하기

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

4

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

5

Webpack 을 선택하세요.

6

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

workflow 실행 조건 설정

webpack.yml
name: NodeJS with Webpack

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

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

webpack.yml
name: NodeJS with Webpack

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

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

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

workflow jobs 구성하기

webpack.yml
name: Example Workflow

on:
  push:
    branches: [main]

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들이 완료된 후 수행됩니다!

webpack.yml
 name: NodeJS with Webpack
 
 on:
   push:
     branches: [step2]
 
+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 폴더에 빌드된 파일들이 생성되는데, 이는 각자 다를 수 있으니 개인의 프로젝트 설정에 따라 바꿔서 사용하면 됩니다!

GitHub Pages 설정

7

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

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

8 9

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

10

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

11

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

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

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

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

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

webpack.yml
 name: NodeJS with Webpack
 
 on:
   push:
     branches: [step2]
 
 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가 캐싱될 겁니다.

13

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

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

14

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

맺음말

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

읽어주셔서 감사합니다!


Profile picture

Written by solo5star

안녕하세요 👋 개발과 IT에 관심이 많은 solo5star입니다

  • GitHub
  • Baekjoon
  • solved.ac
  • about
© 2023, Built with Gatsby