Post

AWS, Nginx, Github Action을 활용한 React CI/CD 구축

Desktop View

이번에 서울특별시에서 주최하는 2024 서울 열린데이터광장 공공데이터 활용 창업 경진대회에 4명의 팀원과 함께 출전하기로 했습니다.

한국노인인력개발원 노인 구인정보를 활용하여, 사람인, 알바몬과 같은 구인구직 사이트를 만들기로 했습니다.

React를 이용한 프론트엔드 개발을 맡게 되어서, AWS, Nginx, Github Action을 사용하여 CI/CD를 우선 구축하였습니다.

React 레퍼지토리를 생성했다는 가정하에 포스팅을 진행하겠습니다.

AWS

인스턴스 생성

우선 AWS에 접속하여 EC2 -> 인스턴스(좌측 메뉴바) -> 인스턴스 시작(우측 상단) 순으로 접속하여 인스턴스를 생성창으로 접속합니다.

Desktop View

인스턴스의 이름을 설정하고 AMI를 Ubuntu Server 22.04로 지정합니다.

Desktop View

AMI를 설정하였다면 인스턴스 유형과 키페어를 설정합니다. 인스턴스 유형을 t2.small를 설정하였지만 t2.micro로 설정하여도 무방합니다.

Desktop View

마지막으로 보안 그룹을 설정합니다. 저희는 nginx를 사용하여 배포를 하기 때문에 HTTP,HTTPS 트래픽을 허용합니다. 우측 하단의 인스턴스 시작 버튼을 클릭하여 인스턴스를 생성합니다.

node js 설치

생성된 인스턴스에서 react를 실행하기 위해 node js를 설치합니다. 저는 아래 사이트를 참고하여 VSCode에서 Remote Development를 사용하여 인스턴스에 접근하였습니다.

VSCode에서 AWS EC2 instance원격 접속하기

위 방법을 사용하시는 분들은 다운로드한 키페어에 읽기 권한을 반드시 부여하셔야 합니다.

Desktop View

접속을 하셨다면 터미널 창을 열고 node js 설치를 진행합니다.

로컬 환경과 같은 버전을 다운 받는 것을 권장합니다.

아래 명령을 입력해 현재 계정에 nvm 스크립트를 설치합니다.

1
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash 

설치한 nvm 스크립트를 사용하기 위해 아래 source 명령어를 입력해 .bashrc 파일에 수정된 값을 적용시킵니다.

1
$ source ~/.bashrc

아래 명령어를 입력해 설치 가능한 버전을 볼 수 있습니다.

1
$ nvm list-remote

저는 로컬 환경과 같은 v20.12.2를 설치하겠습니다.

1
$ nvm install 20.12.2

Desktop View node -v 명령어를 통해 설치 확인

GitHub Action

self-hosted runner

Desktop View

GitHub의 React 레퍼지토리로 들어가 setting -> runner -> New self-hosted runner를 클릭합니다.

self-hosted runner 설치하면 연결된 GitHub의 내용이 업데이트 될 때마다 그 내용을 다운로드합니다.

Desktop View

Runner image는 Linx를 클릭하고 위의 박스 친 부분의 명령어들을 aws 인스턴스 터미널에 입력하여 설치를 진행합니다.

Desktop View

actions-runner 디렉토리로 들어가면 svc.sh 파일이 생성된 것을 확인할 수 있습니다. 아래의 명령어로 설치를 진행합니다

1
$ sudo ./svc.sh start

workflows

이제 workflow를 지정하여 저장소에 이벤트가 발생할 경우 실행할 작업들을 설정합니다.

Desktop View

GitHub 레퍼지토리의 Action에 들어가 node를 검색하여 Node.js를 클릭합니다.

Desktop View

이제 위 창에서 아래 코드를 붙여넣기 하고 commit-changes를 클릭합니다. node-version의 경우 이용하는 Node.js 버전에 맞게 수정해야 합니다!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs

name: Node.js CI

on:
  push:
    branches: [ "main" ]

