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

김철준·2023년 2월 12일
36

Devops

목록 보기
1/9

기존에 프로젝트를 간단하게 배포하기 위해 netlify나 heroku와 같은 서비스를 이용하였다.

나의 블로그 프로젝트 또한 heroku를 통해 배포를 했다만 heroku 서비스가 유로화되면서 새로운 배포 방법을 찾아야했다.

netlify나 heroku와 같이 간단히 서비스를 배포하는 법도 있지만 실무에선 aws 서비스를 통한 배포 방법을 선택을 한다.

유저 트래픽이 많은 경우 netlify나 heroku와 같은 서비스는 감당하기 힘들다고 한다. 또한 둘 다 사용해본 결과 서버 리전이 다른 나라에 있어 정적파일을 서버로 요청하여 불러올 때 응답 속도가 느려 페이지나 이미지의 응답 속도가 느려 한국에서는 UX가 좋지 않다.

그래서 프로젝트를 배포하기 위해서 어떠한 방법들이 있는지 로깅해보겠다.

배포하는 방법은 다음과 같은 방법들이 있다.

  • AWS EC2를 활용한 배포
  • AWS S3와 CloudFront를 활용한 배포
  • AWS amplify를 활용한 배포
  • Nginx를 활용한 배포

각 방법에 따라 배포할 수 있는 서버가 다르다.
여기서 배포할 수 있는 서버란 웹서버와 WAS 서버를 말한다.
각 방법에 따라 배포할 수 있는 서버는 다음과 같다.

EC2

웹 서버,WAS 서버 배포 가능

nginx

정적 콘텐츠 배포하게 해줌.

S3 + cloudfront

정적 콘텐츠(프론트 서버)를 배포하게 해줌.

Amplify

정적 콘텐츠(프론트 서버)를 배포하게 해줌.
S3+ cloudfront 방법보다 간편하게 배포가능하며 배포 자동화
그리고 자동으로 s3,cloudfront 구현

각 방법별로 시도해보며 과정을 블로깅해보겠다.

EC2를 활용한 배포

우선 먼저 EC2로 WAS 서버를 배포하는 방법을 살펴보겠다.

REACT와 Express(node.js)환경으로 express 서버를 배포해보겠다.

express 서버는 정적 파일을 제공해줄 수 있는 서버로도 활용할 수 있고 동시애 API 서버로도 활용할 수 있다.
즉, 웹 서버로도 활용할 수 있고 WAS 서버로도 활용할 수 있다.

인프라 구축만을 알아보기 작성된 것이므로 코드적 내용은 CRA로 만들고 express에서 빌드 파일을 보여주는 식으로만 진행해보겠다.

과정은 다음과 같이 진행한다.

1. express 서버 구축

2. 서버 디렉터리내에 CRA로 react 프로젝트 생성 뒤 빌드

3. express 서버에 빌드한 리액트 정적 컨텐츠 제공

4. express 서버 EC2에 배포

1. express 서버 구축

서버를 만들어주기 위해 express 간단히 서버를 만들어보자.
express를 사용하면 몇줄의 코드만으로 간단히 서버를 구성할 수 있다.

조금 후에 React에서 build된 html 파일을 제공할 것이지만 지금은 간단히 html 파일을 제공해보자.

프로젝트 이름을 아무렇게나 설정하고 package.json을 다음 명령어로 패키지를 초기화해준다.

npm init -y

그리고 서버를 구축하기 위해 express를 설치해주고 변경사항이 바로 반영되게 하기 위해 nodemon을 설치해준다.

npm i express nodemon

나는 npm start로 간단히 서버로 실행하기 위해 package.json에서 시작 명령어를 설정해줬다.

package.json 내용은 다음과 같다.

package.json

{
  "name": "be_with_express",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "nodemon app",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.2"
  },
  "devDependencies": {
    "nodemon": "^2.0.20"
  }
}

최상위 디렉터리에서 app.js 파일을 생성해준다.

서버를 만드는 코드는 다음과 같다.

app.js

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

const app = express();

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


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

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

최상위 디렉터리 내부에 서버에 제공할 index.html 파일을 만들어줘야한다.

index.html의 위치

html 내용은 간단히 이렇게 했다.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>Hello EC2!</h1>
  </body>
</html>

npm start로 5000포트로 로컬 서버를 실행해보면 잘 실행되는 것을 확인할 수 있다.

