Github actions로 리액트 자동배포하기(S3, EC2, Code Deploy, Centos, Nginx, React.js)

Namu CHO
20 min readJul 14, 2021

부제: AWS, 서버 둘 다 잘 몰라도 할 수 있다!

하게 된 이유

wsl2에서 개발한 다음 빌드, 빌드된 파일을 윈도우로 다운로드 받은 후에 그 파일을 다시 EC2로 옮기는 일련의 작업을 매번 반복하는게 귀찮았다.

(또한 수정이 매우 잦았음, 배포를 많이 해야했다는 뜻임, 예- “여기 2px만 줄여주세요.” 등 작고 잦은 수정들)

개발환경

S3, EC2는 회사에서 이미 인스턴스를 만들어서 주셨다.

본인은 IAM등 권한설정만 바꾸면 되었다.

사용하는 EC2의 경우 리눅스 CentOS 운영체제이고 Nginx를 사용한다.

github actions를 사용한 이유

CI/CD를 하기 위한 다양한 방법들 중에 github actions를 사용한 이유는

우선 나는 깃에 푸쉬하면 빌드 후에 배포하는 작업을 하고 싶었는데,

그 과정에서 서드파티 없이 깃으로만 할 수 있다는 게 매력적으로 느껴졌었다(더 간단할 것 같은 느낌).

그리고 앞으로 나머지 유명한 젠킨스나 circle CI도 이용하며 장단점을 비교해볼 생각이다

(직접 해보는 것이 각각의 장단점을 판단하기에 최고라고 생각한다).

하는 법

우선 본인은 회사에서 S3와 EC2 인스턴스를 이미 생성해서 주셨기 때문에

두 인스턴스 생성 방법은 건너 뛰겠다.

S3와 EC2 인스턴스 생성관련 참고링크:

  1. EC2 생성

: https://isntyet.github.io/deploy/github-action과-aws-code-deploy를-이용하여-spring-boot-배포하기(2)/

위 링크에서 ‘EC2 생성’을 검색해보세요.

  1. S3 생성

: https://isntyet.github.io/deploy/github-action과-aws-code-deploy를-이용하여-spring-boot-배포하기(3)/

위 링크에서 ‘배포용 S3 생성’을 검색해보세요.

우선 어떻게 돌아가는지 간략하게 알아보자.

본인은 aws와 서버에 대한 지식이 거의 전무한 상태라서 많이 헤맸다.

나와 같은 분들이 흐름을 한 번 알고 가면 좋을 것 같아서 간략한 설명을 덧붙이겠다.

설명 1. 진행 흐름

  1. 깃 푸쉬→ 빌드→ S3저장소에 파일 업로드(by github actions)
  2. S3에 있는 파일을 EC2에 업로드(by code deploy)

우선 S3는 저장소이다.

(EC2만 써본 본인은 S3가 EC2같은 일반 서버인줄 알고 github actions에서 s3로만 올리면 모든 일이 다 끝나는 줄 알았다.)

따라서 s3는 파일을 저장해놓을 뿐이고 이를 서버(EC2)에 뿌려주고 싶으면 code deploy의 도움이 필요로 하는 것이다.

덧, 본인은 왜 S3 → code deploy → ec2라는 복잡한 단계를 거쳐야 하는가 하는 의문이 들었다.

조금 찾아본 결과, 깃헙액션은 바로 ec2에 접근하여 명령을 수행할 수 없고

코드 디플로이는 저장공간이 없고 단지 역할만 수행하기 때문에 이런 단계가 생기는 것 같았다.

왜 이런 단계를 거쳐야 하는지, 단계를 더 줄일 수 는 없는지 등을 더 찾아서 업데이트 하겠다.

설명 2. 권한설정

위의 단계를 밟기 위해서는 github actions와 code deploy가 각각 나의 s3, ec2에 접근해서 일련의 작업을 할 수 있는 권한을 설정해줘야 한다.

앞으로의 단계에서 이러한 작업을 진행해줄 것이다(IAM 설정).

설명 3. EC2 CodeDeploy agent 설치

