[github-actions] 리액트 빌드하기

스윗포테이토·2022년 12월 31일
2

지난 글에서 언급 했었지만, 프리티어로 사용 중인 t2.micro 인스턴스가 자꾸만 빌드 과정에서 뻗어버리는 일이 발생했다. 처음에는 도커를 사용해서 생기는 문제인 줄 알았지만, 몇번 시도해보니 항상 npm build를 하던 중에 죽어버리더라... 따라서 github actions를 활용해서 빌드를 해서 인스턴스에 빌드 파일을 올려서 돌리기로 했다.

우선 요구사항은 다음과 같다.

프론트엔드 소스코드가 변경될 때, 리액트를 빌드해서 빌드 파일을 EC2 인스턴스에 옮겨두기!

좀 더 뜯어보자면
1. 프론트엔드 소스코드가 변경될 때
2. 리액트를 빌드해서
3. EC2 인스턴스에 반영하기
로 나누어 볼 수 있다.

1. 프론트엔드 소스코드가 변경될 때

on:
  push:
    branches:
      - develop
    paths:
      - client/src/*
      - client/public/*

우선 develop 브랜치에 Push 될 때를 기준으로 했다.
개발하는 과정에서 사용하는 README, Dockerfile 등의 변경에 영향을 받지 않도록 src, public 파일만 트리거로 등록해 두었다.

2. 리액트를 빌드해서

이 과정은 좀 더 작은 단위로 쪼개볼 수 있다.
1. 노드 설치
2. npm 패키지 설치
3. 빌드하기
4. 빌드 결과물 압축

  1. 노드 설치에서 중요한 것은 노드 버전을 사용하는 버전과 맞춰야 한다는 것이다.
    우선 checkout를 사용해서 Runner에 소스코드를 반영한 후, setup-node 액션을 사용해서 노드 버전을 16.14.1로 맞춰주었다.

          - uses: actions/checkout@v2
          - uses: actions/setup-node@v2
            with:
              node-version: 16.14.1
  2. npm package 설치
    npm package를 설치 하는 부분은 step을 나누기 위해 name으로 구분해주었다.

          - name: Install Dependencies
            run: cd client && npm install --production
  3. 빌드하기
    이 과정에서 중요한 것은 환경변수를 넣어주는 것이다. 원래는 .env 파일을 직접 넣어주었지만, 깃헙에 env 파일을 넣지는 않기 때문에 여기서 환경 변수로 등록을 해주는 것이다.
    환경 변수는 직접 문자열로 넣을 수는 있지만, 이 workflow 파일도 깃허브에 올라가는 파일인 만큼 secret에 등록해두고 사용하는 것을 권장한다.
    (참고: github workflow)

          - name: Build
            run: cd client && npm run build
            env:
              REACT_APP_API_KEY: ${{ secrets.DEV_REACT_APP_API_KEY }}
              ...

    이렇게 하면 빌드까지 끝나게 된다.

  4. 빌드 결과물 압축
    사실 이 부분은 EC2 인스턴스에 옮기기 위한 사전 작업이다. 빌드 파일을 폴더로 옮길 수도 있지만, 압축 파일을 한번에 전송하고 서버에서 압축을 푸는 방식을 선택했다.

          - name: Package Application
            run: cd client && tar -czvf build.tar.gz build

3. EC2 인스턴스에 옮기기

EC2 pem키를 사용해서 접속한 후, scp 명령어를 통해 직전단계를 통해 생성된 압축파일을 EC2로 옮기면 된다. appleboy의 scp-action을 활용하였다.

      - name: scp to EC2
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.DEV_EC2_IP_ADDRESS }}
          username: ${{ secrets.DEV_EC2_USER }}
          key: ${{ secrets.DEV_EC2_PRIVATE_KEY }}
          source: client/build.tar.gz
          target: path-to-server-build-file

사실 여기서 상단의 모든 프로세스는 끝난 셈이다. 여기까지 진행하면 서버에는 build.tar.gz 파일이 올라와 있고, 남은 과정은 서버에서 진행하면 된다. 그러나 이왕 github actions를 만들었으니 끝까지 자동화를 해보도록 하자.

서버에 이후 배포 과정을 담은 쉘 스크립트를 작성해준다.

#!/bin/sh

cd client # 위치 이동
sudo tar -xzvf build.tar.gz # 압축파일 압축 해제
... # 이후 배포 과정

이후 workflow에 저 쉘 스크립트를 실행할 step을 하나 더 추가해주면 프론트엔드 배포 자동화를 구축하게 된다!
EC2 인스턴스에 명령어를 전달하기 위해 appleboy의 ssh-actions를 사용했다.

    - name: execute shell script
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.DEV_EC2_IP_ADDRESS }}
        username: ${{ secrets.DEV_EC2_USER }}
        key: ${{ secrets.DEV_EC2_PRIVATE_KEY }}
        script: "cd path-to-shell-script; ./deploy-build-file.sh"

전체 workflow

name: build react app for development server

on:
  push:
    branches:
      - develop
    paths:
      - client/src/*
      - client/public/*
jobs:
  build-and-deploy-react-app-for-development-server:
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: 16.14.1
      - name: Install Dependencies
        run: cd client && npm install --production
      - name: Build
        run: cd client && npm run build
        env:
          REACT_APP_API_KEY: ${{ secrets.DEV_REACT_APP_API_KEY }}
          ...
      - name: Package Application
        run: cd client && tar -czvf build.tar.gz build
      - name: scp to EC2
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.DEV_EC2_IP_ADDRESS }}
          username: ${{ secrets.DEV_EC2_USER }}
          key: ${{ secrets.DEV_EC2_PRIVATE_KEY }}
          source: client/build.tar.gz
          target: path-to-server-build-file
      - name: execute shell script
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.DEV_EC2_IP_ADDRESS }}
          username: ${{ secrets.DEV_EC2_USER }}
          key: ${{ secrets.DEV_EC2_PRIVATE_KEY }}
          script: "cd path-to-shell-script; ./deploy-build-file.sh"

참고

github workflow
appleboy/scp-action
appleboy/ssh-action

profile
나의 삽질이 미래의 누군가를 구할 수 있다면...

0개의 댓글