지난 글에서 언급 했었지만, 프리티어로 사용 중인 t2.micro 인스턴스가 자꾸만 빌드 과정에서 뻗어버리는 일이 발생했다. 처음에는 도커를 사용해서 생기는 문제인 줄 알았지만, 몇번 시도해보니 항상 npm build
를 하던 중에 죽어버리더라... 따라서 github actions를 활용해서 빌드를 해서 인스턴스에 빌드 파일을 올려서 돌리기로 했다.
우선 요구사항은 다음과 같다.
프론트엔드 소스코드가 변경될 때, 리액트를 빌드해서 빌드 파일을 EC2 인스턴스에 옮겨두기!
좀 더 뜯어보자면
1. 프론트엔드 소스코드가 변경될 때
2. 리액트를 빌드해서
3. EC2 인스턴스에 반영하기
로 나누어 볼 수 있다.
on:
push:
branches:
- develop
paths:
- client/src/*
- client/public/*
우선 develop 브랜치에 Push 될 때를 기준으로 했다.
개발하는 과정에서 사용하는 README, Dockerfile 등의 변경에 영향을 받지 않도록 src, public 파일만 트리거로 등록해 두었다.
이 과정은 좀 더 작은 단위로 쪼개볼 수 있다.
1. 노드 설치
2. npm 패키지 설치
3. 빌드하기
4. 빌드 결과물 압축
노드 설치에서 중요한 것은 노드 버전을 사용하는 버전과 맞춰야 한다는 것이다.
우선 checkout를 사용해서 Runner에 소스코드를 반영한 후, setup-node 액션을 사용해서 노드 버전을 16.14.1
로 맞춰주었다.
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 16.14.1
npm package 설치
npm package를 설치 하는 부분은 step을 나누기 위해 name으로 구분해주었다.
- name: Install Dependencies
run: cd client && npm install --production
빌드하기
이 과정에서 중요한 것은 환경변수를 넣어주는 것이다. 원래는 .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 }}
...
이렇게 하면 빌드까지 끝나게 된다.
빌드 결과물 압축
사실 이 부분은 EC2 인스턴스에 옮기기 위한 사전 작업이다. 빌드 파일을 폴더로 옮길 수도 있지만, 압축 파일을 한번에 전송하고 서버에서 압축을 푸는 방식을 선택했다.
- name: Package Application
run: cd client && tar -czvf build.tar.gz build
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"
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"