EC2에 코드 디플로이가 접근하여 파일을 올릴 수 있도록 code deploy agent를 설치해야 한다.

당연한 부분이지만 혹시 빼먹을 수도 있으니 리마인드 차원에서 정리하였다.

설치 방법은 아래에서 설명하겠다.

설명 4. 오탈자 조심!

여러 블로그 글을 참조하며 코드를 작성하다 보니, 명령어가 조금씩 달랐다.

처음에 본 곳에는 S3업로드 코드에 recursive라는 코드가 있었는데,

이 코드를 넣으면 zip파일로 업로드가 계속 안 되었었다.

그 외에도 키값을 Name으로 꼭 지정해줘야 하는 등, 너무 사소하지만 놓치면 몇 시간이 날아가는 포인트들을 잘 지켜줘야 한다.

이런 식으로 명령어의 역할을 모두 꿰고 있지 못하니 필요 없는 부분을 판단할 수 없었기 때문에 많이 헤맸다.

설명 5. CodeDeploy 실행여부, 로그를 잘보자!

본인은 EC2가 이미 생성된 상태였기 때문에 CodeDeploy 를 설치하고 추후에 EC2 CodeDeploy 정책을 추가했다.

이러한 경우 CodeDeploy 를 리스타트해줘야 하는데, 하지 않았기 때문에 오류가 오랜 시간 났다.

그리고 이 문제를 해결할 수 있었던 것은 CodeDeploy 의 로그를 봤기 때문이다.

AWS 콘솔에서는 에러와 관련한 메시지를 구체적으로 주지 않기 때문에 배포 실패 시 꼭 로그를 찾아봐야 한다.

로그는 아래 경로에서 확인 가능하다.

/var/log/aws/codedeploy-agent/

STEP 1. EC2 설정

EC2에 CodeDeploy agent 설치

Ubuntu: https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html

Centos: https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-linux.html

EC2에 코드 디플로이가 접근하여 파일을 올릴 수 있도록 code deploy agent를 설치해야 한다.

sudo yum updatesudo yum install rubysudo yum install wget# 본인은 이 부분이 헷갈렸는데, 홈 뒤에 폴더는 서버가 기본으로 만들어준 폴더명을 넣으면 된다.
# 본인의 경우에는 /home/centos였다.
cd /home/ec2-user
# wget <https://bucket-name.s3.region-identifier.amazonaws.com/latest/install>
# northeast-2 리전의 경우 아래 명령어를 사용하면 된다.
wget <https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install>
chmod +x ./installsudo ./install auto# 서비스가 실행 중인지 확인하려면 다음 명령을 실행합니다.
# The AWS CodeDeploy agent is running. 와 같은 메시지가 출력되면 성공
sudo service codedeploy-agent status
  • awscli 설치 및 사용자 설정도 필요한데 이는 뒤에서 진행할 예정이다(IAM 사용자 생성 후 진행).

EC2 IAM 설정

https://console.aws.amazon.com/iamv2/home#/roles

EC2가 s3와 codeDeploy를 이용할 수 있도록 권한 설정을 해줘야 한다.

✔ IAM를 생성한다.

  • IAM → 역할 → 역할 만들기
  • EC2를 선택하고 ‘다음’버튼 클릭
  • 권한 정책 연결

1. AWSCodeDeployFullAccess

2. AmazonS3FullAccess

두 개의의 권한을 체크해준다.

  • 그 다음 단계인 태그 추가는 건너 뛰어도 된다(본인은 건너뜀).
  • 역할 이름을 설정하고 정책을 잘 선택했는지 확인한다.

✔ 생성 확인

✔ 생성이 된 IAM를 EC2에 연결해준다.

  • 보안 → IAM 역할 수정에서 진행한다.
  • 연결 후에는 ec2 인스턴스를 재부팅 해준다.
  • 만들어둔 IAM role을 선택한다.
전(before)