2. 서버 디렉터리내에 CRA로 react 프로젝트 생성 뒤 빌드

이제 리액트 프로젝트를 빌드한 index.html을 제공해보자.

먼저 최상위 디렉터리내에 리액트 프로젝트를 생성해보자.

  1. 우선 최상위 디렉터리 내에서 CRA로 간단히 리액트 프로젝트를 생성하자.
    npx create react-app FE_with_react

  2. 프로젝트가 생성됬다면 바로 build를 해보자.
    npm run build

3. express 서버에 빌드한 리액트 정적 컨텐츠 제공

빌드가 된 파일은 서버에 제공해주기 위하여 express 서버 코드를 다음과 같이 변경해준다.

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, "FE_with_react/build")));

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

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

5000 포트에서 서버를 실행해보면 리액트 프로젝트가 잘 돌아가는 것을 확인할 수 있다.

4. express 서버 AWS EC2에 배포

이제 express 서버를 EC2 서버 컴퓨터에 배포해보자.

우선 AWS에 로그인을 한 뒤 EC2 서비스에 접속하고 region은 서울로 해준다.

ec2대시보드

a. EC2 서버 컴퓨터 인스턴스 생성(운영체제:우분투)

EC2 대시보드 탭으로 이동하여 해당 페이지에서 인스턴스 시작 버튼을 눌러준다.

인스턴스 이름은 아무거나 입력해준다.

OS는 우분투로 선택해준다.

많은 사람들이 인스턴스 OS로 우분투를 선택하는데 왜 우분투를 선택할까?

인스턴스 유형은 프리티어 사용가능이라면 프리티어 사용 가능한 유형을 골라준다.

키페어 생성

키 페어를 생성해준다.

여기서 키페어란 인스턴스에 접속하기 위한 도구이다.
즉, 키 페어가 없으면 인스턴스에 접속할 수 없다.
그러니 키페어를 꼭 생성해주자.

키 페이 이름을 입력해주고 기본으로 선택되어있는 키페어 유형(RSA)을 선택하고 키 파일 형식을 .pem으로 선택해준다.
(putty와 함께 사용한다면 .ppk로 선택해준다.)

키 페어 생성 버튼을 누르면 키 페어 파일이 다운로드된다.
나 같은 경우에는 C드라이브 하위에 파일을 저장해놓았다.

인스턴스 생성

그 다음으로 네트워크 설정이나 스토리지 구성은 기본으로 선택되어있는 상태로 두고 인스턴스를 생성해준다.

모든 인스턴스 보기를 클릭하고 방금 만든 인스턴스 ID를 눌러 해당 인스턴스 탭에서 연결 버튼을 눌러준다.

이제 인스턴스에 접속을 위해 ssh로 접속해줘야하므로 ssh클라이언트 탭을 눌러 접속하는 방법을 살펴보자.

ssh 접속

이제 ssh를 통해 내 컴퓨터에서 ec2 가상 컴퓨터 인스턴스에 접속해보자.

ssh(secure shell) 뜻
시큐어 셀은 네트워크 상의 다른 컴퓨터에 로그인하거나 원격 시스템에서 명령을 실행하고 다른 시스템으로 파일을 복사할 수 있도록 해주는 응용 프로그램 또는 그 프로토콜을 가리킨다.

즉, ssh는 ec2 빌려준 우분투 체제 가상 컴퓨터에 접속하기 위한 도구라고 생각하면 되겠다.

window의 명령 프롬프트 같은 경우 일반적으로 ssh 명령어를 실행할 수 없기 때문에 우분투 프로그램을 설치하거나 putty를 다운로드해야 ssh 명령어를 사용할 수 있다.

하지만 window 10부터는 open ssh라는 것을 설치하여 ssh를 사용할 수 있다.

ssh를 사용하기 위한 방법
a. open ssh 설치(윈도우 10이상 가능)

b. 우분투 설치
우분투를 설치하여 ssh 사용하는 방법

c. putty 사용

위 3가지 방법을 시도해본결과 open ssh를 설치하는 방법이 제일 간단하다.
그러므로 나는 간단히 open ssh 설치하여 접속하는 방법으로 진행하겠다.

open ssh 설치

설치 방법 참조 포스팅

  • 윈도우 설정을 들어간뒤 앱 카테고리를 선택한다.

  • 앱 및 기능에서 선택적 기능을 선택하여 들어간다.

  • open ssh 클라이언트라는 기능을 설치한다.

