본문 바로가기

Programming/AWS

[AWS/Actions] 웹 프로젝트 배포하기 (4) - 프론트(React) Nginx 배포 및 CI/CD 구축

 

 

 


웹 프로젝트 배포하기 (4) - 프론트(React) Nginx 배포 및 CI/CD 구축


 

 

 

[AWS/Actions] 웹 프로젝트 배포하기 (3) - 서버(SpringBoot) 배포 및 CI/CD 구축

웹 프로젝트 배포하기 (3) - 서버(SpringBoot) 배포 및 CI/CD 구축   [AWS] 웹 프로젝트 배포하기 (2) - 메모리 증설 및 자바 설치웹 프로젝트 배포하기 (2) - 메모리 증설 및 자바 설치    [AWS] 웹 프

hanadoescoding.tistory.com

이전 글에서 이어집니다.

 

 

 

1. React 프로젝트 클론


server 레포지토리와 client 레포지토리를 분리해서

각각 actions 를 적용하는 방법도 있으나..

 

 

이미 한 레포지토리 안에 다 넣어버린 관계로

한번에 진행하는 방식으로 가겠다.

 

각각 하는 방식과 크게 차이 없을 것이다.

workflows 디렉토리 안에 yml 속 scripts 만 잘 작성하면 되니까.

 

프로젝트 클론은 인스턴스를 새 창에 열어서,

서버에서 했던 것과 동일하게 진행하면 된다.

 

 

 

우선 클론이 되어있다는 가정하에 시작하겠다.

 

 

 

2. npm 설치


배포하고자 하는 사이트는 React(vite)로 제작되었다.

 

React 개발을 하면서 npm 을 통해

① node.js 에서 사용하는 모듈을 저장하고

② 설치 및 관리를 위한 CLI(Command Line Interface)를 제공 받아 사용했기에

node.js 와 npm 부터 설치해줄 것이다.

 

 

2.1 Node.js 설치를 위한 도구 curl

Node.js 의 공식 설치 스크립트를 다운로드 하기위한 사전 준비 작업이다.

sudo apt-get install -y curl

 

 

 

2.2 node.js 설치

sudo apt-get install -y nodejs

 

node.js 를 설치한다.

 

node -v

 

설치된 node.js 의 버전은 위 명령을 통해 알 수 있다.

 

 

 

2.3 npm 설치

npm은 node.js 설치 시 자동으로 설치되는 항목인데..

어째서인지 설치가 되지 않아 따로 설치해주었다.

sudo apt-get install npm

 

 

 

2.4 node_modules 설치

cd <클라이언트 프로젝트 폴더>
npm i

 

 

 

2.5 실행

npm run dev

 

 

 

3. 빌드 및 Nginx 설정


Nginx는 웹 애플리케이션의 HTTP 요청을 처리하는데 사용되는 고성능 웹 서버다.

프론트엔드 애플리케이션을 빌드해 정적 파일로 만들고, 이 정적 파일들을 nginx 서버를 통해 서빙한다.

 

