원래 작성하신 내용을 하나도 빠뜨리지 않고, 티스토리 마크다운 모드에서 표와 레이아웃이 깨지지 않도록 가공했습니다.
📋 주차 목표
6주차에 구축한 VPC/EC2 기반 인프라 위에 관리형 데이터베이스(RDS), 객체 스토리지(S3), 로드밸런서(ALB)를 추가하여 맘편한 이동 인프라를 완성합니다. 지도교수 피드백("HTTPS 통신 보안을 살펴볼 필요가 있다")을 반영하여 도메인 구매, ACM 인증서 발급, HTTPS 리스너 구성까지 진행합니다. 보안 그룹 체인(ALB → EC2 → RDS)을 설계하여 각 계층의 접근을 최소화하고, Elastic IP를 할당하여 EC2의 고정 IP를 확보합니다.
✅ 완료한 작업
1. 보안 그룹 체인 설계 및 구성
6주차에는 EC2 보안 그룹만 사용했으나, ALB와 RDS 도입에 맞춰 3단계 보안 그룹 체인을 설계했습니다.
AWS 콘솔 경로: VPC → 보안 그룹 → 보안 그룹 생성
ALB 보안 그룹 (comfortablemove-alb-sg)
| 방향 | 프로토콜 | 포트 | 소스/대상 | 용도 |
|---|---|---|---|---|
| 인바운드 | TCP | 80 | 0.0.0.0/0 | HTTP (HTTPS 리다이렉트용) |
| 인바운드 | TCP | 443 | 0.0.0.0/0 | HTTPS |
| 아웃바운드 | 전체 | 전체 | 0.0.0.0/0 | 헬스체크 등 |
EC2 보안 그룹 (comfortablemove-ec2-sg) - 6주차 대비 변경
| 방향 | 프로토콜 | 포트 | 소스/대상 | 용도 | 변경사항 |
|---|---|---|---|---|---|
| 인바운드 | TCP | 22 | 내 IP/32 | SSH 접속 | 유지 |
| 인바운드 | TCP | 8000 | ALB SG | API 접근 | 변경: 내 IP → ALB SG |
| 아웃바운드 | 전체 | 전체 | 0.0.0.0/0 | 인터넷 | 유지 |
RDS 보안 그룹 (comfortablemove-rds-sg)
| 방향 | 프로토콜 | 포트 | 소스/대상 | 용도 |
|---|---|---|---|---|
| 인바운드 | TCP | 5432 | EC2 SG | PostgreSQL 접근 |
| 아웃바운드 | 전체 | 전체 | 0.0.0.0/0 | - |
보안 그룹 체인 구조:
인터넷 → ALB SG (80, 443) → EC2 SG (8000) → RDS SG (5432)
이 구조에서 RDS는 EC2에서만, EC2의 API 포트는 ALB에서만 접근 가능합니다. 외부에서 RDS나 EC2 API에 직접 접근하는 것은 불가능합니다.
2. RDS PostgreSQL 인스턴스 생성
Docker 컨테이너 내부 PostgreSQL을 AWS 관리형 서비스인 RDS로 전환했습니다.
AWS 콘솔 경로: RDS → 데이터베이스 생성
2-1. DB 서브넷 그룹 생성
RDS를 프라이빗 서브넷에 배치하기 위해 서브넷 그룹을 먼저 생성했습니다.
콘솔 경로: RDS → 서브넷 그룹 → DB 서브넷 그룹 생성
| 항목 | 값 |
|---|---|
| 이름 | comfortablemove-db-subnet |
| VPC | comfortablemove-vpc |
| 가용영역 | ap-northeast-2a, ap-northeast-2c |
| 서브넷 | 프라이빗 A (10.0.11.0/24), 프라이빗 C (10.0.12.0/24) |
2-2. 파라미터 그룹 생성
SQL 로깅을 활성화하기 위해 커스텀 파라미터 그룹을 생성했습니다.
콘솔 경로: RDS → 파라미터 그룹 → 파라미터 그룹 생성
| 파라미터 | 값 | 용도 |
|---|---|---|
| log_statement | all | 모든 SQL 쿼리 로깅 |
| log_min_duration_statement | 1000 | 1초 이상 슬로우 쿼리 로깅 |
2-3. RDS 인스턴스 생성
| 항목 | 값 | 비고 |
|---|---|---|
| 엔진 | PostgreSQL 15 | 백엔드와 동일 버전 |
| 인스턴스 식별자 | comfortablemove-db | - |
| 인스턴스 클래스 | db.t3.micro | 프리티어 (750시간/월) |
| 스토리지 | 20GB gp3 | 최대 30GB 자동 확장 |
| 스토리지 암호화 | 활성화 | AWS 관리형 키 사용 |
| 마스터 사용자 | cmadmin | - |
| DB 이름 | comfortablemove | - |
| Multi-AZ | 비활성화 | 프리티어는 Single-AZ만 무료 |
| 서브넷 그룹 | comfortablemove-db-subnet | 프라이빗 서브넷 |
| 보안 그룹 | comfortablemove-rds-sg | EC2에서만 접근 |
| 자동 백업 | 7일 보존 | 매일 자동 스냅샷 |
| 파라미터 그룹 | comfortablemove-pg15-params | SQL 로깅 활성화 |
RDS 보안 포인트:
- 프라이빗 서브넷 배치 → 인터넷에서 직접 접근 불가
- 보안 그룹으로 EC2에서만 5432 포트 접근 허용
- 스토리지 암호화 활성화
- 퍼블릭 액세스: 비활성화
3. S3 버킷 생성
정적 파일(이미지, 문서 등) 저장을 위한 S3 버킷을 생성했습니다.
AWS 콘솔 경로: S3 → 버킷 만들기
| 항목 | 값 |
|---|---|
| 버킷 이름 | comfortablemove-assets |
| 리전 | ap-northeast-2 (서울) |
| 버전 관리 | 활성화 |
| 기본 암호화 | AES-256 (SSE-S3) |
퍼블릭 액세스 차단 설정:
- 모든 퍼블릭 액세스 차단: ✅ 활성화
- 새 퍼블릭 ACL 차단: ✅
- 새 퍼블릭 버킷 정책 차단: ✅
- 기존 퍼블릭 ACL 무시: ✅
- 기존 퍼블릭 버킷 정책 제한: ✅
CORS 설정:
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "PUT", "POST"],
"AllowedOrigins": ["*"],
"MaxAgeSeconds": 3600
}
]
EC2에서 S3 접근을 위한 IAM 역할:
EC2에 IAM 인스턴스 프로파일을 연결하여 Access Key 없이 S3에 접근할 수 있도록 설정했습니다.
콘솔 경로: IAM → 역할 → 역할 만들기
| 항목 | 값 |
|---|---|
| 역할 이름 | comfortablemove-ec2-role |
| 신뢰 대상 | EC2 서비스 |
| 허용 액션 | s3:GetObject, s3:PutObject, s3:ListBucket |
| 리소스 제한 | comfortablemove-assets 버킷만 |
4. Application Load Balancer 구성
EC2를 직접 노출하지 않고 ALB를 통해 트래픽을 전달하도록 구성했습니다.
AWS 콘솔 경로: EC2 → 로드 밸런서 → 로드 밸런서 생성 → Application Load Balancer
4-1. 타겟 그룹 생성
콘솔 경로: EC2 → 대상 그룹 → 대상 그룹 생성
| 항목 | 값 |
|---|---|
| 이름 | comfortablemove-tg |
| 프로토콜 | HTTP |
| 포트 | 8000 |
| VPC | comfortablemove-vpc |
| 대상 | EC2 인스턴스 등록 |
헬스체크 설정:
| 항목 | 값 |
| :--- | :--- |
| 경로 | /api/v1/health |
| 프로토콜 | HTTP |
| 포트 | 8000 |
| 정상 임계값 | 연속 2회 성공 |
| 비정상 임계값 | 연속 3회 실패 |
| 타임아웃 | 5초 |
| 간격 | 30초 |
| 성공 코드 | 200 |
4-2. ALB 생성
| 항목 | 값 |
|---|---|
| 이름 | comfortablemove-alb |
| 스키마 | 인터넷 경계 (Internet-facing) |
| IP 주소 유형 | IPv4 |
| VPC | comfortablemove-vpc |
| 서브넷 | 퍼블릭 A + 퍼블릭 C (2개 AZ 필수) |
| 보안 그룹 | comfortablemove-alb-sg |
4-3. 리스너 구성
| 리스너 포트 | 동작 |
|---|---|
| HTTPS 443 | 타겟 그룹으로 포워딩 |
| HTTP 80 | HTTPS(443)로 301 리다이렉트 |
ALB DNS: comfortablemove-alb-252716626.ap-northeast-2.elb.amazonaws.com
5. Elastic IP 할당
EC2 인스턴스의 퍼블릭 IP가 재시작 시 변경되는 문제를 해결하기 위해 Elastic IP를 할당했습니다.
AWS 콘솔 경로: EC2 → 탄력적 IP → 탄력적 IP 주소 할당
| 항목 | 값 |
|---|---|
| Elastic IP | 3.37.165.32 |
| 연결 대상 | comfortablemove-server EC2 인스턴스 |
| 비용 | 실행 중 인스턴스 연결 시 무료 |
참고: Elastic IP는 실행 중인 인스턴스에 연결되어 있으면 무료이지만, 인스턴스를 중지하면 시간당 $0.005가 과금됩니다.
6. HTTPS 통신 보안 구성 (지도교수 피드백 반영)
지도교수 피드백 "HTTPS 통신 보안을 살펴볼 필요가 있다"를 반영하여, 도메인 구매부터 SSL 인증서 적용까지 전체 HTTPS 구성을 완료했습니다.
6-1. 도메인 구매comfortablemove.com 도메인을 구매했습니다.
6-2. Route53 호스팅 영역 생성
콘솔 경로: Route53 → 호스팅 영역 → 호스팅 영역 생성
| 항목 | 값 |
| :--- | :--- |
| 도메인 | comfortablemove.com |
| 유형 | 퍼블릭 호스팅 영역 |
생성 후 네임서버(NS) 4개를 도메인 등록기관에 입력하여 DNS를 위임했습니다.
6-3. ACM SSL 인증서 발급
콘솔 경로: Certificate Manager → 인증서 요청
| 항목 | 값 |
| :--- | :--- |
| 인증서 유형 | 퍼블릭 |
| 도메인 | comfortablemove.com |
| 추가 이름 | *.comfortablemove.com (와일드카드) |
| 검증 방법 | DNS 검증 |
| 비용 | 무료 (ACM 퍼블릭 인증서) |
6-4. ALB에 HTTPS 리스너 추가
콘솔 경로: EC2 → 로드 밸런서 → comfortablemove-alb → 리스너 추가
| 설정값 | 내용 |
| :--- | :--- |
| 프로토콜 | HTTPS |
| 포트 | 443 |
| SSL 정책 | ELBSecurityPolicy-TLS13-1-2-2021-06 |
| 인증서 | ACM에서 발급한 comfortablemove.com 인증서 |
| 기본 액션 | 타겟 그룹으로 포워딩 |
6-5. Route53 A 레코드 생성 (도메인 → ALB)
콘솔 경로: Route53 → comfortablemove.com → 레코드 생성
| 항목 | 값 |
| :--- | :--- |
| 레코드 이름 | comfortablemove.com |
| 유형 | A (별칭) |
| 별칭 대상 | ALB (comfortablemove-alb-xxx.elb.amazonaws.com) |
| 라우팅 정책 | 단순 라우팅 |
HTTPS 전체 흐름:
사용자 → https://comfortablemove.com → Route53 (DNS → ALB IP) → ALB (HTTPS:443, SSL 종료) → EC2 (HTTP:8000, 내부 통신) → FastAPI 백엔드
7. AWS Budgets 비용 알림
AWS 콘솔 경로: Billing → Budgets → 예산 생성
| 유형 | 임계값 | 금액 (월 $10 기준) | 설명 |
|---|---|---|---|
| 실제 비용 | 50% | $5.00 초과 시 | 조기 경고 |
| 실제 비용 | 80% | $8.00 초과 시 | 주의 경고 |
| 실제 비용 | 100% | $10.00 초과 시 | 한도 초과 |
| 예측 비용 | 100% | $10.00 초과 예측 시 | 사전 예방 |
8. CloudWatch 모니터링 구성
8-1. CloudWatch 대시보드comfortablemove-dashboard에 6개 위젯을 구성했습니다.
- EC2 CPU Utilization, ALB Request Count, RDS CPU Utilization
- RDS Database Connections, ALB Response Time, RDS Free Storage Space
8-2. CloudWatch 알람
SNS 토픽을 생성하여 이메일 구독을 설정했습니다.
| 알람 | 조건 | 설명 |
| :--- | :--- | :--- |
| EC2 CPU High | CPU > 80% | 서버 과부하 감지 |
| ALB 5xx Errors | 5xx > 10회 | 서버 에러 급증 감지 |
| ALB Unhealthy | 비정상 호스트 > 0 | 헬스체크 실패 감지 |
| RDS CPU High | CPU > 80% | DB 과부하 감지 |
| RDS Storage Low | 여유 공간 < 2GB | 디스크 부족 사전 경고 |
📊 전체 아키텍처
아키텍처 다이어그램 (7주차 완성)
인터넷
│
┌──────┴──────┐
│ Route53 │ comfortablemove.com
│ (DNS) │
└──────┬──────┘
│
┌──────┴──────┐
│ ACM │ SSL 인증서 (무료)
│ (HTTPS) │
└──────┬──────┘
│
┌────────────┴────────────┐
│ VPC (10.0.0.0/16) │
│ │
│ ┌─── 퍼블릭 서브넷 ───┐ │
│ │ │ │
│ │ ┌──────────────┐ │ │
│ │ │ ALB │ │ │
│ │ │ (80 → 443) │ │ │
│ │ │ ALB SG │ │ │
│ │ └──────┬───────┘ │ │
│ │ │ │ │
│ │ ┌──────┴───────┐ │ │
│ │ │ EC2 │ │ │
│ │ │ t2.micro │ │ │
│ │ │ EIP: 3.37. │ │ │
│ │ │ EC2 SG │ │ │
│ │ │ :8000 │ │ │
│ │ └──────┬───────┘ │ │
│ └─────────│───────────┘ │
│ │ │
│ ┌─── 프라이빗 서브넷 ─┐ │
│ │ │ │ │
│ │ ┌──────┴───────┐ │ │
│ │ │ RDS │ │ │
│ │ │ PostgreSQL15 │ │ │
│ │ │ RDS SG │ │ │
│ │ │ :5432 │ │ │
│ │ └──────────────┘ │ │
│ └─────────────────────┘ │
│ │
│ ┌─── S3 ────────────┐ │
│ │ comfortablemove- │ │
│ │ assets (암호화) │ │
│ └──────────────────┘ │
└──────────────────────────┘
AWS 리소스 요약 (6주차 + 7주차)
| 구성 요소 | 리소스 | 주차 | 비용 |
|---|---|---|---|
| VPC | 10.0.0.0/16 (서울) | 6주차 | 무료 |
| 서브넷 | 퍼블릭 2개, 프라이빗 2개 | 6주차 | 무료 |
| EC2 | t2.micro, Amazon Linux 2023 | 6주차 | 프리티어 |
| Elastic IP | 3.37.165.32 | 7주차 | 무료 (연결 시) |
| 보안 그룹 | ALB + EC2 + RDS SG | 7주차 | 무료 |
| ALB | Application Load Balancer | 7주차 | ~$16/월 |
| RDS | PostgreSQL 15, db.t3.micro | 7주차 | 프리티어 |
| S3 | comfortablemove-assets | 7주차 | 프리티어 |
| Route53 | 호스팅 영역 | 7주차 | $0.50/월 |
| ACM | SSL 인증서 (와일드카드) | 7주차 | 무료 |
🔧 기술 스택 (7주차 추가)
- Cloud: RDS (PostgreSQL 15), S3, ALB, Route53, ACM, Elastic IP
- Security: 3단계 보안 그룹 체인, HTTPS (TLS 1.3/1.2), S3 퍼블릭 차단, RDS 암호화
💡 배운 점
- RDS vs Docker 컨테이너 DB: RDS를 통해 자동 백업, 패치, CloudWatch 연동 등 운영 편의성을 크게 확보했습니다.
- ALB 사용 이유: SSL 종료를 처리하여 EC2 부하를 줄이고, 인스턴스를 외부에 직접 노출하지 않아 보안을 강화할 수 있었습니다.
- HTTPS 구성 흐름: 도메인 구매부터 DNS 위임, ACM 검증, 리스너 연결까지의 유기적인 과정을 이해했습니다.
- 보안 그룹 체인: IP 대신 보안 그룹 ID를 참조하여 리소스 간 접근 권한을 명확하고 안전하게 관리하는 법을 익혔습니다.
- Elastic IP: 서버 재시작 시에도 IP를 고정하여 DNS 및 CD(지속적 배포) 환경의 안정성을 확보했습니다.
🔄 다음 주 (8주차) 계획
- 실제 서비스 연동 테스트: DATABASE_URL 전환 및 HTTPS 엔드포인트 최종 확인
- CloudWatch 모니터링: 세부 메트릭 대시보드 고도화 및 성능 모니터링
- 인프라 코드화 (Terraform): 콘솔로 만든 리소스의 IaC화 진행