ssh를 통하여 인스턴스 접속

이제 ssh로 인스턴스에 접속해보자.
위에서 언급했듯이 인스턴스에 접속하기 위해서는 pem 파일(키페어)이 필요하다했다.

그러므로 pem파일이 있는 경로로 이동하여 접속할 수 있기 때문에 아까 pem 파일을 저장해놨던 c 드라이브로 이동한다.

이제 ec2 인스턴스에 접속하기 위해 aws ec2 인스턴스 ssh 클라이언트 접속 안내탭에 나와있는 아래 명령어를 차례로 입력하여 인스턴스에 접속해보자.

chmod 400 pem파일명
ssh -i "pem 파일명" ubuntu@~~~~~~~~.ap-northeast-2.compute.amazonaws.com

명령 프롬프트에 다음과 같은 화면이 나오면 접속이 완료된 것을 확인할 수 있다

ubuntu@ip주소 형식으로 나온다.

우분투 가상 컴퓨터에 node.js,npm,git,프로젝트 가져오기

이제 프로젝트를 인스턴스 서버에 실행하기 위하여 필요한 것들을 설치해보자.

설치할 목록은 다음과 같다.

  • npm
  • node.js
  • git
  • git clone 프로젝트

업데이트
우선 다음 명령어로 update를 진행줘야한다.
sudo apt update

npm 설치를 위한 명령어
다음으로 npm을 설치해준다.
sudo apt install npm

node.js 설치를 위한 명령어
다음으로 node.js을 설치해준다.
sudo apt install nodejs

git 설치를 위한 명령어
프로젝트를 가져오기 위해 git을 설치해준다.
sudo apt install git

github에 등록된 나의 프로젝트 가져오기
git clone https://github.com/BrightJun96/ec2_deploy_test.git

프로젝트에 필요한 패키지 설치

이제 우분투 인스턴스에 프로젝트에 필요한 패키지들을 설치해보자.
프로젝트 경로로 이동한 뒤 패키지를 설치하자.

프로젝트로 이동
cd ec2_deploy_test

서버 패키지 설치
서버에 필요한 패키지(express)를 설치해준다.
npm i

리액트 패키지 설치 및 빌드
서버에 리액트 빌드 파일을 제공하기위해 리액트 프로젝트로 이동하여 패키지를 설치하고 빌드 명령어를 실행하여 빌드파일을 만들어줘야한다.

cd FE_with_react

npm i

npm run build

서버 실행 및 접속
이제 서버를 실행해주고 인스턴스의 퍼블릭 IPv4 DNS의 5000포트로 접속해보자.
cd ..

npm start

나의 express서버는 5000포트로 열어줬기 때문에 uri 끝에 5000을 붙여줘야한다.

하지만 접속 결과..접속 불가!

! 접속 안됨!
iPv4 DNS로 접속하니 접속이 안됨. 왜?
구글링을 해보니 인스턴스 보안탭에서 인바운드 규칙을 추가해줘야했다.

  • 보안 탭으로 이동하여 보안 그룹에 있는 아이디를 눌러준다.

  • 인바운드 규칙 편집을 눌러준다.

  • 규칙 추가를 눌러준다.

  • 유형은 사용자 지정 TCP로 설정하고 포트 범위는 나의 포트(5000)를 입력해준다.

  • 입력한뒤 규칙 저장을 눌러준다.

  • 이제 다시 5000포트로 접속해본다.

5000포트로 접속하니 성공적으로 배포된 것을 확인할 수 있다.

pm2 설치

그렇다면 이제 실행중인 서버를 터미널에서 종료해보자.

그리고 다시 나의 배포된 페이지에 들어가보자.

!!다시 페이지에 접속되지 않는다.

왜 접속되지 않는 것일까?
방금 터미널에서 서버를 종료했기 때문이다.
인스턴스 컴퓨터에서 서버를 종료하면 배포 환경도 중단된다.
배포가 중단됬기 때문에 접속할 수 없었던 것이다.

이 때 pm2라는 것을 설치하면 백그라운드에서 서버를 실행시켜주기 때문에 인스턴스에서 서버를 종료해도 계속 배포 환경이 실행될 수 있게 해준다!

pm2는 모든 디렉토리에서도 사용가능해야 하기 때문에 -g를 붙여서 글로벌로 설치하자.

// 전역 패키지 설치 시 sudo를 넣어줘야한다.
$ sudo npm -g install pm2

