React 프로젝트 Github Actions로 AWS EC2 배포하기 (2)

2025. 3. 22. 19:03·개발

 

2025.03.21 - [웹] - React 프로젝트 Github Actions로 AWS EC2 배포하기 (1)

위 글과 이어지는 글입니다

 

AWS EC2, S3, CodeDeploy를 다 준비했으니, 이제 React 프로젝트와 연결할 준비를 해보자.

 

1. 프로젝트 준비

액세스 키, 비밀 액세스키 등록

이전 글의 AWS IAM 설정 - 액세스 키 발급 부분에서 보관해둔 액세스키, 비밀 액세스키를 사용할 차례이다.

프로젝트가 해당 키 값을 이용해 AWS에 접근할 수 있도록 저장해야 한다. 

 

Github 레포지토리의 Settings - Security - Secrets and variables - Actions에 들어간다.

 

Repository secrets - New repository secret 버튼을 눌러 액세스키, 비밀 액세스키, 지역을 저장한다.

지역은 아시아 태평양(서울)은 ap-northeast-2이다.

 

EC2 인스턴스 키페어 추가

그리고 인스턴스의 키 페어(.pem 파일)를 React 프로젝트 루트 경로에 추가한다.

절대 노출되면 안되므로, 꼭 .gitignore에 파일 이름을 추가한다!

 

2. EC2 인스턴스 연결

EC2 인스턴스에 보면 연결 버튼이 있다.

누른 후 SSH 클라이언트 탭에 보면, 제일 밑에 명령어가 있다. 

 

터미널을 켜고, 키페어 .pem 파일을 저장한 경로로 이동한다. 그리고 위 명령어를 입력하면 된다.

성공적으로 접속되었으면, 터미널 경로가 ubuntu@ip- 로 바뀐다.

 

참고한 글(https://velog.io/@zinukk/AWS-EC2와-Github-Actions로-프론트엔드-CICD-구축하기-3)에서는 AWS-cli를 설치하라고 하는데, 설치하니 에러가 발생했다.

Package awscli is not available, but is referred to by another package. This may mean that the package is missing, has been obsoleted, or is only available from another source E: Package 'awscli' has no installation candidate

 

구글링 해본 결과, Github action을 사용할 땐 configure-aws-credentials를 사용하면 된다고 한다.

 

3. EC2 인스턴스 프로젝트 환경 설정

Code Deploy Agent 설치

AWS 사용자 가이드에 잘 설명되어 있다. ubuntu 버전에 따라 설치를 진행하면 된다.

 

설치 후, sudo service codedeploy-agent status를 입력해서 Active: active (running)으로 표시되어있으면 성공적으로 설치된 것이다. 

그렇지 않다면 sudo service codedeploy-agent start를 입력해 임의로 실행한 후 다시 확인해보자.

 

라이브러리 필요한 라이브러리 설치

Node.js 설치

setup_ 뒤엔 설치할 버전을 적어주면 된다.

sudo apt update
curl -sL https://deb.nodesource.com/setup_20.x | sudo bash -E -
sudo apt-get install -y nodejs

 

pm2 설치

pm2를 사용하여 애플리케이션을 실행시키면, 터미널을 종료해도 중단되지 않도록 할 수 있다. 

sudo npm install pm2 -g

 

4. 프로젝트 Github Actions 세팅

깃 레포지토리에 푸시하면, 변경사항을 포함시켜 자동적으로 재배포하기 위한 코드를 Github Actions가 실행시키기 위해서는 다음과 같은 파일을 React 프로젝트에 작성해주어야 한다.

deploy.yml 파일 생성

Github Actions가 실행할 코드를 작성한다.

프로젝트 루트 경로에 다음과 같이 deploy.yml 파일을 생성해주자.

 

그리고 다음과 같이 작성해준다. 

name: Deploy
on:
  push:
    branches:
      - master
jobs:
  build:
    runs-on: ubuntu-24.04 # ec2 인스턴스 우분투 버전으로 변경
    steps:
      - name: Checkout source code.
        uses: actions/checkout@v2
      - name: Check Node v
        run: node -v
      - name: Install Dependencies
        run: npm install --frozen-lockfile
      - name: Build
        run: npm run build
      - name: zip create
        run: zip -qq -r ./build.zip .
        shell: bash
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}
      - name: Upload to S3
        run: |
          aws s3 cp --region ap-northeast-2 ./build.zip s3://버킷이름/build.zip
      - name: Deploy
        run: aws deploy create-deployment
          --application-name 코드디플로이이름
          --deployment-config-name CodeDeployDefault.AllAtOnce
          --deployment-group-name 코드디플로이배포그룹이름
          --s3-location bucket=버킷이름,bundleType=zip,key=build.zip

 

 

위 코드는 master 브랜치에 푸시가 발생하면 다음 작업을 하도록 한다.

  • 패키지를 설치하고, 빌드한 후 build.zip로 압축한다.
  • AWS 액세스키, 비밀 액세스키를 가지고 인증한다.
  • build.zip 파일을 S3에 업로드한다.
  • CodeDeploy가 S3에서 build.zip 파일을 가져온다.

 