jobs:
  build:

    runs-on : self-hosted

    strategy :
      matrix:
        node-version: [20.x]
        # See supported Node.js release schedule at https://nodejs.org/en/about/releases/

    steps :
      - uses: actions/checkout@v3
      - name: Use Node.js $
        uses: actions/setup-node@v3
        with:
          node-version: $
          cache: 'npm'
      - run: npm ci
      - run: npm run build --if-present

참고로 저의 경우에는 run: npm ci에서 계속 에러가 발생하였습니다. 로컬의 package-lock.json과 GitHub에 package-lock.json의 충돌이 원인이었고 새로운 레퍼지토리를 생성하여 .gitignorepackage-lock.json을 추가하였습니다. 이후 워크플로우의 - run : npm ci 상단에 - run: npm install을 추가하여 이벤트 발생시 AWS 인스턴스 내에서 package-lock.json 파일이 생성되게 하여 문제를 해결했습니다.

1
2
3
4
 # ...
  - run: npm install
  - run: npm ci
 # ...

Desktop View

위 작업을 모두 마치면 Github 레포지토리의 Action에서 CI/CD 워크플로우가 실행됩니다.

Desktop View

잘 실행이 되었다면 Aws 인스턴스의 /actions-runner/_work에 Github 파일이 로드됩니다.

Nginx

Nginx 설치

이제 Github 레퍼지토리에 commit을 하면 자동으로 Aws 인스턴스에 내용이 적용되고 빌드됩니다. 빌드 된 내용을 Nginx를 사용하여 배포하면 됩니다.

Aws 인스턴스 터미널에 아래 명령어를 사용하여 Nginx 설치를 진행합니다.

1
$ sudo apt install nginx

설치를 완료했다면 우리가 만드는 설정과 겹칠 수 있기 때문에 기본 설정을 삭제합니다.

1
2
$ sudo rm /etc/nginx/sites-available/default
$ sudo rm /etc/nginx/sites-enabled/default

이제 Nginx 설정파일을 생성합니다.

1
2
$ cd /etc/nginx/sites-available/
$ sudo touch myapp.conf

myapp.conf의 내용은 다음과 같습니다.

1
2
3
4
5
6
7
8
server {
  listen 80;
  location / {
    root   /home/user/myapp/build;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }
}

listen 80의 의미는 포트 80번을 통해 접근을 허용한다는 뜻입니다. 저희는 Aws 인스턴스를 생성하면서 방화벽이 http에 대한 접근을 허용했습니다만 혹시 하시지 않은 분들은 Aws 인스턴스의 인바운드 규칙에 http 통신을 추가해 주시기 바랍니다.

저의 경우에는 root/home/ubuntu/actions-runner/_work/the-nuri-front/the-nuri-front/build;를 입력하였습니다.

root에 들어가는 경로 모두 읽기 권한이 부여되어야 합니다. 그렇지 않으면 Nginx에서 403 에러를 발생시킵니다.

1
sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/myapp.conf

위 명령어를 입력하여 /etc/nginx/sites-available/에 설정 파일의 심볼릭 링크를 /etc/nginx/sites-enabled/ 에 만듭니다.

워크플로우 추가

아쉽게 Aws 인스턴스에 이벤트 내용을 적용시켰다고 하더라도 Nginx가 서비스하는 웹 페이지에는 적용되지 않습니다.
무중단 배포를 하는 법이 있지만 내용이 너무 복잡하여 그냥 Nginx를 껐다가 다시 실행하는 방식을 선택하였습니다.

1
2
3
4
5
6
7
8
9
10
11
...
 - run : npm install
  - run: npm ci
  - run: npm run build --if-present
  
  # 아래 내용 추가
  - name: Stop Nginx
    run: sudo service nginx stop

  - name: Start Nginx
    run: sudo service nginx start

이 방법은 실제 서비스에 적용되기에는 많은 무리가 있다고 생각되니 참고해 주시기 바랍니다.

Desktop View

이제 커밋한 내용이 퍼블릭 주소의 웹사이트에도 잘 적용된 것을 확인할 수 있습니다.

참고 자료

This post is licensed under CC BY 4.0 by the author.