설치한 후 pm2 명령어를 통해 나의 서버 파일(app.js)를 실행해보자.

pm2 start app.js

파일이 아닌 명령어로 실행해야할 경우!
위와 같이 하나의 서버 파일을 실행할 때도 있지만 명령어로 실행하고 싶을 때도 있을 것이다.
(여러 파일과의 연관성으로 인해!)
그 때는 package.json이 있는 프로젝트 루트 디렉터리에서 다음과 같은 명령어를 실행하면 된다.
나의 경우 npm start로 서버를 시작하는 명령어를 실행놓았다.

pm2 start 'npm start'

Reference

이제는 터미널을 종료하여도 페이지가 잘 접속된다!!

다음 명령어로 현재 실행중인 프로세스를 조회할 수 있다.
pm2 list

pm2를 종료하기 위해서는 다음 명령어로 종료할 수 있다.

// pm2 stop 실행중인 process id
pm2 stop 0

나의 실행중인 프로세스 아이디는 0으로 확인되기 때문에 0으로 입력한 뒤 종료해준다.

포트 Redirect

현재 URI로 접속할 때 5000포트로 접속하고 있다.
당연히 내가 5000포트에서 실행주고 있기 때문에 5000포트로 접속해야 페이지 접속이 가능하다.

하지만 우리가 보통 웹페이지에 접근할 때 위와 같이 뒤에 포트번호가 붙이는 것을 보지 않는다.

일반적으로 우리가 웹페이지에 접속할 때는 기본 포트가 뒤에 붙어있다.
http의 경우 : 80
https의 경우 : 443
하지만 기본 포트는 보이지 않도록 설정되있기 때문에 위 포트로 접속하면 포트는 보이지 않는다.

예를 들어, http://ec2-13-124-23-148.ap-northeast-2.compute.amazonaws.com:80과 같이 http 프로토콜을 통해 접속을 하게 되면 뒤에 80이라는 포트가 보이지 않게 된다는 것이다.

따라서 나의 목적은 포트 번호를 보이지 않게 하기 위함이므로 80포트 접속했을 때(포트를 지정하지 않고 url을 치고 들어왔을 때) 5000포트로 리다이렉트 시켜주면 된다.

그렇다면 포트 리다이렉트를 해주는 명령어를 입력해보자.
명령어는 다음과 같다.

// 맨 뒤에 숫자만 자신의 실행하려는 포트번호를 입력해주면 된다.
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 5000

이제 포트번호(5000)을 붙이지 않고 접속을 해보자.
접속이 잘 되는 것을 확인할 수 있다!

redirect 포트를 확인하고 싶다면?

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

redirect 포트를 삭제하고 싶다면 다음 명령어를 실행!

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

[number] 자리에는 sudo iptables -t nat -L --line-numbers 명령어를 실행했을 때 다음 화면에 표시된 숫자를 입력해주면 된다.

마무리..

이상으로 ec2로 express로 만든 WAS서버를 배포하는 법을 살펴보았다.
aws 서비스를 처음 사용해보고 우분투라는 운영체제도 처음 사용해보는 등등 처음 접하는 부분이 많아 삽집과 고군분투를 많이 했지만 좋은 경험이었다.

또한 aws ec2 서비스를 이용하면서 네트워크 관련 설정이 많았는데 네트워크 관련해서도 공부를 해보고 싶다는 생각이 들었다.

또한 추후에 AWS codedeploy를 통해 자동 배포하는 방법도 해당 포스팅에 추가로 얹어 수정해보겠다.

다음 포스팅에는 aws S3와 cloudfront를 통해 배포하는 방법을 살펴보겠다.

profile
FE DEVELOPER

7개의 댓글

comment-user-thumbnail
2023년 8월 26일

이 포스트보고 막힘없이 진행했습니다 .감삼당

답글 달기
comment-user-thumbnail
2023년 9월 5일

선생님 계신 곳으로 큰 절 올리겠습니다

답글 달기
comment-user-thumbnail
2023년 9월 22일

감사합니다............진짜........

답글 달기
comment-user-thumbnail
2023년 11월 27일

이거 보고 2시간동안 따라해서 결국 성공함 감사합니다.

1개의 답글
comment-user-thumbnail
2024년 6월 29일

정말....개지립니다 선생님...

답글 달기
comment-user-thumbnail
2일 전

감사합니다!! 덕분에 AWS EC2로 프론트 배포 처음 해봤어요!!

답글 달기