appspec.yml 생성

CodeDeploy가 S3에서 build.zip 파일을 가지고 할 작업을 작성해주어야 한다.

 

프로젝트 루트 경로에 appspec.yml 파일을 생성하고, 다음과 같이 작성한다.

version: 0.0
os: linux
files:
  - source: /
    destination: /home/ubuntu/deploy
    overwrite: yes
permissions:
  - object: /home/ubuntu/deploy
    owner: root
    group: root
    mode: 755
hooks:
  AfterInstall:
    - location: deploy.sh
      timeout: 1000
      runas: root

 

위 코드는

  • build.zip 파일을 가져와 EC2 인스턴스의 /home/ubuntu/deploy 경로에 저장한다
  • deploy.sh 파일을 실행한다

 

deploy.sh 파일 생성

루트 경로에 deploy.sh 파일을 생성한다.

REPOSITORY=/home/ubuntu/deploy

cd $REPOSITORY

sudo npm install

sudo pm2 reload all

 

위 코드는

  • EC2 인스턴스에 저장된 프로젝트의 패키지를 설치하고
  • 실행 중이던 애플리케이션(프로세스)을 reload한다

참고로 프로세스를 restart가 아닌 reload를 하면, 프로세스를 중단하지 않고 재시작할 수 있다.

 

 

5. 서버 실행

서버 프로젝트 생성

간단하게 Express 서버를 코드를 작성해보자. 다음 글을 참고했다. 

https://velog.io/@kcj_dev96/프론트-배포-방법-1편AWS-EC2-with-React-Express-환경

 

프론트 배포 방법 1편[AWS EC2를 활용한 배포] with React ,Express 환경

기존에 프로젝트를 간단하게 배포하기 위해 netlify나 heroku와 같은 서비스를 이용하였다. 나의 블로그 프로젝트 또한 heroku를 통해 배포를 했다만 heroku 서비스가 유로화되면서 새로운 배포 방법을

velog.io

 

서버 프로젝트를 만들어 git clone해도 되지만, 코드가 몇 줄 없으니 터미널에서 직접 작성해주었다. 

 

클라이언트 프로젝트가 현재 /home/ubuntu/deploy 안에 있으니, /home/ubuntu 경로로 이동해 폴더를 생성하고 해당 폴더로 이동한다. 그리고 npm 패키지 초기화, 라이브러리(express, nodemon)을 설치한다.

mkdir server
cd server
npm init -y
npm i express nodemon

 

설치가 끝나고, package.json 파일을 확인해본다.

{
  "name": "server",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {
    "start": "nodemon app",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.21.2",
    "nodemon": "^3.1.9"
  },
}

 

scripts에 "start": "nodemon app"이 없다면 추가해주자.

 

그리고 app.js 파일을 생성하고, 다음을 작성해준다.

const express = require("express");
const path = require("path");

const app = express();

app.set("port", process.env.PORT || 5000);

app.use(express.static(path.join(__dirname, "../deploy/dist")));

app.get("/", (req, res) => {
  res.sendFile(path.join(__dirname, "../deploy/dist/index.html"));
});

app.listen(app.get("port"), () => {
  console.log(app.get("port"), "번 포트에서 대기중..");
});

 

빌드된 결과물의 경로에 맞게 작성해주면 된다. 

 

EC2 인바운드 규칙 추가

EC2 - 보안 그룹 - 보안 그룹 ID 클릭 - 인바운드 규칙 편집 버튼 클릭

5000번 포트에 대한 인바운드 규칙을 추가한다.

 

서버 실행

이제 서버를 실행해준다.

sudo pm2 start app.js --name "server"

 

실행 상태를 확인해보자 (LISTEN, online 상태)

netstat -tnlp | grep 5000

 

sudo pm2 list

 

 

이제 도메인:5000(예: example.com:5000)로 접속이 가능하다.

이제 http://example.com 또는 https://example.com으로 접속하더라도 위 페이지로 리다이렉트 되도록 해보자 

 

리다이렉션 설정

뒤에 나올 로드밸런서를 사용하면, 불필요한 부분이니 넘어가도 됩니다.

 

http의 기본포트는 80, https는 443이다.

즉, 80 또는 443 포트로 접속했을 때 5000 포트로 리다이렉트되도록 설정을 해주어야 한다.

 

우선 네트워크 인터페이스 이름을 알아야 한다. 

ifconfig를 입력하면 목록이 나타나는데, 여기에 inet에 적힌 값이 프라이빗 IPv4 주소와 일치하는 것이 있을 것이다. 나의 경우 enX0이었다. (참고한 글에는 eth0으로 되어있었는데 그대로 사용했다가 안되서 한참 헤맸다..)

 

그럼 이제 다음 명령어를 차례로 입력해서 리다이렉션을 설정한다.

# http
sudo iptables -A PREROUTING -t nat -i enX0 -p tcp --dport 80 -j REDIRECT --to-port 5000 

# https
sudo iptables -A PREROUTING -t nat -i enX0 -p tcp --dport 443 -j REDIRECT --to-port 5000

 

