


EC2(Elastic Compute Cloud) : 컴퓨팅 자원(Virtual Machine)을 클라우드로 제공하는 가상 서버 서비스
Elastic IP(Elastic IP Address) : 클라우드 컴퓨팅을 위한 정적 IPv4 주소, EC2 인스턴스에 연결 가능 (클라이언트에 접속하는 IP 주소의 변경 없이 서버의 장애 극복)
Security Group(보안 그룹) : 인스턴스에 대한 트래픽을 제어하는 가상의 방화벽 역할
ELB(Elastic Load Balancing) : Load Balancing을 위해 리전에 존재하는 서비스, 부하를 대상 그룹(Target Group)에 속한 EC2 인스턴스에게 분산
Load Balancing : 부하(트래픽)를 여러 대의 서버로 분산시켜 처리하는 것 (성능과 안정성 향상, 서버의 장애 예방에 기여)
리스너(Listener) : 프로토콜과 포트를 기반으로 외부의 요청을 적절한 타겟으로 전달
Auto Scaling : 트래픽에 따라 자동으로 서버(EC2 인스턴스)의 개수를 조절해주는 기능 (서비스의 안정적 제공과 효율적인 서버 운영)
Auto Scaling이 생성하는 EC2 인스턴스의 사전 정보는 시작 템플릿으로 설정 (AMI 사용 가능)
AMI(Amazon Machine Image) : 인스턴스를 실행하기 위한 정보를 모은 단위로, OS가 설치된 형태의 이미지(템플릿) 파일 (AMI로 EC2 인스턴스를 생성하고 실행 가능)
Auto Scaling Group(ASG) : 가용 영역을 ELB의 대상 그룹(Target group)과 동일하게 설정, ELB는 Auto Scaling으로 생성된 EC2 인스턴스에 부하를 분산
Lambda : 서버리스 컴퓨팅 서비스, 특정한 주기 혹은 트리거에 의해 간단한 코드를 실행할 때 사용

EBS(Elastic Block Store) : EC2에 연결(attach)하여 쓸 수 있는 블록 스토리지
볼륨(Volume) : EBS의 가장 기본적인 형태 (단, 한 개의 EBS에 여러 개의 EC2 인스턴스 연결 불가)
스냅샷(Snapshot) : 볼륨의 특정 시점을 그대로 복사하여 저장한 파일, 스냅샷을 이용해 볼륨을 생성하거나(특정 시점의 데이터 복구) AMI를 생성
S3(Simple Storage Service) : 객체 기반의 파일 저장 스토리지 (데이터의 일부분만 수정이 불가능한 대신 확장성이 높고 안전하게 파일을 저장 가능)
Bucket(버킷)을 생성하고 파일을 업로드한 다음 Object(객체)의 권한을 설정하여 HTTP로 파일을 다운로드 가능
URL을 통해 파일을 공유하고 정적 웹사이트를 호스팅 가능, 데이터 백업에도 적합
RDS(Relational Database Service) : 관계형 데이터베이스 서비스, 데이터베이스를 여러 대 복제하는 Replication을 기반으로 함
Master DB(Primary DB) & Standby DB (장애가 발생하면 Standby DB로 읽기와 쓰기 작업을 진행하는 Failover를 수행) & Read Replica (읽기 전용으로 만들어진 복제본)
다중 AZ(Multi-AZ) : 단일 지역의 2개 이상의 가용 영역에 걸쳐 데이터베이스를 구축하는 것
Master DB 인스턴스를 만들고 다중 AZ 배포로 변환하여 Standby DB를 만든 다음, 다른 리전에 Read Replica를 생성
EC2 인스턴스가 RDS를 사용하게 하려면 EC2 인스턴스의 설정 파일과 RDS의 보안 규칙을 변경 (Auto Scaling이 설정되어 있다면 AMI, 시작 템플릿도 변경)
DynamoDB : 완전 관리형 클라우드 NoSQL 데이터베이스 (스키마가 없는 데이터 모델에 최적화)
기본 키(Primary Key) : 단순 기본 키(파티션 키)와 복합 기본 키(파티션 키 + 정렬 키)
파티션 키(Partition Key) : 데이터가 저장되는 파티션을 결정
정렬 키(Sort Key) : 동일한 파티션 내의 항목을 정렬
보조 인덱스 : 글로벌 보조 인덱스(Global Secondary Index)(전체 테이블), 로컬 보조 인덱스(Local Secondary Index)(파티션 내)
데이터 조회 : 키 기반으로 Query 혹은 전체 데이터를 가져와 필터링하는 Scan

