AWS RDS, EC2, S3를 사용한 서버 무중단 배포기

Project Diary/React + MariaDB (PicShare WebApp)

이번 포스팅에서는 AWS의 RDS, EC2, S3를 활용하여 서버를 설정하고, 무중단 배포를 위해 PM2를 사용하는 방법을 단계별로 설명합니다.


<AWS 계정 및 인스턴스 설정>

1. AWS 계정 생성

 

2. EC2 인스턴스 생성

  • AWS Management Console에서 EC2 인스턴스를 생성합니다.
  • 인스턴스 생성 시 키 페어를 생성해야 합니다.
※ 키페어
- 인스턴스에 접근하기 위한 중요한 보안 정보
- 한 번만 발급되며, 이후에는 다시 다운로드 할 수 없기 때문에 안전한 곳에 잘 보관해야 합니다!!
( 저도 배포 다 하고 키 페어를 잃어버려 인스턴스를 새로 생성하여 다시 배포했습니다ㅠㅠ )
  • 인스턴스를 생성한 후, 탄력적 IP 주소를 할당하고 인스턴스에 연결합니다.
    네트워크 보안 -> 탄력적 IP -> 탄력적 IP 주소 할당 -> 기본 선택사항 "할당" -> 작업 -> 탄력적 IP 주소 연결 -> 생성한 인스턴스 선택 -> 연결

 

 

<RDS 설정>

3. RDS 데이터베이스 생성

  • RDS 서비스로 이동하여 MariaDB 데이터베이스를 생성합니다.
  • 템플릿에서 "프리티어"를 선택하고 필요한 설정을 완료합니다.

 

4. 보안 그룹 설정

  • VPC 보안 그룹에서 인바운드 규칙과 아웃바운드 규칙을 설정합니다.
  • 인바운드 규칙
    - MySQL/Aurora (TCP/3306)
    - SSH (TCP/22)
    - HTTP (TCP/80)
    - TTPS (TCP/443)

  • 아웃바운드 규칙
    - 모든 트래픽 (전체, 전체, 사용자 지정, 0.0.0.0/0)

5. RDS와 EC2 연결 설정

  • RDS 데이터베이스를 생성한 후, 해당 DB 인스턴스를 선택하여 EC2 인스턴스와 연결합니다.

  • HeidiSQL을 사용하여 RDS 데이터베이스에 접속하고, 필요한 테이블을 생성합니다.

6. HeidiSQL 설정

  • 네트워크 유형: MariaDB or MySQL (TCP)
  • Library: libmariadb.dll
  • 호스트명/IP: RDS -> 데이터베이스 -> 연결 및 보안 -> 엔드포인트
  • 사용자: RDS에서 설정한 사용자명
  • 암호: RDS에서 설정한 암호
  • 포트: 3306
  • 로컬 컴퓨터에서 테스트했던 DB와 테이블을 "데이터베이스를 SQL로 내보내기" 한 내용을 AWS 데이터베이스에 쿼리로 복사하여 붙여넣기 합니다. Foreign key가 없는 테이블부터 먼저 생성합니다.

7. DB 설정

  • erver 폴더의 db.js 파일을 수정하여 위에서 설정한 호스트명, 사용자, 암호, 데이터베이스명으로 설정합니다.

8. web.js 파일 수정

  • server 폴더의 web.js 파일에서 포트를 80으로 설정합니다.
const PORT = 80;

 

 

<S3 설정 및 파일 업로드>

 

9. IAM 사용자 생성

  • AWS Management Console에서 IAM을 검색하고, 사용자를 생성합니다.
  • 사용자 이름 입력 -> 권한 옵션 "직접 정책 연결" -> S3 검색: AmazonS3FullAccess 선택 -> 생성
  • 생성된 사용자명을 클릭하고 "액세스 키 만들기"를 선택합니다.
  • 액세스 키와 시크릿 키를 생성하고 안전하게 보관합니다.

 

10. S3 버킷 생성

 

11. 버킷 설정

  • 생성된 버킷 이름, 액세스 키, 시크릿 키를 프로젝트의 router에 설정합니다.
  • 필요한 라이브러리 설치