aws 에 배포를 할 때 매번 사용하던 포스 번호를 붙여줘야 했다. (ex http://54.180.101.9:8070/ )

그러나 nginx 를 사용하면 포트 번호를 붙이지 않고, IP 주소(도메인) 만으로도 웹 페이지를 띄울 수 있게 된다.

nginx 는 기본적으로 HTTP 요청을 처리하는 포트인 80번 포트를 사용하기 때문이다.

 

 

3.1 빌드

npm run build

 

 

 

Killed 어쩌구하는 오류가 뜬다면 이는 메모리 부족이 원인일 가능성이 크다.

 

NODE_OPTIONS="--max-old-space-size=4096" npm run build

 

그럴 때는 사용하는 메모리 용량을 늘려주는 명령을 사용해 빌드해보자.

 

 

Vite 프로젝트는 dist , CRA 프로젝트는 build 디렉토리가 생긴다.

 

 

3.2 Nginx 설치

sudo apt install nginx

 

npm run dev 은 로컬 환경에서 실행하기 위한 명령이다.

배포를 위해서는 nginx 같은 웹 서버를 활용해야 한다.

 

기존에는 IP:5173 과 같이 포트를 붙여야 실행이 됐지만,

nginx 를 사용하게 되면 IP 만으로 웹 서버를 실행할 수 있게 된다.

 

sudo systemctl start nginx

 

이제 nginx 에 프로젝트가 뜨도록 설정해주자.

 

 

 

3.3 Nginx 설정

기존 nginx 파일을 바꿔치기(!) 할 것이다.

 

 

3.3.1 nginx 기본 설정 삭제

먼저, 커스텀 설정과의 출동 방지를 위해 nginx 기본 설정에 대한 파일을 삭제해준다.

sudo rm /etc/nginx/sites-available/default
sudo rm /etc/nginx/sites-enabled/default

 

 

3.3.2 커스텀 설정

cd /
cd etc/nginx/sites-available

 

/ (root / 루트) 위치로 이동한 뒤

etc/nginx/sites-availanble 폴더로 이동한다.

 

cd /etc/nginx/sites-available

 

최상위 폴더가 아닌 다른 위치에서 이동한다면 앞에 / 절대 경로를 붙이면 된다.

 

 

sudo vim myapp.conf

 

 

커스텀 설정을 위한 myapp.conf 파일을 생성하고, 작성한다.

 

 

 

server {
        listen 80;
        location / {
                root   <빌드 파일이 있는 경로>;
                index  index.html index.htm;
                try_files $uri $uri/ /index.html;
        }
        location /api {
                proxy_pass <api 요청을 전달하는 주소>;
                proxy_http_version 1.1;
        }
}

 

root 빌드 파일이 있는 절대 경로
index 디렉토리 접근을 위한 기본 문서를 나타냄. index.html 을 기본으로, 없다면 index.htm 을 기본으로 설정
try_files 사용자가 요청한 파일이 존재하지 않는 경우 index.html 을 대체 파일로 반환
proxy_pass 백엔드 서버와 통신 시 api 요청을 전달하는 주소

 

proxy_pass  에는 vite.config.js(http-proxy-middleware) 파일에 작성해둔 API 서버 주소를 작성해주면 된다.

 

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vite.dev/config/
export default defineConfig({
  plugins: [react()],
  server: {
    port: 5173,
    proxy: {
      '/api': {
        target: 'http://localhost:8070', // API 서버 주소
        changeOrigin: true,
        secure: false,
        rewrite: (path) => path.replace(/^\/api/, ''),
      }
    }
  },
})

 

이렇게 설정해놨다면..

proxy_pass 는 http://localhost:8070 이다.

 

 

3.3.3 작성 파일 활성화를 위한 링크 걸기

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

 

작성 파일 활성화를 위하여 sites-enabled 에 링크를 걸어준다.

 

 

sites-enabled 로 가니 myapp.conf 가 똑같은 파일로 링크가 걸린 것을 볼 수 있다.

 

 

3.4 실행

sudo vi /etc/nginx/nginx.conf

 

권한 부여를 위해 nginx.conf 파일을 수정한다.

 

 

파일 최상단에 user www-data; 로 되어 있는 부분을 사용자 이름으로 바꾼다.

기본 설정인 ubuntu 로 바꿔주면 된다.

 

sudo systemctl restart nginx

 

이후 서버를 재실행 시켜주면....

 

 

내가 정한 닉네임이 아니다

 

서버와 클라이언트 모두 잘 실행되는 모습이다 ^^b

 

 

 

4. 액션 (Actions)


4.1 deploy.yml 수정

만약 client 레포지토리를 따로 만들었다면 actions 설정을 다시 해야하지만 (방법은 서버 때랑 똑같음)

이미 한 레포지토리 안에 넣어둔 상태라 같이 진행되도록 기존 설정에 script 만 추가해주었다.

 

name: GitHub Actions 실행 # workflow 의 이름

on:
  push:
    branches:
      - main # main 브랜치에 push 될 때 아래의 workflow 를 실행

jobs:
  My-Deploy-job: # GitHub Actions 에서 실행될 Job 이름
    runs-on: ubuntu-latest # Actions 실행 환경
    steps: # Job 이 실행될 단계 정의
      - name: Dive 프로젝트 서버 배포
        uses: appleboy/ssh-action@master # Actions 의 appleboy/ssh-action 을 사용하여 SSH 접속 수행
        env: # 환경변수 설정
          APPLICATION_PROPERTIES: ${{ secrets.APPLICATION_YML }} # secret 에 작성한 yml 가져오기
        with:
          host: ${{ secrets.EC2_HOST }} # EC2 인스턴스의 공인 IP 주소 또는 도메인
          username: ${{ secrets.EC2_USERNAME }} # EC2에 접속할 사용자 이름
          key: ${{ secrets.EC2_PRIVATE_KEY }} # SSH 접속을 위한 비밀키
          envs: APPLICATION_PROPERTIES # 환경변수를 EC2 서버에 전달
          script_stop: true # 스크립트 실행 중 오류가 발생하면 즉시 종료
          script: |
            cd /home/ubuntu/project-dive-musicstreaming
            rm -rf src/main/resources/application.yml
            git pull origin main
            echo "$APPLICATION_PROPERTIES" > src/main/resources/application.yml
            sudo ./gradlew clean build
            sudo fuser -k -n tcp 8070 || true
            nohup java -jar build/libs/*SNAPSHOT.jar > ./output.log 2>&1 &
            cd TeamDive_Client
            sudo npm run build
            sudo systemctl restart nginx

 

cd TeamDive_Client
sudo npm run build
sudo systemctl restart nginx

 

클라이언트 폴더로 들어가서

빌드 다시 하고

nginx 재시작하는 코드.

 

이제 깃에 커밋푸시 후 테스트를 해보자.

 

 

일단 Actions 에는 어쩌구저쩌고 빌드 어쩌구저쩌구 하더니 초록불이 들어왔다!

 

수정 정보도 push 후 바로 반영이 되는지 테스트를 위해 백엔드와 프론트의 정보를 조금씩 수정했다.

 

 

[프론트] Footer 에 있던 정보

기존

 

수정사항
push 후

 

 

 

[백] api/member/test 요청 텍스트

기존
push 후

 

 

성공 ^^b

 

 

 

* 사진 올리는 bucket 은 배포 담당 팀원분이 담당하셨는데.. DB 이미지 이름에 버킷 주소가 담겨있어서 이를 다루려면 DB 를 갈아 엎어야 했음.. 그래서 다루지 못했지만, 다음 프로젝트에는 해볼 수 있었으면 좋겠다