CloudFront : CDN 역할의 서비스로, 캐싱을 통해 콘텐츠를 빠르게 전송할 수 있게 함
기본 단위는 배포(Distribution)
CloudFront로 S3 Origin에서 원본 파일을 가져오려면 S3 버킷 정책을 수정
Route 53 : DNS 시스템, 도메인 이름을 IP 주소로 바꿔줌
CloudWatch : 클라우드 모니터링 서비스
로그 데이터 및 지표를 모니터링
경보 기능으로 조건에 따라 알람을 전달
IAM (Identity and Access Management) : AWS 리소스에 대한 권한을 관리하는 서비스
IAM 사용자를 추가하여 권한(Role)을 제한적으로 부여 가능
IAM 그룹을 생성하여 그룹에 속한 사용자에게 특정 권한을 부여 가능
AWS SDK(Software Development Kit) : 애플리케이션에 AWS를 연동하기 위한 개발 도구의 집합
AWS CLI(Command Line Interface) : 명령행 도구


Step 1. EC2 인스턴스 생성하기

Ubuntu 인스턴스 생성 후 SSH 접속

Node.js 설치 → 설치 방법
sudo apt-get install -y curl
curl -fsSL https://deb.nodesource.com/setup_23.x -o nodesource_setup.sh
sudo -E bash nodesource_setup.sh
sudo apt-get install -y nodejs
node -v
Express 설치 (Node.js 웹 애플리케이션 프레임워크)
sudo mkdir project
sudo chown ubuntu:ubuntu project/ (폴더의 소유자 변경)
cd project → npm init -y
npm install express
Vim 환경 설정
vim ~/.vimrc
set autoindent
set ts=4
set shiftwidth=4
set nu
Step 2. 보안 그룹 설정하기