npm i aws-sdk multer
  • 예시
import multer from "multer";
import AWS from 'aws-sdk';
import fs from 'fs';

const upload = multer({ dest: 'uploads/' });
const s3 = new AWS.S3({
  accessKeyId: '액세스키',
  secretAccessKey: '시크릿키',
  region: 'ap-northeast-2'
});   

const params = {
    Bucket: '버킷이름',  
    Key: req.file.filename,
    Body: fileContent
};

 

12. 클라이언트 이미지 경로 수정

<img src={`${serverUrl}/uploads/${item.photo}`} alt={item.name} />
<img src={item.photo} alt={item.name} />

 

 

<소스 코드 배포하기>

13. SSH 로그인 문제 해결

*.pem 키가 있는 폴더에서 마우스 우클릭 > "속성" > "보안" > "Administrator" 선택 > 중간에 "고급" > "Administrator" 선택 > 아래쪽에 "상속 사용 안 함" 클릭 > "이 개체에서 상속된 사용 권한을 모두 제거합니다." 선택 > 확인 > 확인

 

14. 소스 코드 배포

  • 기존에 build 폴더가 있으면 삭제합니다.
npm run build
server 폴더에서 node_modules 폴더도 삭제
  • SSH 로그인
ssh -i "*.pem 파일이 있는 경로와 파일명" ubuntu@퍼블릭 IPv4 DNS
  • 로그인 성공 후 다음 명령 실행(처음 한 번만)
sudo apt update
sudo apt install npm
sudo apt install nodejs
  • 업로드 후 SSH 창으로 이동
cd /home/ubuntu/server
ls -l  # 업로드 파일 목록 확인
npm install  # node_modules 새로 설치
sudo npm start  # 서버 실행
  • 브라우저 주소창에 "퍼블릭 IPv4 DNS"를 복사하여 붙여넣기

 

15. 코드 수정 후 재배포

  • 클라이언트 코드를 수정한 경우 build 폴더를 삭제하고 다시 빌드합니다.
npm run build
  • SSH 창에서 이전에 업로드한 server 폴더 삭제
cd /home/ubuntu/
rm -rf server
ls -l
  • 소스 코드 다시 업로드
scp -i "*.pem 파일 경로" -r "server 폴더 경로" ubuntu@퍼블릭 IPv4 DNS:/home/ubuntu/

 


 

<PM2를 통한 무중단 배포>

 

16. PM2 설치 및 설정

  • PM2를 글로벌로 설치합니다.
sudo npm install -g pm2

 

17. 서버 애플리케이션을 PM2로 시작

cd /home/ubuntu/server
pm2 start web.js --name "my-server"  # my-server는 원하는 이름으로 변경 가능합니다.

 

 

18. PM2 설정 저장 및 시스템 시작 설정

pm2 save
pm2 startup

 

-- 위 명령을 실행하면 아래와 같이 출력된 명령어를 그대로 실행합니다.

sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u ubuntu --hp /home/ubuntu

 

19. 애플리케이션 상태 확인 및 로그 확인

  • 애플리케이션 상태 확인
pm2 status
  • 로그 확인
pm2 logs my-server

 

20. 포트 80 사용 권한 부여

  • 로그 확인 시 포트 80에서 열 수 없다는 오류가 발생하면 다음 명령어로 권한을 부여합니다.
sudo setcap 'cap_net_bind_service=+ep' $(which node)
pm2 restart my-server

 


<AWS 과금 주의사항>

 

> 인스턴스 중지 및 종료

  • 인스턴스를 사용하지 않을 경우 중지 후 종료해야 과금이 발생하지 않습니다.
  • 인스턴스를 종료할 때 연결된 리소스로 인해 비용이 발생할 수 있으므로, 네트워킹 -> 탄력적 IP 주소 연결 해제를 해야 합니다.
  • VPC 대시보드 -> 서브넷 -> 서브넷 ID 선택 -> 작업 -> 서브넷 설정 편집 -> 퍼블릭 IPv4 주소 자동 할당 활성화 선택 해제