AWS 기반의 History AI 서비스 인프라를 Terraform으로 정의한 IaC(Infrastructure as Code) 레포지토리입니다.
terraform-infrastructure/
├── main.tf # 루트 모듈 – 모든 서브 모듈 호출
├── variables.tf # 루트 변수 선언
├── outputs.tf # 루트 출력값
├── terraform.tfvars # 실제 변수 값 (⚠️ git 제외)
├── terraform.tfvars.example # 변수 예시 파일
└── modules/
├── vpc/ # VPC, 서브넷, 라우팅
├── vpc_endpoints/ # S3·ECR VPC 엔드포인트
├── security/ # 보안 그룹 정의
├── alb/ # Application Load Balancer
├── ecr/ # ECR 이미지 레포지토리
├── ecs/ # ECS Fargate 서비스 (Gateway / Backend / Django)
├── iam/ # ECS 태스크 실행 IAM 역할
├── rds/ # RDS PostgreSQL
├── elasticache/ # ElastiCache Redis
├── s3/ # S3 프런트엔드 버킷
├── cloudfront/ # CloudFront CDN
├── acm/ # ACM TLS 인증서 (us-east-1)
├── route53/ # Route53 DNS 레코드
├── waf/ # WAF (선택)
└── asg/ # Auto Scaling Group (선택)
| 리소스 | 값 | 설명 |
|---|---|---|
| VPC CIDR | 10.0.0.0/16 |
전체 네트워크 대역 |
| Public Subnet A | 10.0.1.0/24 |
ap-northeast-2a – ALB 배치 |
| Public Subnet C | 10.0.2.0/24 |
ap-northeast-2c – ALB 배치 |
| Private Subnet A | 10.0.11.0/24 |
ap-northeast-2a – ECS / RDS / Redis |
| Private Subnet C | 10.0.12.0/24 |
ap-northeast-2c – ECS / RDS / Redis |
- Multi-AZ 구성으로 가용성 확보
- Private 서브넷의 컨테이너는 VPC Endpoint (S3, ECR, Secrets Manager 등)를 통해 인터넷 없이 AWS 서비스에 접근
- NAT Gateway를 통해 외부 API(Typecast TTS 등) 호출 가능
| 보안 그룹 | 역할 |
|---|---|
alb_sg |
인터넷 → ALB 80/443 허용 |
gateway_sg |
ALB → Gateway(8080) 허용 |
backend_sg |
Gateway → Backend(8080) 허용 |
django_sg |
Gateway → Django(8000) 허용 |
rds_sg |
Backend/Django → PostgreSQL(5432) 허용 |
redis_sg |
Backend/Django/Gateway → Redis(6379) 허용 |
세 개의 마이크로서비스가 Private Subnet 위의 ECS Fargate로 실행됩니다.
[ALB] → [Gateway :8080] → [Backend :8080]
↘ [Django :8000]
| 서비스 | 이미지 | CPU | Memory | 역할 |
|---|---|---|---|---|
| Gateway | ECR gateway |
512 | 1024 MB | API 라우팅 (Spring Cloud Gateway) |
| Backend | ECR backend |
512 | 1024 MB | Java Spring Boot 메인 API |
| Django | ECR django |
256 | 512 MB | AI 추론 / TTS (Python Django) |
컨테이너 간 통신은 AWS Cloud Map Private DNS를 사용합니다.
backend.history-ai-prod.local → Backend ECS Task IP
django.history-ai-prod.local → Django ECS Task IP
민감한 정보(DB 비밀번호, JWT 키, Bedrock ARN, Typecast API 키 등)는 모두 AWS Secrets Manager에서 주입됩니다.
history-ai/prod/db-username
history-ai/prod/db-password
history-ai/prod/jwt-secret
history-ai/prod/aws-access-key
history-ai/prod/aws-secret-key
history-ai/prod/bedrock-kb-id
history-ai/prod/bedrock-kb-model-arn
history-ai/prod/bedrock-debate-prompt-arn
history-ai/prod/bedrock-ai-person-prompt-arn
history-ai/prod/bedrock-debate-summary-prompt-arn
history-ai/prod/redis-url
history-ai/prod/typecast-api-key
각 서비스는 CloudWatch Log Group에 7일 보존 설정으로 로그를 전송합니다.
/ecs/history-ai-prod-gateway
/ecs/history-ai-prod-backend
/ecs/history-ai-prod-django
| 항목 | 값 |
|---|---|
| 엔진 | PostgreSQL 15.15 |
| 인스턴스 | db.t3.micro |
| 스토리지 | 20 GB |
| DB명 | historyai |
| 배치 | Private Subnet (Multi-AZ 서브넷 그룹) |
| 항목 | 값 |
|---|---|
| 버전 | Redis 7.0 |
| 노드 타입 | cache.t3.micro |
| 배치 | Private Subnet |
| 용도 | 세션 캐싱, Gateway 상태 관리 |
사용자 → CloudFront (khistoryai.com)
├── /api/* → ALB → ECS Gateway
└── /* → S3 (정적 프런트엔드)
| 리소스 | 설명 |
|---|---|
| S3 | 빌드된 프런트엔드 정적 파일 호스팅 |
| CloudFront | CDN + HTTPS 종료 |
| ACM | khistoryai.com TLS 인증서 (us-east-1 자동 발급) |
| Route53 | khistoryai.com → CloudFront A 레코드 |
이미지 레포지토리 3개가 자동으로 생성됩니다.
<account>.dkr.ecr.ap-northeast-2.amazonaws.com/history-ai-prod-gateway
<account>.dkr.ecr.ap-northeast-2.amazonaws.com/history-ai-prod-backend
<account>.dkr.ecr.ap-northeast-2.amazonaws.com/history-ai-prod-django
| 역할 | 용도 |
|---|---|
ecs-task-execution-role |
ECR 이미지 Pull, CloudWatch 로그 전송, Secrets Manager 읽기 |
ecs-task-role |
Bedrock, S3 등 태스크 런타임 권한 |
- Terraform
>= 1.0 - AWS CLI 설정 (
aws configure) - AWS 계정에 적절한 IAM 권한
cp terraform.tfvars.example terraform.tfvars
# terraform.tfvars 를 편집하여 실제 값 입력주요 설정 항목:
aws_region = "ap-northeast-2"
project_name = "history-ai"
environment = "prod"
domain_name = "khistoryai.com"
# DB 비밀번호 (Secrets Manager 사용 권장)
postgres_master_password = "YOUR_SECURE_PASSWORD"# DB 인증 정보
aws secretsmanager create-secret --name "history-ai/prod/db-username" --secret-string "postgres"
aws secretsmanager create-secret --name "history-ai/prod/db-password" --secret-string "YOUR_PASSWORD"
aws secretsmanager create-secret --name "history-ai/prod/jwt-secret" --secret-string "YOUR_JWT_SECRET"
aws secretsmanager create-secret --name "history-ai/prod/redis-url" --secret-string "rediss://YOUR_REDIS_ENDPOINT:6379"
# Bedrock / AI
aws secretsmanager create-secret --name "history-ai/prod/aws-access-key" --secret-string "YOUR_KEY"
aws secretsmanager create-secret --name "history-ai/prod/aws-secret-key" --secret-string "YOUR_SECRET"
aws secretsmanager create-secret --name "history-ai/prod/bedrock-kb-id" --secret-string "YOUR_KB_ID"
aws secretsmanager create-secret --name "history-ai/prod/bedrock-kb-model-arn" --secret-string "YOUR_MODEL_ARN"
aws secretsmanager create-secret --name "history-ai/prod/bedrock-debate-prompt-arn" --secret-string "YOUR_ARN"
aws secretsmanager create-secret --name "history-ai/prod/bedrock-ai-person-prompt-arn" --secret-string "YOUR_ARN"
aws secretsmanager create-secret --name "history-ai/prod/bedrock-debate-summary-prompt-arn" --secret-string "YOUR_ARN"
# Typecast TTS
aws secretsmanager create-secret --name "history-ai/prod/typecast-api-key" --secret-string "YOUR_KEY"# 초기화
terraform init
# 플랜 확인
terraform plan -out=tfplan
# 적용
terraform apply tfplan# ECR 로그인
aws ecr get-login-password --region ap-northeast-2 | \
docker login --username AWS --password-stdin <account>.dkr.ecr.ap-northeast-2.amazonaws.com
# 예: Gateway 이미지 빌드 & 푸시
docker build -t history-ai-prod-gateway ./gateway
docker tag history-ai-prod-gateway:latest <ECR_URL>/history-ai-prod-gateway:latest
docker push <ECR_URL>/history-ai-prod-gateway:latestaws ecs update-service \
--cluster history-ai-prod-cluster \
--service history-ai-prod-gateway \
--force-new-deployment
aws ecs update-service \
--cluster history-ai-prod-cluster \
--service history-ai-prod-backend \
--force-new-deployment
aws ecs update-service \
--cluster history-ai-prod-cluster \
--service history-ai-prod-django \
--force-new-deployment# S3 업로드
aws s3 sync ./frontend/dist s3://history-ai-prod-s3-frontend
# CloudFront 캐시 무효화
aws cloudfront create-invalidation \
--distribution-id <DISTRIBUTION_ID> \
--paths "/*"terraform apply 완료 후 아래 값들이 출력됩니다.
| Output | 설명 |
|---|---|
application_url |
https://khistoryai.com |
cloudfront_url |
CloudFront 배포 URL |
alb_url |
ALB 직접 접근 URL |
ecs_cluster_name |
ECS 클러스터 이름 |
ecr_gateway_repository_url |
Gateway ECR URL |
ecr_backend_repository_url |
Backend ECR URL |
ecr_django_repository_url |
Django ECR URL |
s3_frontend_bucket_name |
프런트엔드 S3 버킷 이름 |
cloudfront_distribution_id |
CloudFront 배포 ID |
| 변수 | 기본값 | 설명 |
|---|---|---|
aws_region |
ap-northeast-2 |
AWS 리전 |
project_name |
history-ai |
리소스 공통 접두어 |
environment |
prod |
환경 (dev / staging / prod) |
vpc_cidr |
10.0.0.0/16 |
VPC CIDR |
domain_name |
khistoryai.com |
서비스 도메인 |
postgres_version |
15.15 |
PostgreSQL 버전 |
rds_instance_class |
db.t3.micro |
RDS 인스턴스 |
redis_node_type |
cache.t3.micro |
Redis 노드 |
gateway_cpu / gateway_memory |
512 / 1024 MB |
Gateway 리소스 |
backend_cpu / backend_memory |
512 / 1024 MB |
Backend 리소스 |
django_cpu / django_memory |
256 / 512 MB |
Django 리소스 |
terraform.tfvars파일은.gitignore에 등록하여 절대 커밋 금지- DB 비밀번호 등 민감 정보는 모두 AWS Secrets Manager로 관리
- ECS 태스크는 Public IP 없이 Private Subnet에서만 실행
- ALB는 Public Subnet에 위치하지만 보안 그룹으로 접근 제한
- TLS는 CloudFront ↔ 사용자 구간에서 ACM 인증서로 자동 처리
terraform destroy
⚠️ S3 버킷에 오브젝트가 남아있으면 삭제가 실패할 수 있습니다. 먼저 버킷을 비워주세요.aws s3 rm s3://history-ai-prod-s3-frontend --recursive