project/index.js 작성
const express = require('express');
const PORT = 3000;
const app = express();
app.get('/', (req, res) => {
res.send("Hello, World!");
});
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}...`);
});
node index.js 실행 후 <퍼블릭 IPv4 주소>:3000으로 접속

Step 3. 이미지 파일 업로드 API 만들기
기존 폴더 삭제
cd ~ → rm -r project프로젝트 기본 구조 만들기
cd /home → sudo npx express-generator --view=ejs project
프로젝트 폴더 소유자 변경
sudo chown -R ubuntu:ubuntu project/패키지 설치
cd project → npm install서버 시작
npm start
multer 설치 및 사용하기 (API 작성)
npm install multer
파일 복사 cd routes → cp users.js images.js
vim images.js로 파일 수정
const express = require('express');
const fs = require('fs');
const path = require('path');
const multer = require('multer');
const router = express.Router();
const upload = multer({
dest: path.join(__dirname, '..', 'uploads')
});
router.get('/', (req, res, next) => {
res.send('respond with a resource');
});
router.post('/', upload.single('new-image'), (req, res, next) => {
console.dir(req.file);
res.send();
});
module.exports = router;
Router 등록
cd .. → vim app.js로 파일 수정
HTML 파일 수정하기
cd views → vim index.ejs로 파일 수정
① Bootstrap
label 태그의 for 속성, input 태그의 id 속성을 file-upload로 변경
div 태그에 id="progress" 속성 추가 및 aria-valuenow 속성을 0으로 변경, 하위 div 태그 style="width: 0%" 속성 변경



② jQuery
jQuery 페이지 3.7.1 minified 버전 script 추가
jQuery UI 페이지 1.13 minified 버전 script 추가

③
<script src="https://blueimp.github.io/jQuery-File-Upload/js/jquery.fileupload.js" crossorigin="anonymous"></script> 추가
input 태그에 name="new-image" 속성 추가

④ 최하단에 jQuery 코드 추가
<script>
$(function () {
$('#file-upload').fileupload({
url: '/images',
dataType: 'json',
progressall: function (e, data) {
var progress = parseInt(
(data.loaded / data.total) * 100,
10
);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
},
});
});
</script>
npm start으로 서버를 실행하고 이미지를 업로드하면 로그 확인 가능


Step 4. S3 버킷 연결하기 (AWS SDK for JavaScript)

S3 버킷 생성하기

공유 자격 증명 설정하기






AWS SDK for JavaScript 설치하기
npm install @aws-sdk/client-s3S3 연결하기
routes 폴더에서 vim images.js 실행, 아래와 같이 코드 수정
const express = require('express');
const fs = require('fs');
const path = require('path');
const multer = require('multer');
const router = express.Router();
const upload = multer({
dest: path.join(__dirname, '..', 'uploads')
});
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const s3Client = new S3Client({ region: 'ap-northeast-2' });
router.get('/', (req, res, next) => {
res.send('respond with a resource');
});
router.post('/', upload.single('new-image'), (req, res, next) => {
console.dir(req.file);
fs.readFile(req.file.path, (err, data) => {
s3Client.send(
new PutObjectCommand({
Bucket: '버킷 이름',
Key: req.file.filename,
Body: data,
ContentType: req.file.mimetype,
})
)
.then((data) => {
console.log(data);
res.send(data);
})
.catch((error) => {
console.log(error);
});
});
});
module.exports = router;
npm start 후 이미지를 업로드하면 S3 버킷에 업로드됨
Step 5. CloudFront로 S3 파일 보여주기

CloudFront 배포 생성 및 정책 편집





API 코드 수정
routes 폴더에서 vim images.js 실행, 아래와 같이 코드 수정 (객체 최대 50개 읽어옴)
const express = require('express');
const fs = require('fs');
const path = require('path');
const multer = require('multer');
const router = express.Router();
const upload = multer({
dest: path.join(__dirname, '..', 'uploads')
});
const { S3Client, PutObjectCommand, ListObjectsV2Command } = require('@aws-sdk/client-s3');
const s3Client = new S3Client({ region: 'ap-northeast-2' });
router.get('/', (req, res, next) => {
s3Client.send(
new ListObjectsV2Command({
Bucket: '버킷 이름',
MaxKeys: 50,
})
)
.then((data) => {
res.send(data.Contents);
})
.catch((error) => {
console.log(error);
});
});
router.post('/', upload.single('new-image'), (req, res, next) => {
console.dir(req.file);
fs.readFile(req.file.path, (err, data) => {
s3Client.send(
new PutObjectCommand({
Bucket: '버킷 이름',
Key: req.file.filename,
Body: data,
ContentType: req.file.mimetype,
})
)
.then((data) => {
console.log(data);
res.send(data);
})
.catch((error) => {
console.log(error);
});
});
});
module.exports = router;
npm start 후 <퍼블릭 IPv4 주소>:3000/images로 접속
HTML 파일 수정
views 폴더에서 vim index.ejs 실행
<div id="image-list"></div> 추가
최하단에 jQuery 코드 추가
<script>
$.getJSON('/images', function (data) {
$.each(data, function (i, e) {
const img = $('<img>');
img.attr(
'src',
'<CloudFront 배포 도메인 이름>/' + e.Key
)
.attr({ width: '200px', height: '200px' })
.addClass('img-thumbnail');
$('#image-list').append(img);
});
});
</script>
npm start 후 <퍼블릭 IPv4 주소>:3000로 접속
Step 6. ELB Load Balancer 설정하기
pm2 설치 (Node.js용 프로세스 매니저)
sudo npm install pm2 -g
프로젝트 폴더에서 pm2 start ./bin/www
애플리케이션 상태 확인 pm2 show www
서버 부팅 시 자동 시작 설정 : pm2 startup 명령어를 실행하면 나오는 명령어를 복사하여 실행
프로세스 목록 저장 pm2 save
dump 파일 내용 확인 cat ~/.pm2/dump.pm2
"pm_exec_path"에 실행 경로가 들어가있음EC2 인스턴스 재부팅 후 애플리케이션이 잘 구동되는지 확인
ELB Load Balancer 설정하기
ELB Load Balancer 생성
Application Load Balancer 선택
EC2 인스턴스가 존재하는 가용 영역 포함
대상 그룹에 인스턴스 등록 (포트 번호 3000번으로 설정)
ELB 생성 후 3000번 포트 리스너 추가
DNS 이름의 3000번 포트로 접속




Step 7. Auto Scaling 설정하기
AMI 생성하기

Auto Scaling Group 생성하기
시작 템플릿 생성 필요
ELB의 대상 그룹(Target Group)과 동일하게 가용 영역을 설정
S3에 접근할 수 있도록 IAM 권한 설정





DNS 이름의 3000번 포트로 접속하면 최종적으로 잘 실행됨

Problem : Auto Scaling 이후, DNS 이름의 3000번 포트로 접속했을 때 이미지가 나오기도 나오지 않기도 하는 문제점 발생
Examination : 생성된 EC2 인스턴스에서 이미지를 GET, POST하는 요청만이 되지 않는 상황이므로 S3 권한과 관련된 문제
pm2 monit 명령어로 로그를 관찰한 결과 credentials에 대한 문제임을 확인
Solution : 시작 템플릿에 IAM 권한(S3 접근 권한)이 포함되지 않은 것으로, AMI를 생성할 때 IAM 권한이 포함되도록 해야 했음

참고 자료
└ 소플의 처음 만난 AWS