(인스턴스를 찾을 수 없어서 https://isntyet.github.io/deploy/github-action과-aws-code-deploy를-이용하여-spring-boot-배포하기(2)/ 이 곳의 이미지를 가져왔다.)

https://isntyet.github.io/deploy/github-action과-aws-code-deploy를-이용하여-spring-boot-배포하기(2)/ 에서 가져온 이미지
  • 연결완료되었다는 메시지가 뜬다.

STEP 2. CodeDeploy

CodeDeploy IAM 설정

CodeDeploy가 S3에서 파일을 받아서 EC2에 올려야 하기 때문에 해당 작업을 위한 권한 설정이 필요로 하다.

✔ IAM를 생성한다.

  • IAM → 역할 → 역할 만들기
  • CodeDeploy를 선택하고 화면 하단에 CodeDeploy를 선택한다.
  • 선택되어있는 역할 그대로 놔두고 ‘다음’ 버튼을 누른다.
  • 다음 스텝은 건너뛰어도 된다(본인은 건너 뛰었음).
  • 이름을 설정하고 생성완료하기

✔ 생성 확인

완료

CodeDeploy 애플리케이션 생성, 설정(배포그룹 설정)

✔ 애플리케이션 생성한다.

https://ap-northeast-2.console.aws.amazon.com/codesuite/codedeploy/application/new?region=ap-northeast-2

권한을 설정해줬으니 CodeDeploy 어플리케이션을 생성해줘야한다.

  • CodeDeploy → 애플리케이션 → 애플리케이션 생성

!! 주의! 여기에서 컴퓨팅 플랫폼은 반드시 ‘EC2/온프레미스’를 선택한다.

✔ 배포 그룹을 생성한다.

배포를 하기 위해선 배포그룹이 필요하다.

화면 하단 오른편의 버튼을 눌러 배포그룹을 만들어준다.

  • 설정 1: 이름, 서비스 역할

서비스 역할의 경우에는 인풋창 클릭 시 자동으로 아까 생성해둔 IAM가 뜬다.

  • 설정 2: 배포유형, 환경 구성

배포유형은 ‘현재 위치’로 설정한다.

환경구성은 ‘Amazon EC2 인스턴스’를 체크하고

!!!중요! 태그 그룹의 키는 꼭 Name으로 설정한다.

참고: https://yeonyeon.tistory.com/72
  • 설정 3: 배포 설정, 로드밸런서

‘AWS Systems Manager를 사용한 에이전트 구성’은 건들이지 않았다.

배포 설정도 설정 되어있는 그대로 두고(CodeDeployDefault.AllAtOnce),

로드 밸런서의 ‘로드 밸런싱 활성화’ 체크박스를 해지한다.

전반적으로 이렇게 설정하면 된다.

STEP 3. Github actions

깃헙 액션이 S3에 접근하여 파일을 업로드 할 수 있도록 IAM 사용자 추가 및 권한 설정을 해준다.

AWS IAM 사용자 추가

https://console.aws.amazon.com/iam/home?region=ap-northeast-2#/users

  • ‘사용자 추가’ 버튼을 눌러 사용자를 추가한다.
  • 액세스 유형은 ‘프로그래밍 방식 액세스’를 선택한다.
  • ‘기존 정책에 직접 연결’, AmazonS3FullAccess, CodeDeployFullAccess 정책을 선택한다.
  • 다음 단계는 건너 뛰어도 된다(본인은 건너 뜀).
  • 설정 확인 후 ‘사용자 만들기’ 버튼 클릭

!!!중요!!! 생성이 완료 되면 accees-key와 secret-access-key가 생기는데

이걸 꼭 CSV파일로 저장해둬야 한다!

(캡쳐한 이미지가 없어서 https://isntyet.github.io/deploy/github-action과-aws-code-deploy를-이용하여-spring-boot-배포하기(3)/님의 이미지를 첨부했습니다.)

https://isntyet.github.io/deploy/github-action과-aws-code-deploy를-이용하여-spring-boot-배포하기(3)/ 로부터 가져온 이미지

Key 등록

깃헙에 등록

AWS에 접근하여 작업하기 위한 액세스키들을 원하는 깃헙 리파지토리에 올려둬야 한다.

깃헙 리파지토리 → Settings → Secrets → New repository secret 버튼을 눌러 액세스 키들을 저장한다.

Name에 키 이름, Value에 아까 IAM 사용자 생성 후 발급받은 키를 넣으면 된다.

이름은 아무거나 지정하면 된다.

지정한 이름을 추후에 yml파일에 변수로 넣을 것이다.

(AWS_ACCESS_KEY_ID 에는 access-key

AWS_SECRET_ACCESS_KEY 에는 secret-access-key

AWS_REGION 에는 ap-northeast-2

이렇게 지정하면 무난할 것 같다.)

EC2에 등록

EC2에 awscli 설치 및 사용자 설정이 필요하다.

# 설치
$ sudo apt update
$ sudo apt install awscli
# 설치 확인
$ aws help
# 사용자 설정
$ aws configure
AWS Access Key ID [None]: 액세스 키를 입력AWS Secret Access Key [None]: 시크릿 액세스 키를 입력Default region name [None]: ap-northeast-2 # 혹시 리전이 다르면 해당 리전 기입Default output format [None]: 그냥 Enter 입력

yml 파일 만들기

위의 단계들을 통해 작업을 위한 환경세팅이 끝났다!

이제는 직접 명령어를 작성하여

어디 폴더에서 어디 경로에 파일을 업로드할 것인지 등을 지정할 차례이다.

이는 2단계로 진행이 된다.

  1. 깃헙의 업데이트 내용을 S3로 올리는 명령어 작성
  2. S3에 올린 내용을 코드 디플로이를 통해 EC2로 업로드하는 명령어 작성이다.

✔ 리액트 기준 이런 대략 프로젝트 폴더구조가 될 것이다.

✔ 우선 1번, 깃헙의 업데이트 내용을 S3로 업로드하는 yml 파일을 작성해보겠다.

  • 프로젝트의 루트 경로에 .github폴더를 만들고, 그 안에 workflows 폴더를 생성하고 그 안에 yml파일을 생성한다(파일이름은 아무거나 해도 괜찮다).

직접 폴더에서 생성해도 되고, 깃헙 리파지토리의 Actions에서 생성해도 된다(본인은 이 방법을 선택했다).

  • Actions 상단의 ‘Workflows made for your JavaScript repository’를 선택
  • 파일이름 지정 후(이름은 아무거나 해도 괜찮습니다) 내용 작성, 그리고 Start commit버튼을 누른다.

!!!들어가는 내용!!!

내용이 달라지거나 오탈자가 있으면 안 된다.

  • 만든 zip파일과 s3에 업로드하는 zip파일이름이 동일해야 하고,
  • s3 버킷이름
  • s3에 올리고자하는 폴더 경로 등을 잘 확인해야한다!
  • **여기 이 내용을 잘 봐주세요**(별표 두 개 안에 감싸져있는 내용, 코드를 작성하실 때 별표는 제외하고 작성해주세요.)
name: Deploy # Workflow 이름
on: # Event 감지
push:
branches:
- master # 마스터 브랜치의 푸쉬가 일어날 때 CI/CD를 진행하겠다는 뜻
jobs: # Job 설정
build:
# 내 EC2는 CentOS라서 바꿔야 할 것 같지만, 여기는 아래 상태로 둔다.
runs-on: ubuntu-latest
steps:
- name: Checkout source code. # Repo checkout
uses: actions/checkout@v2
- name: Check Node v # Node v 확인
run: node -v
- name: Install Dependencies # 의존 파일 설치
run: yarn install --frozen-lockfile
- name: Build # React Build
run: yarn build
- name: zip create
# zip 파일을 만듭니다(파일명은 자유, 대신 아래 workflow에 적을 파일명과 동일하게 맞춰주세요).
run: zip -qq -r ./**build-fe.zip .**
shell: bash
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
**# 아래 볼드 표시한 부분을 깃헙 리파지토리에서 지정한 이름으로 작성해주세요!**
aws-access-key-id: ${{ secrets.SECRET_KEY }}
aws-secret-access-key: ${{ secrets.SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Upload to S3 # Upload build file to S3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.SECRET_KEY }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.SECRET_ACCESS_KEY }}
**# 여기에서 S3버킷이름, 폴더이름을 바꿔주세요! 혹시 aws리전이 다르면 리전도 바꿔주세요.**
run: |
aws s3 cp --region ap-northeast-2 **./build-fe.zip** s3://**S3버킷이름/S3에서-업로드하고자-하는-폴더**/**build-fe.zip**
- name: Deploy # Deploy to EC2
run: aws deploy create-deployment
--application-name **여기에 생성한-코드디플로이-애플리케이션-이름을 써주세요**
--deployment-config-name CodeDeployDefault.AllAtOnce
--deployment-group-name **여기에 코드디플로이에서-생성한-그룹명을-써주세요**
--s3-location bucket=**S3버킷이름**,key=**S3에서-업로드하고자-하는-폴더**/**build-fe.zip**,bundleType=zip
노션에서의 빨간표시가 미디엄에서는 별표 두 개로 나온다.

위의 작업까지 문제 없이 했다면

Actions → Workflows에서 성공했음을 확인 할 수 있다.

appspec.yml 파일 만들기

위의 작업까지가 S3에 파일을 업로드하는 것이다.

이제 EC2에 파일을 배포해야 한다.

배포하는 파일은 프로젝트 루트경로에 appspec.yml 이라는 파일을 생성하여 작업을 진행한다.

!!주의!! 이 파일의 경우 이름이 반드시 appspec.yml이어야 한다!

!!!들어가는 내용!!!

  • **여기 이 내용을 잘 봐주세요**(별표 두 개 안에 감싸져있는 내용, 코드를 작성하실 때 별표는 제외하고 작성해주세요.)
version: 0.0
os: linux
# 폴더경로는 원하는 곳에 하시면 됩니다. 꼭 /usr/share/nginx/html/안에 들어가지 않아도 됩니다.
files:
- source: /
destination: /usr/share/nginx/html/**원하는-폴더경로**
overwrite: yes
permissions:
- object: /usr/share/nginx/html/**원하는-폴더경로**
owner: root
group: root
mode: 755
hooks:
AfterInstall:
# location은 프로젝트의 root경로를 기준
# 파일을 올린 후 진행해야하는 작업을 적은 deploy.sh 파일 경로를 적어줍니다.
# 필요 없을 경우 안 적어도 되는 것 같습니다(테스트 필요).
- location: deploy.sh
timeout: 60
runas: root

deploy.sh

#!/usr/bin/env bash
echo "> FE 배포"
# 제가 본 예제에서는 S3에서 EC2로 파일을 받는 폴더를 별도로 지정한 후에 복사하여 원하는 경로에 파일을 이동하는 작업을 진행한 것 같습니다.
# 해당 코드 출처: # <https://www.sunny-son.space/AWS/Github%20Action%20CICD/>
# 어떤 작업을 진행하는 지는 본인이 지정하면 될 것 같습니다.
# 저는 별도의 작업을 진행하지 않았습니다.
sudo cp -rf /home/ubuntu/deploy-fe/dist/* /var/www/html
주석의 줄바꿈이 신경쓰여서 원본 사진 첨부합니다. ㅎㅎ

마무리

여기까지 작업을 하고 위에서 지정한대로 마스터브랜치에 푸쉬를 하면 끝!

CodeDeploy → 배포 에서 배포 성공여부를 확인할 수 있다.

혹시 배포가 잘 안 된다면 꼭꼭 로그를 확인해보세요!

로그는 아래 경로에서 확인이 가능하다.

/var/log/aws/codedeploy-agent/

클릭 표시된 파일을 열어보시면 됩니다(codedeploy-agent.log).

참고 링크

https://www.sunny-son.space/AWS/Github Action CICD/

https://isntyet.github.io/deploy/github-action과-aws-code-deploy를-이용하여-spring-boot-배포하기(4)/

--

--