AWS 입문 가이드 | EC2, S3, RDS 실전 사용법
이 글의 핵심
AWS 입문 가이드에 대해 정리한 개발 블로그 글입니다. EC2로 서버를 올리고, S3에 정적 파일을 두고, RDS로 DB를 붙이는 흐름을 한 번에 잡는다. 무료 티어 한도는 문서와 함께 꼭 확인할 것. --- 클라우드는 인터넷으로 컴퓨팅·스토리지를 빌려 쓰는 방식이다.… 개념과 예제 코드를 단계적으로 다루며, 실무·학습에 참고할 수 있도록 구성했습니다. 관련 키워드: AWS,…
이 글의 핵심
EC2로 서버를 올리고, S3에 정적 파일을 두고, RDS로 DB를 붙이는 흐름을 한 번에 잡는다. 무료 티어 한도는 문서와 함께 꼭 확인할 것.
사전 지식 (초보자를 위한 기초)
1. 클라우드란?
클라우드는 인터넷으로 컴퓨팅·스토리지를 빌려 쓰는 방식이다.
전통적인 방식 (온프레미스):
- 서버를 직접 구매 (수천만 원)
- 데이터 센터 구축
- 유지보수 직접 관리
- 초기 비용 높음
클라우드 방식:
- 필요한 만큼만 빌려 씀
- 사용한 만큼만 지불
- 유지보수는 AWS가 담당
- 초기 비용 거의 없음
온프레미스는 장비를 사서 직접 돌리는 쪽이고, 클라우드는 필요한 만큼만 쓰고 반납에 가깝다. 비용·운영 방식이 달라진다.
2. 클라우드 서비스 모델
IaaS (Infrastructure as a Service)
- 가상 서버, 스토리지, 네트워크 제공
- 예: AWS EC2, S3
PaaS (Platform as a Service)
- 애플리케이션 실행 환경 제공
- 예: AWS Elastic Beanstalk, Heroku
SaaS (Software as a Service)
- 완성된 소프트웨어 제공
- 예: Gmail, Notion, Slack
3. AWS 주요 서비스
컴퓨팅:
- EC2: 가상 서버
- Lambda: 서버리스 함수
스토리지:
- S3: 파일 저장소
- EBS: 블록 스토리지
데이터베이스:
- RDS: 관계형 DB (MySQL, PostgreSQL)
- DynamoDB: NoSQL DB
네트워킹:
- VPC: 가상 네트워크
- CloudFront: CDN
- Route 53: DNS
보안:
- IAM: 권한 관리
- Cognito: 사용자 인증
1. AWS란 무엇인가?
AWS의 장점
1. 확장성
- 트래픽 증가 시 자동 확장
- 클릭 몇 번으로 서버 추가
2. 안정성
- 99.99% 가동률 보장
- 전 세계 데이터 센터
3. 비용 효율
- 사용한 만큼만 지불
- 무료 티어 제공
4. 보안
- 물리적 보안
- DDoS 방어
- 암호화 지원
AWS 리전과 가용 영역
리전 (Region):
- 지리적 위치 (서울, 도쿄, 미국 등)
- 각 리전은 독립적
가용 영역 (Availability Zone):
- 리전 내 독립적인 데이터 센터
- 서울 리전: ap-northeast-2a, ap-northeast-2b, ap-northeast-2c
예시:
┌─────────────────────────────────┐
│ Seoul Region (ap-northeast-2)│
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │ AZ-a │ │ AZ-b │ │ AZ-c │ │
│ │ DC 1 │ │ DC 2 │ │ DC 3 │ │
│ └──────┘ └──────┘ └──────┘ │
└─────────────────────────────────┘
AZ-a에 장애 발생해도 AZ-b, AZ-c는 정상 작동
2. AWS 계정 생성 및 설정
계정 생성
1. https://aws.amazon.com/ko/ 접속
2. "AWS 계정 생성" 클릭
3. 이메일, 비밀번호 입력
4. 신용카드 등록 (무료 티어 사용 시 과금 없음)
5. 본인 인증 (전화)
6. 지원 플랜 선택 (기본 - 무료)
무료 티어
12개월 무료:
- EC2: t2.micro 인스턴스 750시간/월
- S3: 5GB 스토리지
- RDS: db.t2.micro 750시간/월
- Lambda: 100만 요청/월
영구 무료:
- Lambda: 100만 요청/월
- DynamoDB: 25GB 스토리지
- CloudWatch: 10개 지표
IAM 사용자 생성 (보안)
⚠️ 루트 계정 직접 사용 금지!
1. IAM 콘솔 접속
2. "사용자" → "사용자 추가"
3. 사용자 이름: admin-user
4. 권한: AdministratorAccess
5. 액세스 키 생성 (CLI 사용 시)
6. MFA 활성화 (2단계 인증)
3. VPC 네트워킹 기초
VPC(Virtual Private Cloud)는 계정 전용 가상 네트워크다. EC2·RDS·Lambda( VPC 내부에 두는 경우)가 모두 이 경계 안에서 서로 통신한다. 콘솔에서 “기본 VPC”를 쓰면 빠르게 시작할 수 있지만, 운영·보안을 생각하면 서브넷·라우팅·게이트웨이를 머릿속에 그릴 수 있어야 한다.
CIDR, 서브넷, 가용 영역
VPC (예: 10.0.0.0/16)
├── 퍼블릭 서브넷 (10.0.1.0/24, AZ-a)
│ └── 인터넷 게이트웨이(IGW)로 나가는 라우트
├── 퍼블릭 서브넷 (10.0.2.0/24, AZ-b)
└── 프라이빗 서브넷 (10.0.10.0/24, AZ-a)
└── NAT 게이트웨이를 경유해 아웃바운드만 인터넷
- CIDR: VPC와 서브넷의 IP 주소 범위. 겹치지 않게 설계한다.
- 서브넷: AZ 하나에 묶인 IP 범위. 같은 AZ에 여러 서브넷을 둘 수 있다.
- 라우트 테이블: “이 대역은 IGW로, 이 대역은 VPC 내부로” 같은 다음 홉 규칙이다. 잘못 붙이면 EC2는 떠 있는데 외부에서 안 보이거나, 반대로 DB만 있어야 할 서브넷이 인터넷에 노출된다.
인터넷 게이트웨이와 NAT
| 구분 | 역할 | 흔한 용도 |
|---|---|---|
| IGW | VPC와 인터넷 사이 양방향 | 퍼블릭 웹 서버, 로드밸런서 |
| NAT 게이트웨이 | 프라이빗 서브넷 → 인터넷 아웃바운드만 | 패치·외부 API 호출이 필요한 앱 서버 |
| NAT 인스턴스 | NAT를 EC2로 직접 구성 | 레거시·특수 요구 시(운영 부담 큼) |
프라이빗 서브넷의 인스턴스는 퍼블릭 IP 없이 NAT 뒤에 두고, RDS는 프라이빗 서브넷 + 애플리케이션 보안 그룹만 허용이 전형적 패턴이다.
보안 그룹 vs 네트워크 ACL
네트워크 ACL (서브넷 경계)
- 상태 비저장(Stateless), 번호 순 규칙
- 서브넷 단위 방화벽
보안 그룹 (ENI/인스턴스)
- 상태 저장(Stateful), 허용만 기술
- 리소스에 붙는 가상 방화벽
보안 그룹은 “이 EC2는 443으로 들어온 트래픽의 응답은 자동 허용”처럼 상태를 이해한다. NACL은 서브넷 입구의 거친 필터로, 둘 다 맞아야 통과한다는 식으로 방어를 겹쳐 쓸 수 있다.
DNS, 엔드포인트, 하이브리드
- Route 53 프라이빗 호스트 존: VPC 내부 이름 해석(예:
db.internal.local). - VPC 엔드포인트(Interface/Gateway): S3·DynamoDB 등으로 가는 트래픽을 인터넷을 타지 않고 AWS 백본으로 보내 비용·노출을 줄인다.
- 피어링·Transit Gateway: VPC 간 또는 온프레미스와 연결할 때 사용한다.
초보 단계에서는 기본 VPC + 보안 그룹 최소 개방으로 시작하고, 서비스가 커지면 퍼블릭/프라이빗 서브넷 분리·NAT·엔드포인트 순으로 다듬으면 된다.
라우팅 테이블·NAT 배치 예시
퍼블릭 서브넷 라우트 테이블에는 0.0.0.0/0 → Internet Gateway가 있어야 인스턴스가 퍼블릭 IP(또는 EIP)로 인바운드·아웃바운드 인터넷이 가능하다. 프라이빗 서브넷은 기본 라우트를 IGW에 붙이지 않고, 아웃바운드만 필요하면 0.0.0.0/0 → NAT Gateway를 둔다(NAT는 퍼블릭 서브넷에 위치).
[퍼블릭 서브넷 rtb-public]
10.0.0.0/16 → local
0.0.0.0/0 → igw-0abc...
[프라이빗 앱 서브넷 rtb-private-app]
10.0.0.0/16 → local
0.0.0.0/0 → nat-0def... # 패키지 설치·외부 API
[프라이빗 DB 서브넷 rtb-private-db]
10.0.0.0/16 → local
# 기본 라우트 없음 → 인터넷 직접 출구 없음(가장 안전한 형태)
NAT Gateway는 시간당·데이터 처리 요금이 있으므로, 개발 환경에서는 NAT 인스턴스(저비용·직접 관리)나 VPC 엔드포인트로 AWS API만 쓰는 방식으로 NAT 비용을 줄이는 경우도 있다.
S3 Gateway VPC 엔드포인트(정책 예시)
프라이빗 서브넷의 애플리케이션이 S3로 가는 트래픽을 IGW/NAT 없이 AWS 백본으로 보내려면 Gateway 엔드포인트를 라우트 테이블에 연결한다. 엔드포인트 정책으로 허용 버킷을 제한할 수 있다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-app-bucket/*"
},
{
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:PutObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::my-app-bucket",
"arn:aws:s3:::my-app-bucket/*"
]
}
]
}
보안 그룹 참조로 티어 간 최소 개방
DB는 CIDR 전체 개방(10.0.0.0/16) 대신 애플리케이션 보안 그룹 ID를 소스로 거는 편이 감사·최소 권한에 유리하다.
규칙 예:
- sg-alb : 인바운드 443 ← 0.0.0.0/0
- sg-app : 인바운드 8080 ← sg-alb
- sg-rds : 인바운드 5432 ← sg-app
이렇게 하면 “웹 티어가 바뀌어도 IP 대역을 손대지 않고 보안 그룹 참조만 유지”할 수 있다.
4. EC2 - 가상 서버
EC2란?
EC2 (Elastic Compute Cloud)는 AWS의 가상 서버다.
비유: 컴퓨터 한 대를 빌리는 것
- 원하는 사양 선택 (CPU, 메모리)
- 원하는 OS 선택 (Ubuntu, Amazon Linux)
- 필요할 때 켜고 끄기 가능
- 사용한 시간만큼 과금
EC2 인스턴스 생성
1) EC2 콘솔 접속
1. AWS 콘솔 → EC2
2. "인스턴스 시작" 클릭
2) 설정
이름: my-web-server
AMI (운영체제):
- Ubuntu Server 22.04 LTS 선택
인스턴스 유형:
- t2.micro (무료 티어)
- vCPU: 1개, 메모리: 1GB
키 페어:
- "새 키 페어 생성" 클릭
- 이름: my-key
- .pem 파일 다운로드 (SSH 접속용)
네트워크 설정:
- 보안 그룹: SSH (22), HTTP (80), HTTPS (443) 허용
스토리지:
- 8GB (무료 티어 최대 30GB)
"인스턴스 시작" 클릭
3) SSH 접속
# Linux/Mac
chmod 400 my-key.pem
ssh -i my-key.pem ubuntu@<Public-IP>
# Windows (PowerShell)
ssh -i my-key.pem ubuntu@<Public-IP>
웹 서버 구축
# 1. 패키지 업데이트
sudo apt update && sudo apt upgrade -y
# 2. Node.js 설치
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
# 3. 애플리케이션 배포
git clone https://github.com/your-repo/app.git
cd app
npm install
npm run build
# 4. PM2로 프로세스 관리
sudo npm install -g pm2
pm2 start npm --name "my-app" -- start
pm2 startup
pm2 save
# 5. Nginx 설정 (리버스 프록시)
sudo apt install -y nginx
sudo nano /etc/nginx/sites-available/default
Nginx 설정:
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
# Nginx 재시작
sudo systemctl restart nginx
EC2 가상화와 Nitro 아키텍처
EC2 인스턴스는 물리 서버 위에서 돌아가는 가상 머신이다. 초기에는 Xen 하이퍼바이저가 흔했고, 현재 대부분의 최신 인스턴스 패밀리는 AWS Nitro System 위에서 동작한다. 입문자에게는 “왜 내 코드와 상관없이 네트워크·디스크가 빨라졌나?”를 이해하는 힌트가 된다.
[전통적 가상화]
게스트 OS + 앱
↑
하이퍼바이저(CPU 일부 소모) ← 네트워크/스토리지 가상화도 CPU가 담당
↑
물리 서버
[Nitro의 방향]
네트워크·EBS I/O·모니터링 등을 **Nitro 카드(전용 하드웨어)**로 오프로드
→ CPU는 거의 **고객 워크로드**에만 사용
Nitro를 이렇게 나누어 보면 이해가 쉽다.
- Nitro 하이퍼바이저: 가상화 제어를 담당하되, 경량화되어 있다.
- Nitro 카드: VPC 네트워킹, EBS(블록 스토리지) 경로 등을 전용 칩으로 처리해 CPU 부담을 줄인다.
- Nitro 보안 칩: 인스턴스 스토리지 암호화·보안 관련 기능과 연계된다(제품 세대에 따라 제공 범위 상이).
실무 관점에서는 베어메탈에 가까운 네트워크 처리량·지연 특성을 기대할 수 있고, 같은 vCPU라도 세대·Nitro 기반 여부에 따라 성능이 달라질 수 있다. 인스턴스 선택 시 인스턴스 패밀리 설명에서 Nitro 기반 여부와 네트워크 성능(예: 최대 대역폭)을 함께 보면 된다.
인스턴스 패밀리·크기 선택(실무 체크리스트)
1) 먼저 워크로드 유형을 나눈다. CPU 위주(배치·압축), 메모리 위주(캐시·JVM 힙 큰 앱), 네트워크·디스크 I/O 위주(파일 서버·로그 수집)에 따라 범용(M)·컴퓨트 최적화(C)·메모리 최적화(R)·스토리지 최적화(I/D) 패밀리 후보가 달라진다. 입문·소규모 웹/API는 보통 범용 M 시리즈 또는 버스트 가능 T 시리즈에서 시작한다.
2) T 시리즈(예: t3, t4g)는 “평소 낮은 CPU, 가끔 스파이크”에 맞춘 버스트형이다. CPU 크레딧을 소모하면 기준 성능(baseline) 아래로 떨어질 수 있어, 지속적으로 vCPU를 100%에 가깝게 쓰는 서비스에는 부적합할 수 있다. 반면 트래픽이 들쭉날쭉한 개발·스테이징·소규모 사이트에는 비용 대비 효율이 좋다. Graviton(ARM) 기반 t4g는 x86 대비 과금이 낮은 편이라, 애플리케이션이 ARM 빌드를 지원하면 비용 절감 후보다.
3) 고정 성능이 필요하면 M/C/R의 온디맨드 또는 Savings Plans를 검토한다. 예를 들어 API 서버가 항상 일정 RPS를 처리한다면 m7i.large·m7g.large 같은 고정 크레딿 없는 인스턴스가 예측 가능하다. 데이터베이스를 EC2에 직접 올리는(셀프 매니지드) 경우 메모리 여유가 중요해 R 시리즈가 후보가 되고, 비디오 트랜스코딩처럼 CPU 밀도가 높으면 C 시리즈가 후보다.
4) 디스크는 EBS 볼륨 타입과 인스턴스의 EBS 최대 대역폭을 함께 본다. gp3는 기본 IOPS·처리량을 설정해 비용과 성능을 균형 있게 맞출 수 있고, 지연에 민감한 DB 볼륨에는 io2/io2 Block Express 검토가 나온다. 인스턴스 유형 페이지의 “네트워크 성능”·“EBS 전용 대역폭”이 병목인지 CloudWatch CPUCreditBalance, EBSIOBalance%, NetworkOut으로 확인한다.
| 목적 | 흔한 출발점 | 메모 |
|---|---|---|
| 개인 블로그·데모 | t3.micro / t4g.micro | 무료 티어·저비용, 버스트 한도 주의 |
| 소규모 웹·Node API | t3.small~medium, m7g.large | 트래픽이 안정되면 M으로 이관 |
| CPU 바운드 작업 | c7i / c7g | vCPU당 비용·성능 비교 |
| 메모리 많은 앱·캐시 | r7i / r7g | JVM heap, Redis 등 |
| ARM 이전 검증 | 동급 m7g vs m7i | 벤치마크 후 Savings Plans |
5) Auto Scaling과 함께 쓸 때는 시작 템플릿에 동일 AMI·User Data를 맞추고, 스케일 아웃 시 병목이 CPU인지 메모리인지에 따라 다른 인스턴스 타입을 혼합한 Mixed Instances Policy를 둘 수 있다(비용·가용성 트레이드오프).
5. S3 - 파일 저장소
S3란?
S3 (Simple Storage Service)는 객체 단위로 파일을 올리는 스토리지다. 용량은 사용만큼 늘어난다.
용도:
- 이미지, 동영상 저장
- 정적 웹사이트 호스팅
- 백업 및 아카이브
- 로그 파일 저장
특징:
- 용량 무제한
- 99.999999999% (11 nines) 내구성
- 저렴한 비용
S3 버킷 생성
1. S3 콘솔 → "버킷 만들기"
2. 버킷 이름: my-app-bucket (전 세계에서 유일해야 함)
3. 리전: 아시아 태평양 (서울)
4. 퍼블릭 액세스 차단: 체크 (보안)
5. "버킷 만들기" 클릭
파일 업로드
AWS CLI 설치:
# macOS
brew install awscli
# Windows
choco install awscli
# Linux
sudo apt install awscli
# 설정
aws configure
# AWS Access Key ID: [입력]
# AWS Secret Access Key: [입력]
# Default region: ap-northeast-2
# Default output format: json
파일 업로드:
# 단일 파일 업로드
aws s3 cp image.jpg s3://my-app-bucket/images/
# 폴더 전체 업로드
aws s3 sync ./dist s3://my-app-bucket/website/
# 파일 목록 확인
aws s3 ls s3://my-app-bucket/
# 파일 다운로드
aws s3 cp s3://my-app-bucket/images/image.jpg ./
Node.js에서 S3 사용
npm install @aws-sdk/client-s3
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';
import fs from 'fs';
const s3Client = new S3Client({ region: 'ap-northeast-2' });
// 파일 업로드
async function uploadFile(filePath, key) {
const fileContent = fs.readFileSync(filePath);
const command = new PutObjectCommand({
Bucket: 'my-app-bucket',
Key: key,
Body: fileContent,
ContentType: 'image/jpeg'
});
await s3Client.send(command);
console.log('Upload success:', key);
}
// 파일 다운로드
async function downloadFile(key, outputPath) {
const command = new GetObjectCommand({
Bucket: 'my-app-bucket',
Key: key
});
const response = await s3Client.send(command);
const stream = response.Body;
const writeStream = fs.createWriteStream(outputPath);
stream.pipe(writeStream);
}
// 사용
await uploadFile('./image.jpg', 'uploads/image.jpg');
await downloadFile('uploads/image.jpg', './downloaded.jpg');
S3 정적 웹사이트 호스팅
1. S3 버킷 → "속성" 탭
2. "정적 웹 사이트 호스팅" 편집
3. "활성화" 선택
4. 인덱스 문서: index.html
5. 오류 문서: error.html
6. "변경 사항 저장"
7. "권한" 탭 → "버킷 정책" 편집
버킷 정책 (퍼블릭 읽기 허용):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-app-bucket/*"
}
]
}
# 웹사이트 배포
aws s3 sync ./dist s3://my-app-bucket --delete
# 접속
# http://my-app-bucket.s3-website.ap-northeast-2.amazonaws.com
S3 복제·일관성 모델(개념과 실무)
분산 객체 스토어는 보통 “여러 노드에 복제하고, 그 사이에 짧은 지연이 있을 수 있다”는 이벤추얼 컨시스턴시(eventual consistency) 로 설명해 왔다. 면접·교재에서도 “S3는 eventual consistency”라고 말하는 경우가 있는데, 서비스는 시간이 지나며 강한 일관성 쪽으로 발전해 왔다. 최신 동작은 AWS 공식 문서의 객체 read-after-write 일관성 설명을 기준으로 삼는 것이 안전하다.
[과거에 문제가 되던 그림]
PUT 직후 GET → 아직 복제가 안 끝나 다른 노드에서 읽음 → "방금 올린 파일이 안 보임"
[현재 S3(리전 내 객체 작업)]
PUT/DELETE 후 같은 키에 대한 GET은 일관된 결과를 기대할 수 있음
(공식 문서 기준, 모든 리전에서 객체 작업에 대해 강한 read-after-write 일관성)
그럼에도 앱에서 “올렸는데 안 보인다”는 증상은 흔하다. 원인은 S3 “복제 지연”이 아니라 다음인 경우가 많다.
- CloudFront·브라우저 캐시: 정적 자산은 캐시 무효화(invalidation)나 버전 쿼리(
app.js?v=2)가 필요하다. - 크로스 리전 복제(CRR): 다른 리전으로의 복제는 비동기라, 재해 복구·글로벌 배포 설계 시 지연을 고려해야 한다.
- 클라이언트/프록시 캐시: API 응답이나 presigned URL을 중간에서 캐시하는 경우.
정리하면, S3 자체의 일관성 모델을 이해하고, CDN·복제·캐시 계층까지 포함해 “사용자에게 보이는 일관성”을 설계하는 것이 프로덕션 역량이다.
스토리지 클래스·비용·접근 패턴
S3는 객체를 한 번 올려두고, 접근 빈도·복구 허용 시간·내구성 요구에 따라 스토리지 클래스를 나눈다. “모든 객체를 Standard만 쓰면 비용이 새는” 경우가 많으므로, 접근 패턴을 먼저 정의하고 클래스를 고른다.
| 클래스 | 흔한 용도 | 접근·복구 특성(개념) |
|---|---|---|
| S3 Standard | 활성 데이터, CDN 원본 | 즉시 접근, 리전 내 고가용 |
| Standard-IA | 드물게 읽지만 즉시 필요 | Standard보다 저장 단가↓, 검색·GB당 검색 비용↑ |
| S3 Intelligent-Tiering | 패턴이 불규칙한 워크로드 | 자동으로 자주/드문 티어 이동(모니터링 비용 발생) |
| Glacier Instant Retrieval | 아카이브이지만 밀리초 단위 읽기 | IA와 유사한 지연, 장기 보관 |
| Glacier Flexible Retrieval | 백업·규제 보관 | 복구에 분~시간(검색 옵션) |
| S3 Glacier Deep Archive | 장기 아카이브(연 1~2회 접근) | 가장 저렴한 저장, 복구 시간 길 수 있음 |
실무 패턴 예시
- 업로드 원본 + 썸네일: 원본은
Standard, 90일 지난 원본은 Lifecycle으로Standard-IA또는Intelligent-Tiering으로 내린다. 썸네일은 트래픽이 많으면 Standard 유지. - 로그·감사 파일: 30일 Standard → 180일 Glacier Instant Retrieval → 7년 후 삭제 같은 단계 전환을 JSON으로 명시한다.
- 법적 보관(WORM 느낌): S3 Object Lock(거버넌스/컴플라이언스 모드)과 함께 Glacier 계열을 쓰는 경우가 있다. 잠금 모드는 삭제·덮어쓰기 정책에 영향을 준다.
수명 주기 정책 예시(여러 접두사)
{
"Rules": [
{
"Id": "uploads-tiering",
"Status": "Enabled",
"Filter": { "Prefix": "uploads/" },
"Transitions": [
{ "Days": 60, "StorageClass": "STANDARD_IA" },
{ "Days": 365, "StorageClass": "GLACIER_IR" }
],
"NoncurrentVersionTransitions": [
{ "NoncurrentDays": 30, "StorageClass": "GLACIER" }
]
},
{
"Id": "logs-expire",
"Status": "Enabled",
"Filter": { "Prefix": "logs/" },
"Expiration": { "Days": 90 }
}
]
}
- 버전 관리를 켠 버킷에서는
NoncurrentVersionTransitions로 오래된 버전만 저렴한 클래스로 보내 현재 버전은 빠른 클래스에 둘 수 있다. - 복제(CRR) 를 쓰는 경우 목적지 버킷에도 동일한 수명 주기를 두어 복제 스토리지 비용을 통제한다.
대량 객체의 스토리지 클래스 변경은 콘솔 S3 Batch Operations(매니페스트 CSV·S3 Inventory 기반)로 PUT Object 복사·StorageClass 지정, 또는 S3 Lifecycle으로 시간 기반 전환을 쓰는 경우가 많다. 수백만 객체를 한꺼번에 옮길 때는 요청 비용·복제 시간·다운스트림 캐시를 함께 계획한다.
개별 객체를 Intelligent-Tiering으로(예시)
aws s3 cp s3://my-app-bucket/reports/2026/q1.csv s3://my-app-bucket/reports/2026/q1.csv \
--storage-class INTELLIGENT_TIERING \
--metadata-directive REPLACE
cp로 같은 키에 덮어쓰기하면서 스토리지 클래스만 바꾸는 패턴이다. 대량일 때는 위와 같이 한 건씩이 아니라 Lifecycle 규칙 또는 Batch Operations가 운영에 맞다.
6. RDS - 관리형 데이터베이스
RDS란?
RDS (Relational Database Service)는 MySQL·PostgreSQL 등을 패치·백업까지 AWS가 관리하는 형태로 쓰는 서비스다.
직접 관리:
- DB 설치
- 백업 설정
- 보안 패치
- 모니터링
→ 복잡하고 시간 소모
RDS 사용:
- 클릭 몇 번으로 DB 생성
- 자동 백업
- 자동 패치
- 모니터링 내장
→ 간편하고 안정적
RDS 인스턴스 생성
1. RDS 콘솔 → "데이터베이스 생성"
2. 엔진 선택:
- PostgreSQL 15.4 (추천)
- MySQL 8.0
- MariaDB
3. 템플릿:
- 프리 티어 (무료)
4. 설정:
- DB 인스턴스 식별자: my-database
- 마스터 사용자 이름: admin
- 마스터 암호: [강력한 비밀번호]
5. 인스턴스 구성:
- db.t3.micro (무료 티어)
6. 스토리지:
- 20GB (무료 티어 최대)
7. 연결:
- VPC: 기본 VPC
- 퍼블릭 액세스: 예 (테스트용)
- 보안 그룹: 새로 생성
8. "데이터베이스 생성" 클릭
RDS 연결
보안 그룹 설정:
// 실행 예제
1. EC2 콘솔 → "보안 그룹"
2. RDS 보안 그룹 선택
3. "인바운드 규칙 편집"
4. PostgreSQL (5432) 허용
- 소스: 내 IP 또는 EC2 보안 그룹
Node.js 연결:
npm install pg
const { Pool } = require('pg');
const pool = new Pool({
host: 'my-database.xxxxx.ap-northeast-2.rds.amazonaws.com',
port: 5432,
user: 'admin',
password: 'your-password',
database: 'postgres',
ssl: {
rejectUnauthorized: false
}
});
// 쿼리 실행
async function getUsers() {
const result = await pool.query('SELECT * FROM users');
return result.rows;
}
// 사용
const users = await getUsers();
console.log(users);
RDS 백업 및 복원
자동 백업:
- 매일 자동 백업
- 보관 기간: 7일 (설정 가능)
- 특정 시점 복원 가능
수동 스냅샷:
1. RDS 콘솔 → 인스턴스 선택
2. "작업" → "스냅샷 생성"
3. 스냅샷 이름 입력
4. "스냅샷 생성" 클릭
복원:
1. "스냅샷" 메뉴
2. 스냅샷 선택 → "작업" → "스냅샷 복원"
3. 새 인스턴스로 복원됨
RDS Multi-AZ와 장애 조치(Failover)
Multi-AZ는 고가용성(HA) 용도다. 프라이머리 인스턴스와 다른 가용 영역의 스탠바이가 한 쌍을 이루고, 스토리지 층에서 동기 방식으로 복제되어 둘 중 하나가 죽어도 데이터 손실을 최소화하는 구성에 가깝다(엔진·버전에 따라 세부 구현은 문서 확인).
[정상]
애플리케이션 → DNS 엔드포인트(예: xxx.rds.amazonaws.com) → 프라이머리(AZ-a)
↓ 동기 복제
스탠바이(AZ-b) — 대기만 함(일반적으로 읽기 부하 분산 X)
[프라이머리 장애]
RDS가 감지 → 스탠바이 승격 → 같은 DNS 이름이 새 프라이머리를 가리키도록 전환
→ 앱은 연결 문자열을 바꾸지 않고 재접속·커넥션 풀 재설정으로 대응
알아둘 점
- Failover 소요 시간: 보통 수십 초~2분 안팎으로 잡고 설계한다(부하·장애 유형에 따라 달라짐).
- 읽기 확장이 목적이면 Multi-AZ만으로는 부족하다. 읽기 부하는 읽기 전용 복제본(Read Replica) 을 별도로 둔다.
- 애플리케이션은 짧은 연결 끊김을 견디도록(재시도, 커넥션 풀 타임아웃) 만드는 것이 안전하다.
DB 서브넷 그룹·보안 그룹·퍼블릭 액세스(설정 예시)
프로덕션 권장 형태는 “RDS는 프라이빗 서브넷 + 퍼블릭 액세스 아니오 + 애플리케이션 보안 그룹에서만 DB 포트 허용”이다. 콘솔에서 흔히 맞추는 값은 아래와 같다.
RDS 생성 마법사(요약)
- VPC: 운영용 VPC (예: vpc-0abc...)
- 서브넷 그룹: private-db-subnet-a (ap-northeast-2a), private-db-subnet-b (ap-northeast-2b)
- 퍼블릭 액세스: 아니오
- VPC 보안 그룹: sg-rds-prod → 인바운드 PostgreSQL 5432, 소스 sg-app-prod
- 가용 영역: 선호 AZ 지정 또는 “선호 없음”
DB 서브넷 그룹은 “이 RDS가 어느 서브넷들에 ENI를 붙일 수 있는지”를 정한다. Multi-AZ를 쓰면 보통 서로 다른 AZ의 프라이빗 서브넷을 두 개 이상 포함한다. 서브넷 그룹이 퍼블릭 서브넷만 가리키면 실수로 인터넷 노출 설계가 될 수 있으니, 서브넷 이름·라우트 테이블을 반드시 대조한다.
보안 그룹 규칙 예시(개념)
sg-app-prod (EC2/ECS)
아웃바운드: 5432 → sg-rds-prod (또는 VPC CIDR 내)
sg-rds-prod (RDS)
인바운드: 5432 ← sg-app-prod
인바운드: 5432 ← sg-bastion (점프 서버만 SSH 관리 시)
(관리용으로 내 IP 고정 허용은 최소화·임시)
파라미터 그룹·연결·읽기 복제본
DB 파라미터 그룹(PostgreSQL 예)에서는 max_connections, shared_buffers, work_mem, log_min_duration_statement 등을 환경에 맞게 조정한다. 변경 후 재부팅이 필요한 파라미터가 있으니 유지보수 창을 잡는다.
# 의미만 빠르게 볼 때 (실제 값은 인스턴스 메모리·동시 접속에 따라 산정)
shared_buffers ≈ 메모리의 25% 내외(권장 범위는 엔진 문서 확인)
max_connections 는 앱 서버 풀 합산보다 넉넉히, 너무 크면 메모리 압박
읽기 전용 복제본(Read Replica) 을 만들면 보고·배치·읽기 비중 높은 API를 분리할 수 있다. 애플리케이션에서는 쓰기는 프라이머리 엔드포인트, 읽기는 리플리카 엔드포인트로 분리한다.
// Node(pg) 예: 쓰기/읽기 풀 분리 개념
import { Pool } from 'pg';
const writer = new Pool({
host: process.env.RDS_WRITER_HOST,
user: process.env.RDS_USER,
password: process.env.RDS_PASSWORD,
database: process.env.RDS_DB,
max: 20,
ssl: { rejectUnauthorized: true }
});
const reader = new Pool({
host: process.env.RDS_READER_HOST, // 읽기 복제본 엔드포인트
user: process.env.RDS_USER,
password: process.env.RDS_PASSWORD,
database: process.env.RDS_DB,
max: 50,
ssl: { rejectUnauthorized: true }
});
export async function createUser(name) {
return writer.query('INSERT INTO users (name) VALUES ($1) RETURNING *', [name]);
}
export async function listUsers() {
return reader.query('SELECT id, name FROM users ORDER BY id DESC LIMIT 100');
}
복제 지연이 있으므로 “쓰기 직후 같은 세션에서 반드시 읽기” 같은 요구는 프라이머리로 읽기하거나 세션 스티키 전략을 쓴다. 리플리카는 고가용성 Failover용이 아니라 읽기 확장용으로 이해하는 것이 안전하다(Multi-AZ와 역할이 다름).
CloudWatch 알람·Performance Insights(운영 예)
알람 예:
- DatabaseConnections > (max_connections * 0.8) → 스케일 업 또는 풀 조정
- FreeStorageSpace < 임계값 → 스토리지 자동 확장·정리
- ReplicaLag > 수 초~분 단위(서비스 SLO에 맞게) → 복제 지연 조사
RDS Performance Insights를 켜 두면 vCPU·대기 이벤트·SQL별 부하를 시각화해 느린 쿼리·락을 빠르게 좁힐 수 있다.
7. Lambda - 서버리스
Lambda란?
Lambda는 서버를 직접 띄우지 않고 이벤트에 맞춰 코드만 실행하는 서비스다.
전통적인 방식:
- EC2 인스턴스 24시간 실행
- 요청 없어도 비용 발생
- 서버 관리 필요
Lambda:
- 요청이 올 때만 실행
- 실행 시간만큼만 과금
- 서버 관리 불필요
Lambda 함수 생성
1. Lambda 콘솔 → "함수 생성"
2. "새로 작성" 선택
3. 함수 이름: hello-world
4. 런타임: Node.js 18.x
5. "함수 생성" 클릭
코드 작성:
export const handler = async (event) => {
const name = event.queryStringParameters?.name || 'World';
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: `Hello, ${name}!`
})
};
};
API Gateway 연동
1. Lambda 함수 → "트리거 추가"
2. "API Gateway" 선택
3. "HTTP API" 생성
4. 보안: 열기
5. "추가" 클릭
API 엔드포인트 생성됨:
https://xxxxx.execute-api.ap-northeast-2.amazonaws.com/default/hello-world
테스트:
curl "https://xxxxx.execute-api.ap-northeast-2.amazonaws.com/default/hello-world?name=Alice"
# {"message":"Hello, Alice!"}
Lambda 실전 예제: 이미지 리사이징
import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
import sharp from 'sharp';
const s3Client = new S3Client({ region: 'ap-northeast-2' });
export const handler = async (event) => {
// S3 이벤트에서 파일 정보 추출
const bucket = event.Records[0].s3.bucket.name;
const key = event.Records[0].s3.object.key;
// 원본 이미지 다운로드
const getCommand = new GetObjectCommand({ Bucket: bucket, Key: key });
const { Body } = await s3Client.send(getCommand);
// 이미지 리사이징
const resized = await sharp(Body)
.resize(800, 600, { fit: 'inside' })
.jpeg({ quality: 80 })
.toBuffer();
// 리사이징된 이미지 업로드
const putCommand = new PutObjectCommand({
Bucket: bucket,
Key: `resized/${key}`,
Body: resized,
ContentType: 'image/jpeg'
});
await s3Client.send(putCommand);
return { statusCode: 200, body: 'Success' };
};
8. CloudFront - CDN
CloudFront란?
CloudFront는 AWS의 CDN으로, 엣지에 캐시해 지연을 줄인다.
CDN 없이:
사용자 (한국) → 서버 (미국)
- 거리: 10,000km
- 응답 시간: 500ms
CDN 사용:
사용자 (한국) → CDN 엣지 (서울) → 서버 (미국)
- 거리: 10km (캐시된 경우)
- 응답 시간: 10ms (50배 빠름!)
CloudFront 배포 생성
1. CloudFront 콘솔 → "배포 생성"
2. 원본 도메인:
- S3 버킷 선택: my-app-bucket.s3.amazonaws.com
3. 원본 액세스:
- OAI (Origin Access Identity) 생성
- S3 버킷 정책 자동 업데이트
4. 뷰어 프로토콜 정책:
- Redirect HTTP to HTTPS
5. 캐시 정책:
- CachingOptimized
6. "배포 생성" 클릭
배포 도메인:
https://d123456.cloudfront.net
커스텀 도메인 연결
1. Route 53에서 도메인 구매 또는 등록
2. CloudFront 배포 → "일반" 탭
3. "편집" → "대체 도메인 이름" 추가
- cdn.example.com
4. SSL 인증서 요청 (ACM)
5. Route 53에서 CNAME 레코드 추가
- cdn.example.com → d123456.cloudfront.net
9. 실전 아키텍처와 프로덕션 패턴
3-Tier 아키텍처
┌──────────────────────────────────────────┐
│ CloudFront (CDN) │
│ 정적 파일 (이미지, CSS, JS) │
└────────────────┬─────────────────────────┘
│
┌────────────────▼─────────────────────────┐
│ Application Load Balancer │
│ (트래픽 분산) │
└────┬─────────────────────┬────────────────┘
│ │
┌────▼────┐ ┌─────▼────┐
│ EC2 1 │ │ EC2 2 │ ← Auto Scaling
│ (Web) │ │ (Web) │
└────┬────┘ └─────┬────┘
│ │
└──────────┬───────────┘
│
┌──────▼──────┐
│ RDS (DB) │
│ Multi-AZ │
└─────────────┘
비용 최적화 아키텍처
┌──────────────────────────────────────────┐
│ S3 + CloudFront │
│ 정적 웹사이트 호스팅 │
│ (매우 저렴, 고성능) │
└────────────────┬─────────────────────────┘
│
│ API 요청만
│
┌───────▼────────┐
│ Lambda + API │
│ Gateway │
│ (서버리스) │
└───────┬────────┘
│
┌───────▼────────┐
│ DynamoDB │
│ (NoSQL) │
└────────────────┘
월 비용: $5~$10 (트래픽 적을 때)
프로덕션에서 반복되는 운영 패턴
아키텍처 그림만 그리는 것과, 장애·보안·배포까지 포함해 운영 가능한지는 다른 문제다. EC2·S3·RDS를 쓸 때 자주 등장하는 패턴을 압축해 정리한다.
| 패턴 | 요지 | 관련 서비스 예 |
|---|---|---|
| 최소 권한 | 사람·애플리케이션 IAM 역할에 필요한 API만 | IAM, STS |
| 비밀 분리 | DB 비밀번호를 코드에 넣지 않음 | Secrets Manager, Parameter Store |
| 네트워크 분리 | 웹은 퍼블릭, DB는 프라이빗 서브넷 | VPC, 서브넷, 보안 그룹 |
| 헬스 체크 + 자동 복구 | 불량 인스턴스는 교체 | ALB/NLB, Auto Scaling, RDS Multi-AZ |
| 관측 가능성 | 로그·지표·추적으로 원인 추적 | CloudWatch, X-Ray(선택) |
| 배포 안전장치 | 한 번에 전부 갈아끼우지 않음 | CodeDeploy 블루/그린, 카나리(조직에 따라) |
S3·CloudFront를 쓸 때: 버킷은 가능하면 비공개로 두고, CloudFront OAC(Origin Access Control) 로 원본 접근만 허용하는 식이 일반적이다. 퍼블릭 GetObject 정책은 정말 정적 호스팅만 할 때로 한정하는 것이 좋다.
RDS를 쓸 때: 프로덕션에서는 퍼블릭 액세스 끄기, 애플리케이션은 같은 VPC의 프라이빗 IP/엔드포인트로만 붙인다. 백업 보관 기간·스냅샷은 복구 목표 시간(RTO)·복구 시점 목표(RPO) 와 맞춰 설정한다.
EC2를 쓸 때: 단일 인스턴스는 장애 시 다운타임이 크므로, 트래픽이 생기면 로드 밸런서 뒤에 다중 AZ로 옮기는 로드맵을 잡는다. 그때 Nitro 세대 인스턴스의 네트워크 대역이 병목인지, 애플리케이션인지 지표로 구분한다.
프로덕션에서 자주 쓰는 추가 패턴
1) 경계 방어: ALB 앞에 AWS WAF(SQLi/XSS 규칙, 레이트 리밋), 필요 시 Shield Advanced 검토. CloudFront를 쓰면 엣지에서 지리적 제한·봇 완화를 함께 구성하기 쉽다.
2) 비밀·설정 회전: RDS 자격 증명은 Secrets Manager에 두고 Lambda 회전 또는 앱 시작 시 주입. 일반 설정은 Parameter Store(SSM) /prod/app/LOG_LEVEL 형태로 버전 관리.
3) 백업 계층: RDS 자동 백업 + 수동 스냅샷(릴리즈 전)·AWS Backup 볼트로 교차 리전 복사(규정 대응). S3는 버전 관리 + Lifecycle + 중요 버킷은 복제 또는 S3 Batch Replication 검토.
4) 관측·감사: CloudWatch 알람 + CloudTrail(API 감사), 데이터 이벤트는 S3/Data Events(비용 유의)로 추적. 애플리케이션은 구조화 로그(JSON) 를 남겨 검색 비용을 줄인다.
5) 배포 안전: EC2는 CodeDeploy 블루/그린 또는 롤링 + 대상 그룹 교체, 컨테이너면 ECS/EKS 롤아웃 전략. DB 스키마는 호환되는 순서로 마이그레이션(expand-contract)하여 롤백 가능성을 남긴다.
6) 비용·성능: Compute Savings Plans로 안정 워크로드 할인, S3는 스토리지 클래스 분리, RDS는 예약 인스턴스와 스토리지 자동 확장 상한선을 함께 설정한다.
7) 재해 복구 연습: 분기별로 스냅샷 복원 → 앱 연결 확인 시나리오를 문서화한다. “백업은 있는데 복구를 안 해 본” 상태가 가장 위험하다.
참조 아키텍처(텍스트 다이어그램)
Internet
│
▼
CloudFront (정적) ──► S3 (OAC, 비공개 버킷)
│
▼
WAF ─► ALB (다중 AZ)
│
├─► ASG: EC2/ECS (프라이빗 앱 서브넷, NAT로 아웃바운드)
│
└─► RDS Primary (프라이빗 DB 서브넷, Multi-AZ)
└── Read Replica (리포팅, 별도 엔드포인트)
10. 보안 모범 사례
IAM 권한 관리
최소 권한 원칙:
// ❌ 너무 많은 권한
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
// ✅ 필요한 권한만
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-app-bucket/*"
}
보안 그룹 설정
❌ 나쁜 예:
- SSH (22): 0.0.0.0/0 (전 세계 허용)
- 해킹 위험!
✅ 좋은 예:
- SSH (22): 내 IP만 허용
- HTTP (80): 0.0.0.0/0 (웹은 공개)
- HTTPS (443): 0.0.0.0/0
비밀 정보 관리
AWS Secrets Manager:
# 비밀 정보 저장
aws secretsmanager create-secret \
--name myapp/database \
--secret-string '{"username":"admin","password":"secret123"}'
# 비밀 정보 조회
aws secretsmanager get-secret-value --secret-id myapp/database
// Node.js에서 사용
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';
const client = new SecretsManagerClient({ region: 'ap-northeast-2' });
async function getSecret(secretName) {
const command = new GetSecretValueCommand({ SecretId: secretName });
const response = await client.send(command);
return JSON.parse(response.SecretString);
}
const dbCreds = await getSecret('myapp/database');
console.log(dbCreds.username, dbCreds.password);
11. 비용 관리
무료 티어 모니터링
1. Billing 콘솔 → "무료 티어"
2. 사용량 확인
3. 알림 설정:
- "결제 알림" 활성화
- CloudWatch 알람 생성
- 예산: $10
비용 절감 팁
1) EC2 인스턴스 중지
# 사용하지 않을 때 중지 (스토리지 비용만 발생)
aws ec2 stop-instances --instance-ids i-xxxxx
# 재시작
aws ec2 start-instances --instance-ids i-xxxxx
2) S3 수명 주기 정책
// 실행 예제
{
"Rules": [
{
"Id": "DeleteOldLogs",
"Status": "Enabled",
"Prefix": "logs/",
"Expiration": {
"Days": 30
}
},
{
"Id": "ArchiveOldData",
"Status": "Enabled",
"Prefix": "archive/",
"Transitions": [
{
"Days": 90,
"StorageClass": "GLACIER"
}
]
}
]
}
3) RDS 예약 인스턴스
장기 사용 시 예약 인스턴스 구매:
- 1년 약정: 40% 할인
- 3년 약정: 60% 할인
12. 모니터링
CloudWatch
로그 확인:
# CloudWatch Logs에 로그 전송
aws logs put-log-events \
--log-group-name /aws/lambda/my-function \
--log-stream-name 2026/03/31 \
--log-events timestamp=1616239022000,message="Hello World"
알람 설정:
1. CloudWatch 콘솔 → "알람"
2. "알람 생성"
3. 지표 선택:
- EC2 > CPU 사용률
4. 조건:
- CPU > 80% (5분 동안)
5. 알림:
- SNS 주제 생성
- 이메일 주소 입력
6. "알람 생성"
13. CI/CD 파이프라인
GitHub Actions + AWS
.github/workflows/deploy.yml
name: Deploy to AWS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to S3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
aws s3 sync ./dist s3://my-app-bucket --delete
- name: Invalidate CloudFront
run: |
aws cloudfront create-invalidation \
--distribution-id E123456 \
--paths "/*"
14. 실전 프로젝트: 풀스택 앱 배포
아키텍처
┌─────────────────────────────────────────┐
│ CloudFront + S3 (React 프론트엔드) │
└────────────────┬────────────────────────┘
│
┌───────▼────────┐
│ API Gateway │
│ + Lambda │
│ (백엔드) │
└───────┬────────┘
│
┌───────▼────────┐
│ RDS │
│ (PostgreSQL) │
└────────────────┘
1단계: 프론트엔드 배포 (S3 + CloudFront)
# React 앱 빌드
npm run build
# S3 업로드
aws s3 sync ./build s3://my-app-frontend
# CloudFront 배포 생성 (위에서 설명)
2단계: 백엔드 배포 (Lambda)
handler.js
import { Pool } from 'pg';
const pool = new Pool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
});
export const handler = async (event) => {
const { httpMethod, path } = event;
// GET /api/users
if (httpMethod === 'GET' && path === '/api/users') {
const result = await pool.query('SELECT * FROM users');
return {
statusCode: 200,
body: JSON.stringify(result.rows)
};
}
// POST /api/users
if (httpMethod === 'POST' && path === '/api/users') {
const { name, email } = JSON.parse(event.body);
const result = await pool.query(
'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *',
[name, email]
);
return {
statusCode: 201,
body: JSON.stringify(result.rows[0])
};
}
return {
statusCode: 404,
body: JSON.stringify({ error: 'Not Found' })
};
};
3단계: 데이터베이스 설정 (RDS)
-- RDS PostgreSQL 접속 후
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO users (name, email) VALUES
('Alice', '[email protected]'),
('Bob', '[email protected]');
15. 트러블슈팅
자주 발생하는 문제
1) EC2 SSH 접속 안됨
# 원인: 키 파일 권한 문제
# 해결:
chmod 400 my-key.pem
# 원인: 보안 그룹 설정
# 해결: 보안 그룹에 SSH (22) 포트 열기
2) S3 파일 접근 안됨
원인: 버킷 정책 또는 퍼블릭 액세스 차단
해결:
1. "퍼블릭 액세스 차단" 설정 확인
2. 버킷 정책에 s3:GetObject 권한 추가
3) RDS 연결 안됨
// 실행 예제
원인: 보안 그룹 또는 네트워크 설정
해결:
1. 보안 그룹에 PostgreSQL (5432) 포트 열기
2. 퍼블릭 액세스 활성화 (테스트용)
3. VPC 설정 확인
FAQ
Q1. AWS 무료 티어는 정말 무료인가? 한도 안에서 쓰면 과금이 없는 항목이 있다. 다만 초과·리전·12개월 경과 후 요금이 붙을 수 있으니 청구 알림을 켜 두는 게 안전하다. Q2. EC2 vs Lambda 어떤 것을 선택해야 하나요?
// 실행 예제
EC2 선택:
- 24시간 실행 필요
- 복잡한 애플리케이션
- 상태 유지 필요
Lambda 선택:
- 간헐적 실행
- 짧은 실행 시간 (<15분)
- 서버 관리 싫음
Q3. 비용이 얼마나 나올까요?
소규모 웹 앱 (월 예상 비용):
- EC2 t2.micro: 무료 (12개월)
- S3 (5GB): 무료
- RDS t3.micro: 무료 (12개월)
- CloudFront (10GB): $1
- 총: $1~$5
중규모 서비스:
- EC2 t3.medium: $30
- S3 (100GB): $2
- RDS t3.small: $25
- CloudFront (1TB): $85
- 총: $150~$200
요약
핵심 정리
VPC:
- 계정 전용 네트워크, 서브넷·라우팅·IGW/NAT로 흐름 제어
- 보안 그룹(인스턴스)과 NACL(서브넷)의 역할 분담 EC2:
- 가상 서버, 최신 세대는 Nitro로 네트워크·스토리지 일부를 하드웨어 오프로드
- 완전한 제어와 함께 패치·스케일링은 직접 설계 S3:
- 객체 저장소, 리전 내 객체 작업은 강한 read-after-write 일관성(공식 문서 기준)
- CDN·CRR·캐시는 별도로 “보이는 일관성”을 설계 RDS:
- 관리형 DB, Multi-AZ는 동기 복제 기반 장애 조치(읽기 확장은 읽기 복제본)
- 자동 백업·스냅샷으로 RPO/RTO 협의 Lambda:
- 서버리스 함수
- 사용한 만큼만 과금
- 자동 스케일링
AWS 학습 로드맵
계정·IAM·EC2로 SSH까지 연 다음, S3·RDS로 데이터 경로를 만든다. 그다음 VPC·로드밸런서·CloudFront로 네트워크를 넓히고, 자동 확장·CI/CD·관측은 서비스가 커질 때 붙이면 된다.
다음 글 추천
키워드: AWS, Cloud, EC2, S3, RDS, Lambda, CloudFront, 클라우드, 아마존, 서버리스, IAM
심화 부록: 구현·운영 관점
이 부록은 앞선 본문에서 다룬 주제(「AWS 입문 가이드 | EC2, S3, RDS 실전 사용법」)를 구현·런타임·운영 관점에서 다시 압축합니다. 도메인별 세부 구현은 글마다 다르지만, 입력 검증 → 핵심 연산 → 부작용(I/O·네트워크·동시성) → 관측의 흐름으로 장애를 나누면 원인 추적이 빨라집니다.
내부 동작과 핵심 메커니즘
flowchart TD A[입력·요청·이벤트] --> B[파싱·검증·디코딩] B --> C[핵심 연산·상태 전이] C --> D[부작용: I/O·네트워크·동시성] D --> E[결과·관측·저장]
sequenceDiagram participant C as 클라이언트/호출자 participant B as 경계(런타임·게이트웨이·프로세스) participant D as 의존성(API·DB·큐·파일) C->>B: 요청/이벤트 B->>D: 조회·쓰기·RPC D-->>B: 지연·부분 실패·재시도 가능 B-->>C: 응답 또는 오류(코드·상관 ID)
- 불변 조건(Invariant): 버퍼 경계, 프로토콜 상태, 트랜잭션 격리, FD 상한 등 단계별로 문장으로 적어 두면 디버깅 비용이 줄어듭니다.
- 결정성: 순수 층과 시간·네트워크·스케줄에 의존하는 층을 분리해야 테스트와 장애 분석이 쉬워집니다.
- 경계 비용: 직렬화, 인코딩, syscall 횟수, 락 경합, 할당·GC, 캐시 미스를 의심 목록에 둡니다.
- 백프레셔: 생산자가 소비자보다 빠를 때 버퍼·큐·스트림에서 속도를 줄이는 신호를 어디에 둘지 정의합니다.
프로덕션 운영 패턴
| 영역 | 운영 관점 질문 |
|---|---|
| 관측성 | 요청 단위 상관 ID, 에러율·지연 p95/p99, 의존성 타임아웃·재시도가 대시보드에 보이는가 |
| 안전성 | 입력 검증·권한·비밀·감사 로그가 코드 경로마다 일관적인가 |
| 신뢰성 | 재시도는 멱등 연산에만 적용되는가, 서킷 브레이커·백오프·DLQ가 있는가 |
| 성능 | 캐시·배치 크기·커넥션 풀·인덱스·백프레셔가 데이터 규모에 맞는가 |
| 배포 | 롤백 룬북, 카나리/블루그린, 마이그레이션·피처 플래그가 문서화되어 있는가 |
| 용량 | 피크 트래픽·디스크·FD·스레드 풀 상한을 주기적으로 검증하는가 |
스테이징은 데이터 양·네트워크 RTT·동시성을 프로덕션에 가깝게 맞출수록 재현율이 올라갑니다.
확장 예시: 엔드투엔드 미니 시나리오
앞선 본문 주제(「AWS 입문 가이드 | EC2, S3, RDS 실전 사용법」)를 배포·운영 흐름에 맞춰 옮긴 체크리스트입니다. 도메인에 맞게 단계 이름만 바꿔 적용할 수 있습니다.
- 입력 계약 고정: 스키마·버전·최대 페이로드·타임아웃·에러 코드를 경계에 둔다.
- 핵심 경로 계측: 요청 ID, 단계별 지연, 외부 호출 결과 코드를 로그·메트릭·트레이스에서 한 흐름으로 본다.
- 실패 주입: 의존성 타임아웃·5xx·부분 데이터·락 대기를 스테이징에서 재현한다.
- 호환·롤백: 설정/마이그레이션/클라이언트 버전을 되돌릴 수 있는지 확인한다.
- 부하 후 검증: 피크 대비 p95/p99, 에러율, 리소스 상한, 알림 임계값을 점검한다.
handle(request):
ctx = newCorrelationId()
validated = validateSchema(request)
authorize(validated, ctx)
result = domainCore(validated)
persistOrEmit(result, idempotentKey)
recordMetrics(ctx, latency, outcome)
return result
문제 해결(Troubleshooting)
| 증상 | 가능 원인 | 조치 |
|---|---|---|
| 간헐적 실패 | 레이스, 타임아웃, 외부 의존성, DNS | 최소 재현 스크립트, 분산 트레이스·로그 상관관계, 재시도·서킷 설정 점검 |
| 성능 저하 | N+1, 동기 I/O, 락 경합, 과도한 직렬화, 캐시 미스 | 프로파일러·APM으로 핫스팟 확인 후 한 가지씩 제거 |
| 메모리 증가 | 캐시 무제한, 구독/리스너 누수, 대용량 버퍼, 커넥션 미반납 | 상한·TTL·힙/FD 스냅샷 비교 |
| 빌드·배포만 실패 | 환경 변수, 권한, 플랫폼 차이, lockfile | CI 로그와 로컬 diff, 런타임·이미지 버전 핀 |
| 설정 불일치 | 프로필·시크릿·기본값, 리전 | 스키마 검증된 설정 단일 소스와 배포 매트릭스 표준화 |
| 데이터 불일치 | 비멱등 재시도, 부분 쓰기, 캐시 무효화 누락 | 멱등 키·아웃박스·트랜잭션 경계 재검토 |
권장 순서: (1) 최소 재현 (2) 최근 변경 범위 축소 (3) 환경·의존성 차이 (4) 관측으로 가설 검증 (5) 수정 후 회귀·부하 테스트.
배포 전에는 git add → git commit → git push 후 npm run deploy 순서를 권장합니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- [2026] 클라우드 컴퓨팅 기초 — 가상화·VPC·스토리지·프로덕션 패턴까지
- Nitro 완벽 가이드 | 유니버설 서버 엔진·라우팅·캐시·Edge·실전 API
- [2026] PostgreSQL 완전 가이드 — MVCC·VACUUM·플래너·인덱스·프로덕션 운영
이 글에서 다루는 키워드 (관련 검색어)
AWS, Cloud, EC2, S3, RDS, Lambda, CloudFront, IAM, 클라우드, 아마존 등으로 검색하시면 이 글이 도움이 됩니다.