확인해보려면 다음 명령어를 입력하면 된다.

sudo iptables -t nat -L --line-numbers

 

 

참고로 삭제 명령어는 다음과 같다.

# sudo iptables -t nat -D PREROUTING [number]
sudo iptables -t nat -D PREROUTING 1

 

 

그럼 이제 http, https를 붙여 접속해보면? https 접속은 안된다...

 

찾아보니 https를 적용하기 위해서는 SSL/TLS 인증서를 발급받고, Elastic Load Balancer 또는 Amazon CloudFront를 통해 EC2 인스턴스와 인증서를 연결해야 한다고 한다. 

 

6. HTTPS 적용

다음 글을 참고했다. 

https://tioon.tistory.com/184

 

EC2 도메인 연결 및 HTTPS 적용하기

이번엔 AWS에서 서버 배포를 할때, 도메인을 적용시키고, 추가적으로 HTTP가 아닌 HTTPS로 적용시켜 배포하는것을 알아보도록 하겠습니다. 우선, 이 과정을 진행하기 위해선 필요한것들은 다음과

tioon.tistory.com

 

AWS Certificate Manager(ACM) 인증서 발급

AWS Certificate Manager(ACM) 서비스로 들어가 인증서 요청 버튼을 누른다.

인증서 유형은 퍼블릭 인증서 요청을 선택하고, 도메인 이름에 구매한 도메인을 입력한 후 나머지는 기본값 그대로 요청한다.

 

생성된 인증서 ID를 클릭해서 들어가서, 도메인 - Route 53에서 레코드 생성 버튼을 누른다.

 

Route 53 - 호스팅 영역에서 해당 도메인 이름을 눌러 들어가보면, CNAME 유형의 레코드가 생긴 것을 볼 수 있다. 곧 인증서의 상태가 "발급됨"으로 바뀐다.

 

로드 밸런싱 대상 그룹 생성

로드 밸런스는 외부로부터 받은 요청을 여러 서버에 작업을 고르게 분산하는 기술이다. 

AWS Elastic Load Balancing(ELB)는 외부로부터 받은 80, 443 포트 요청에 대해 전달될 포트를 지정함으로써 다른 포트 번호로 매핑하여 처리하는 것을 가능하게 한다. 

 

현재 EC2의 보안 인바운드 규칙에는 http, https와 5000번 포트에 대한 규칙을 추가해둔 상태이다. 

 

EC2 - 로드 밸런싱 - 대상 그룹을 이동해, 대상 그룹 생성 버튼을 누른다.

임의로 대상 그룹 이름을 입력하고, 나머지는 기본값을 유지하고 다음으로 넘어간다.

그럼 대상 등록 - 사용 가능한 인스턴스 목록이 나오는데, 인스턴스를 선택하고 서버 실행 포트 번호를 입력하면 된다. 

 

로드 밸런서 생성

EC2 - 로드 밸런싱 - 로드밸런서로 들어가, 로드 밸런서 생성 버튼을 누른다.

 

로드 밸런서 유형은 Application Load Balancer를 선택한다.

이름은 임의로 입력하고, 가용 영역 및 서브넷은 2개 이상 선택하면 된다.

특정 가용 영역에 문제가 생겼을 때 다른 영역으로 트래픽을 분산시키기 위해, 최소 2개 이상의 서브넷이 필요하다.

 

EC2 인스턴스에서 사용하는 보안 그룹을 선택한다.

 

http(80), https(443) 포트에 대한 리스너를 추가한다. 로드밸런서로 들어온 80, 443 요청을 대상 그룹에 전달할 수 있다.

 

생성한 Certificate Manger 인증서를 선택한다.

 

로드 밸런서와 도메인 연결

Route 53 - 호스팅 영역으로 가서,  레코드 목록 중 유형이 A인 레코드의 값을 수정한다.

별칭을 선택하고, 트래픽 라우팅 대상을 생성해둔 로드 밸런서로 선택한다.

이제 조금 기다리면 https 접속이 가능하다!

 

반응형
'개발' 카테고리의 다른 글
  • Hot Module Replacement (Hot-Reloading)
  • 윈도우에서 iOS safari 디버깅하는 법
  • React 프로젝트 Github Actions로 AWS EC2 배포하기 (1)
  • 크로스 브라우징(Cross Browsing)
xosoy
xosoy
겅부하자!
  • xosoy
    gungboohaza
    xosoy
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 개발
      • CS
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    react19
    initialdata
    feature-sliced design
    mobx
    hot-reloading
    시간 포맷팅
    liveblocks
    event bubbling
    Font Optimiation
    useEffectEvent
    이벤트 버블링
    서버 컴포넌트
    배포
    Pointer Event
    React Server Component
    TanStack Query
    핫 리로딩
    가상리스트
    이벤트 루프
    event capturing
    Github Actions
    matter.js
    HydrationBoundary
    react
    리스트가상화
    Next.js
    oEmbed
    이벤트 캡처링
    prefetchInfiniteQuery
    E2E
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
xosoy
React 프로젝트 Github Actions로 AWS EC2 배포하기 (2)
상단으로

티스토리툴바