IaC 도입 및 확장된 인프라 구조 문서화 - 100-hours-a-week/KTB4-4th-wiki GitHub Wiki
NeedU V2부터 AWS 인프라를 Terraform 기반 IaC(Infrastructure as Code)로 관리한다.
V1은 단일 EC2에서 Docker Compose로 Frontend, Backend, AI Server를 운영하고, MySQL과 PostgreSQL을 EC2에 직접 설치하는 구조였다.
V2에서는 ECS Fargate, ALB, RDS, ElastiCache 등 관리 대상이 증가하고, 개발·검증·운영 환경을 분리한다.
이에 따라 Terraform을 도입하여 다음을 목표로 한다.
- AWS 인프라 구성을 코드로 관리하고 변경 이력을 Git에 남긴다.
- 환경별 목적에 맞는 인프라를 구성한다.
- 공통 리소스는 재사용 가능한 Terraform Module로 관리한다.
- Dev, Staging, Prod의 리소스와 접근 권한을 격리한다.
- Staging에서 Prod와 동일한 조건으로 배포 및 데이터 이전을 검증한다.
- AWS Console을 통한 수동 변경을 최소화한다.
- Terraform은 인프라 구조를 관리하고, CD는 애플리케이션 버전을 관리한다.
NeedU V2에서는 Dev, Staging, Prod를 단순히 이름만 다른 동일한 환경으로 구성하지 않는다.
각 환경의 목적에 따라 리소스 사양, 배포 정책, 데이터, 운영 기능을 다르게 구성한다.
| 구분 | Dev | Staging | Prod |
|---|---|---|---|
| 목적 | 개발 및 통합 테스트 | 운영 배포 및 DB Migration 리허설 | 실제 사용자 서비스 |
| 주요 사용자 | 개발팀 | 개발팀·Cloud팀 | 실제 사용자 |
| 인프라 구성 | 경량 V2 환경 | Prod와 동등한 환경 | 운영 기준 환경 |
| 애플리케이션 | 개발 버전 | 배포 후보 버전 | 승인된 운영 버전 |
| 데이터 | 테스트 데이터 | 운영 데이터의 검증용 복제본 | 실제 운영 데이터 |
| 배포 | 자동 | 수동 승인 | 수동 승인 |
| 상시 운영 | O | 필요 시 생성·삭제 | O |
| 데이터 보호 | 개발 기준 | 검증 기준 | 운영 기준 |
Dev는 개발 중인 기능을 실제 V2 인프라에서 통합 검증하기 위한 환경이다.
Frontend, Backend, AI Server가 각각 ECS Service로 실행되며, ALB, Service Connect, RDS, ElastiCache를 사용한다.
단, Dev는 운영 환경과 동일한 처리량이나 가용성을 보장하는 것이 목적이 아니다.
따라서 다음과 같이 경량화한다.
- ECS Service별 기본 Task 수 1개
- Auto Scaling 기본 비활성화
- RDS 소형 인스턴스 사용
- ElastiCache 소형 구성
- CloudWatch 로그 보존 기간 단축
- 운영 데이터 대신 테스트 데이터 사용
- GitHub Actions를 통한 자동 배포
Dev에서 검증하는 항목은 다음과 같다.
- FE → BE API 통신
- BE → AI Service Connect 통신
- ECS → RDS 연결
- ECS → ElastiCache 연결
- Redis 기반 공유 상태 및 Pub/Sub
- AI Catalog Sync / Import
- Parameter Store 환경변수 주입
- 서비스 간 통합 기능
- 필요 시 다중 Task 동작
Dev는 Prod와 동일한 AWS 서비스를 일부 사용하지만, 리소스 규모와 운영 정책은 다르다.
Staging은 Prod 배포 전에 운영 환경과 동일한 조건에서 변경 사항을 검증하는 환경이다.
Dev와 달리 Staging은 Prod의 인프라 구조와 주요 설정을 동일하게 구성한다.
특히 V1 → V2 전환 과정에서는 실제 운영 데이터 이전 절차를 사전에 검증하는 역할을 수행한다.
Staging에서 검증하는 항목은 다음과 같다.
- Prod와 동일한 ECS Service 구성
- Prod와 동일한 Task 수 및 리소스 사양
- Prod와 동일한 ALB Routing
- Prod와 동일한 Service Connect 구성
- Prod와 동일한 RDS 엔진·버전·사양
- Prod와 동일한 ElastiCache 구성
- AI Catalog Batch 실행
- V1 → V2 DB Migration
- 데이터 정합성
- 실제 배포 절차
- Rolling Deployment
- 서비스 간 E2E 동작
- 장애 및 Rollback 절차
Staging은 Prod와 동일한 Terraform Module 및 설정을 기반으로 생성한다.
다만 운영 데이터 보호와 환경 격리를 위해 다음 항목은 분리한다.
- 도메인
- 데이터베이스 및 데이터
- IAM Role
- Parameter Store
- Security Group
- S3 Bucket
- CloudWatch Log Group
- 삭제 보호 정책
Staging은 상시 운영하지 않고, 배포 검증이나 Migration 리허설이 필요할 때 Terraform으로 생성한다.
검증 완료 후 로그와 필요한 Snapshot을 보존하고 리소스를 삭제한다.
Prod는 실제 사용자가 접근하는 운영 환경이다.
가용성, 데이터 보호, 보안, 모니터링을 우선한다.
- FE / BE / AI 최소 2 Task
- ECS Service Auto Scaling
- RDS 백업 및 삭제 보호
- 운영용 ElastiCache
- CloudWatch Alarm
- 승인 기반 배포
- 운영 데이터 보호
- Rollback 절차
- 운영용 IAM 최소 권한
Dev, Staging, Prod는 별도의 애플리케이션 프로젝트를 만들지 않는다.
Frontend, Backend, AI Server는 각각 동일한 코드베이스를 사용한다.
환경에 따라 배포하는 이미지 버전과 설정값이 달라진다.
Frontend Repository
Backend Repository
AI Repository
│
▼
GitHub Actions CI
│
▼
ECR
│
├── Dev
│ └── 개발 중인 Image
│
├── Staging
│ └── Prod 배포 후보 Image
│
└── Prod
└── Staging에서 검증한 동일 Image
Staging에서 검증한 이미지의 Git SHA 또는 Image Digest를 Prod 배포에 그대로 사용한다.
인프라 코드 역시 공통 Module을 재사용하지만 환경별 Root Module은 목적에 따라 다르게 구성할 수 있다.
특히 Staging과 Prod는 동일한 인프라 구성을 재현할 수 있도록 공통 구성을 사용한다.
| 영역 | 결정 |
|---|---|
| IaC 도구 | Terraform |
| Terraform 저장소 | Cloud 저장소 |
| Terraform 구성 단위 | bootstrap / shared / dev / staging / prod |
| Terraform State | 5개 |
| 기존 VPC / IGW / Hosted Zone | Terraform data로 참조 |
| 공용 리소스 | shared State |
| Terraform 운영 기반 | bootstrap State |
| Subnet / Route Table | 환경별 생성 |
| ECS Cluster | needu-{env}-cluster |
| 리소스 이름 | needu-{env}-{role} |
| 설정값 저장 | Parameter Store |
| Task Definition | Terraform에서 기본 정의 관리 |
| ECR | 기존 Repository Import |
| Redis | ElastiCache |
| Dev | 경량 통합 테스트 환경 |
| Staging | Prod 동등 배포·Migration 검증 환경 |
| Prod | 실제 운영 환경 |
| Staging / Prod 관계 | 동일한 인프라 구성 |
| Dev / Prod 관계 | 공통 기술 스택, 다른 리소스 사양·운영 정책 |
| State Backend | State별 S3 Bucket |
| State Lock | S3 Native Lock |
| Prod 초기 도메인 | v2.needu.gift |
| Production 전환 | 검증 후 needu.gift 전환 |
Internet
│
▼
Internet Gateway (data)
│
▼
VPC 10.0.0.0/16 (data)
│
├── V1
│ └── 기존 EC2 운영 환경
│
├── Dev (dev State)
│ ├── Public Subnet A / C
│ │ ├── ALB
│ │ ├── Frontend ECS Service
│ │ ├── Backend ECS Service
│ │ ├── AI ECS Service
│ │ ├── AI Catalog Sync Task
│ │ └── AI Catalog Import Task
│ │
│ └── Private DB Subnet A / C
│ ├── RDS MySQL
│ ├── RDS PostgreSQL + pgvector
│ └── ElastiCache Redis
│
├── Staging (staging State)
│ ├── Public Subnet A / C
│ │ ├── ALB
│ │ ├── Frontend ECS Service
│ │ ├── Backend ECS Service
│ │ ├── AI ECS Service
│ │ ├── AI Catalog Sync Task
│ │ ├── AI Catalog Import Task
│ │ └── Migration Task
│ │
│ └── Private DB Subnet A / C
│ ├── RDS MySQL
│ ├── RDS PostgreSQL + pgvector
│ └── ElastiCache Redis
│
└── Prod (prod State)
├── Public Subnet A / C
│ ├── ALB
│ ├── Frontend ECS Service
│ ├── Backend ECS Service
│ ├── AI ECS Service
│ ├── AI Catalog Sync Task
│ └── AI Catalog Import Task
│
└── Private DB Subnet A / C
├── RDS MySQL
├── RDS PostgreSQL + pgvector
└── ElastiCache Redis
Shared (shared State)
├── ECR Frontend
├── ECR Backend
├── ECR AI
├── CI Role
└── 공통 Frontend Build Parameters
Bootstrap (bootstrap State)
├── Terraform State Bucket 5개
└── Terraform IAM Roles
Data 참조
├── 기존 VPC
├── Internet Gateway
├── Route 53 Hosted Zone
└── GitHub OIDC Provider
| 항목 | Dev | Staging | Prod |
|---|---|---|---|
| ALB | 별도 ALB | Prod와 동일한 설정 | 기준 |
| ECS FE | 1 Task | 2 Task | 2 Task |
| ECS BE | 1 Task | 2 Task | 2 Task |
| ECS AI | 1 Task | 2 Task | 2 Task |
| Service Connect | 사용 | Prod 동일 | 사용 |
| RDS | 소형 | Prod 동일 | 운영 사양 |
| ElastiCache | 소형 | Prod 동일 | 운영 사양 |
| Auto Scaling | 기본 OFF | Prod 동일 | ON |
| AI Catalog | 테스트 실행 | Prod 동일 | 운영 실행 |
| CloudWatch | 개발 기준 | Prod 동등 지표·경보 | 운영 기준 |
| 배포 | 자동 | 승인 | 승인 |
Prod와 Staging의 Task 수 및 사양은 V2 부하 테스트 결과에 따라 함께 변경한다.
| 구분 | 리소스 | State |
|---|---|---|
| 환경별 관리 | Subnet, Route Table, Security Group | dev / staging / prod |
| 환경별 관리 | ALB, Target Group, Listener | dev / staging / prod |
| 환경별 관리 | ECS Cluster, Service, Task Definition | dev / staging / prod |
| 환경별 관리 | Service Connect | dev / staging / prod |
| 환경별 관리 | Auto Scaling | staging / prod |
| 환경별 관리 | RDS, DB Subnet Group | dev / staging / prod |
| 환경별 관리 | ElastiCache | dev / staging / prod |
| 환경별 관리 | AI Catalog S3 | dev / staging / prod |
| 환경별 관리 | IAM Task Role, Execution Role, CD Role | dev / staging / prod |
| 환경별 관리 | Parameter Store 이름 | dev / staging / prod |
| 환경별 관리 | CloudWatch Logs, Alarm | dev / staging / prod |
| 환경별 관리 | ACM Certificate, Route 53 Record | dev / staging / prod |
| 공용 관리 | CI Role, 공통 Parameter | shared |
| Import 후 관리 | ECR 3개 | shared |
| 운영 기반 | State Bucket, Terraform Role | bootstrap |
| data 참조 | VPC, IGW, Hosted Zone, OIDC Provider | 없음 |
| Terraform 외부 관리 | Parameter 실제 비밀 값 | 없음 |
하나의 AWS 리소스는 하나의 Terraform State에서만 관리한다.
기존 VPC, Internet Gateway, Route 53 Hosted Zone, GitHub OIDC Provider는 data source로 참조한다.
V1 운영 환경에 영향을 주지 않기 위해 기존 리소스를 새로 생성하거나 변경하지 않는다.
data "aws_vpc" "main" {
id = var.vpc_id
}
data "aws_internet_gateway" "main" {
internet_gateway_id = var.internet_gateway_id
}
data "aws_route53_zone" "main" {
name = "needu.gift"
}
data "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"
}Shared State에서는 환경 간 공통으로 사용하는 리소스를 관리한다.
| 리소스 | 공용 관리 이유 |
|---|---|
| ECR | 동일 Image Repository 사용 |
| CI Role | 이미지 빌드·Push는 환경과 독립적 |
| FE 공통 Parameter | 빌드에 필요한 공통 설정 |
Dev, Staging, Prod는 공용 리소스를 data source로 조회한다.
Terraform 실행을 위해 먼저 필요한 리소스를 관리한다.
- State Bucket 5개
- Terraform Plan Role
- Terraform Dev Role
- Terraform Staging Role
- Terraform Prod Role
Bootstrap은 최초 구축 후 변경이 드물기 때문에 Cloud 팀이 별도로 관리한다.
Cloud Repository/
│
├── .github/
│ └── workflows/
│ ├── terraform-pr.yml
│ ├── terraform-dev.yml
│ ├── terraform-staging.yml
│ └── terraform-prod.yml
│
├── modules/
│ ├── network/
│ ├── security-groups/
│ ├── alb/
│ ├── ecs-cluster/
│ ├── ecs-service/
│ ├── ai-catalog/
│ ├── migration-task/
│ ├── rds/
│ ├── elasticache/
│ ├── ecr/
│ ├── iam-github-oidc/
│ ├── parameters/
│ └── observability/
│
├── bootstrap/
│ ├── backend.tf
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
│
└── environments/
├── shared/
│ ├── backend.tf
│ ├── main.tf
│ ├── variables.tf
│ └── shared.tfvars
│
├── dev/
│ ├── backend.tf
│ ├── main.tf
│ ├── variables.tf
│ └── dev.tfvars
│
├── staging/
│ ├── backend.tf
│ ├── main.tf
│ ├── variables.tf
│ └── staging.tfvars
│
└── prod/
├── backend.tf
├── main.tf
├── variables.tf
└── prod.tfvars
Terraform Module은 AWS 리소스의 재사용 가능한 구성 단위다.
Dev, Staging, Prod에서 같은 AWS 서비스를 사용한다면 가능한 한 동일한 Module을 재사용한다.
다만 Module을 재사용한다고 해서 모든 환경의 인프라가 같아지는 것은 아니다.
환경별 Root Module에서 필요한 기능과 리소스 사양을 결정한다.
Dev는 통합 테스트에 필요한 Module을 사용한다.
- Network
- ALB
- ECS
- Service Connect
- RDS
- ElastiCache
- AI Catalog
- Parameter Store
- IAM
- CloudWatch
운영용 Auto Scaling과 일부 고가용성 설정은 기본적으로 적용하지 않는다.
Staging과 Prod는 동일한 Module 조합을 사용한다.
- Network
- ALB
- ECS
- Service Connect
- RDS
- ElastiCache
- AI Catalog
- Auto Scaling
- Parameter Store
- IAM
- CloudWatch
Staging에는 추가로 Migration Task를 실행할 수 있는 구성을 둔다.
Staging과 Prod의 설정 차이가 불필요하게 발생하지 않도록 운영 사양을 공통 변수로 관리한다.
예를 들어 다음 항목을 동일하게 유지한다.
- ECS CPU / Memory
- ECS 기본 Task 수
- Auto Scaling 설정
- RDS Engine / Version
- RDS Instance Class
- RDS Storage
- ElastiCache Engine / Version / Node Type
- ALB Listener / Target Group 설정
- Service Connect 설정
환경별로 반드시 달라야 하는 값만 별도로 관리한다.
- Resource Name
- Domain
- Database Name
- Credentials
- Parameter 경로
- IAM Resource ARN
- S3 Bucket
- 데이터
- 삭제 보호 및 리소스 수명 정책
State별 전용 S3 Bucket을 사용한다.
| State | Bucket | 적용 주체 |
|---|---|---|
| bootstrap | bootstrap-state-bucket | Cloud 팀 |
| shared | shared-state-bucket | 승인된 파이프라인 |
| dev | dev-state-bucket | 자동 파이프라인 |
| staging | staging-state-bucket | 수동 파이프라인 |
| prod | prod-state-bucket | 승인된 파이프라인 |
Bucket 이름은 실제 생성 시 전역 유일성을 고려해 확정한다.
terraform {
backend "s3" {
bucket = "<state-bucket>"
key = "terraform.tfstate"
region = "ap-northeast-2"
use_lockfile = true
encrypt = true
}
}모든 State Bucket에는 다음을 적용한다.
- Versioning
- Encryption
- Public Access Block
- S3 Native Lock
- 최소 권한 IAM
1. Bootstrap 로컬 초기화
2. Terraform Apply
3. State Bucket 5개 생성
4. Terraform IAM Role 생성
5. S3 Backend 설정
6. terraform init -migrate-state
Bootstrap State도 최종적으로 S3에 보관한다.
Staging은 필요할 때 생성하고 삭제한다.
Staging State Bucket
│
▼
terraform apply
│
▼
Staging 전체 인프라 생성
│
▼
배포 / Migration 검증
│
▼
Snapshot 및 결과 보존
│
▼
terraform destroy
Staging 리소스를 삭제하더라도 State Bucket은 유지한다.
bootstrap
│
▼
shared
│
▼
dev
│
▼
staging (필요 시)
│
▼
prod
Staging은 Prod 인프라 및 배포 절차 검증이 필요한 시점에 생성한다.
Pull Request
│
├── terraform fmt -check
├── terraform init
├── terraform validate
└── terraform plan
공통 Module 변경 시 해당 Module을 사용하는 환경을 모두 검증한다.
| 환경 | 적용 방식 | 승인 |
|---|---|---|
| bootstrap | Cloud 팀 로컬 | Cloud 팀 |
| shared | GitHub Actions | Cloud 팀 |
| dev | Merge 후 자동 | 없음 |
| staging | workflow_dispatch | 필요 |
| prod | workflow_dispatch | 필요 |
Staging은 다음 작업을 수동으로 실행한다.
terraform apply
│
▼
Staging 인프라 생성
│
▼
배포 후보 Image 배포
│
▼
Migration / E2E 검증
│
▼
검증 결과 확인
│
▼
terraform destroy
Staging의 생성·삭제는 Prod 리소스에 영향을 주지 않아야 한다.
S3 Native Lock을 사용하기 위해 Terraform 1.10 이상을 사용한다.
terraform {
required_version = ">= 1.10.0, < 2.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}다음 파일은 Git에 포함한다.
.terraform.lock.hcl
다음 파일은 Git에서 제외한다.
.terraform/
*.tfstate
*.tfstate.backup
*.tfplan
실제 사용 버전은 팀 내에서 동일하게 유지한다.
기존 V1 VPC를 재사용한다.
VPC: 10.0.0.0/16
V1 Subnet은 변경하지 않는다.
| Subnet | AZ | CIDR |
|---|---|---|
| Public A | ap-northeast-2a | 10.0.16.0/24 |
| Public C | ap-northeast-2c | 10.0.17.0/24 |
| Private DB A | ap-northeast-2a | 10.0.20.0/24 |
| Private DB C | ap-northeast-2c | 10.0.21.0/24 |
| Subnet | AZ | CIDR |
|---|---|---|
| Public A | ap-northeast-2a | 10.0.32.0/24 |
| Public C | ap-northeast-2c | 10.0.33.0/24 |
| Private DB A | ap-northeast-2a | 10.0.36.0/24 |
| Private DB C | ap-northeast-2c | 10.0.37.0/24 |
| Subnet | AZ | CIDR |
|---|---|---|
| Public A | ap-northeast-2a | 10.0.48.0/24 |
| Public C | ap-northeast-2c | 10.0.49.0/24 |
| Private DB A | ap-northeast-2a | 10.0.52.0/24 |
| Private DB C | ap-northeast-2c | 10.0.53.0/24 |
CIDR은 실제 VPC에서 중복 여부를 확인한 후 확정한다.
기존 V2 설계대로 NAT Gateway를 사용하지 않는다.
ECS Task는 Public Subnet에 배치하고 Public IP를 할당한다.
Public Subnet
├── Frontend ECS
├── Backend ECS
└── AI ECS
ECS Task의 외부 직접 접근은 Security Group으로 제한한다.
ALB는 2개 AZ의 Public Subnet에 배치한다.
ALB
├── Public Subnet A
└── Public Subnet C
RDS는 Private DB Subnet에 배치한다.
DB Subnet Group
├── Private DB A
└── Private DB C
Staging과 Prod는 동일한 RDS 배치 정책을 사용한다.
| 계층 | Dev | Staging | Prod |
|---|---|---|---|
| State | dev | staging | prod |
| Security Group | needu-dev-* | needu-staging-* | needu-prod-* |
| Service Connect | needu-dev | needu-staging | needu-prod |
| Parameter Store | /needu/dev/* | /needu/staging/* | /needu/prod/* |
| IAM | Dev 전용 | Staging 전용 | Prod 전용 |
| ALB | Dev ALB | Staging ALB | Prod ALB |
| RDS | Dev DB | Staging DB | Prod DB |
| ElastiCache | Dev Redis | Staging Redis | Prod Redis |
| AI Catalog S3 | Dev Bucket | Staging Bucket | Prod Bucket |
동일 VPC에 있더라도 환경 간 접근은 Security Group과 IAM으로 제한한다.
| Security Group | Ingress |
|---|---|
| needu-{env}-alb-sg | 443 ← Internet |
| needu-{env}-frontend-sg | 3000 ← ALB |
| needu-{env}-backend-sg | 8080 ← ALB |
| needu-{env}-ai-sg | 8000 ← Backend |
| needu-{env}-ai-catalog-sync-sg | 없음 |
| needu-{env}-ai-catalog-import-sg | 없음 |
| needu-{env}-mysql-sg | 3306 ← Backend, Catalog Sync |
| needu-{env}-postgres-sg | 5432 ← AI, Catalog Sync, Catalog Import |
| needu-{env}-redis-sg | 6379 ← Backend, AI |
Staging에서는 Migration Task가 V1 DB와 Staging RDS에 접근할 수 있도록 별도 규칙을 추가한다.
Migration 완료 후 V1 DB 접근 규칙은 제거한다.
| 환경 | Domain |
|---|---|
| Dev | dev.needu.gift |
| Staging | staging.needu.gift |
| Prod 검증 | v2.needu.gift |
| Prod 전환 후 | needu.gift |
Staging 도메인은 운영 전환과 독립적으로 유지한다.
ALB
├── /api/* → Backend Target Group
└── 그 외 → Frontend Target Group
AI Service는 외부에 직접 노출하지 않는다.
Backend가 Service Connect를 통해 AI를 호출한다.
Fargate는 awsvpc Network Mode를 사용한다.
target_type = "ip"ACM Certificate는 각 환경에서 관리한다.
Route 53 DNS Validation을 사용한다.
| 서비스 | Dev | Staging | Prod |
|---|---|---|---|
| Frontend | 1 | 2 | 2 |
| Backend | 1 | 2 | 2 |
| AI | 1 | 2 | 2 |
초기 사양:
| 서비스 | CPU | Memory |
|---|---|---|
| Frontend | 0.5 vCPU | 1 GiB |
| Backend | 1 vCPU | 2 GiB |
| AI | 1 vCPU | 2 GiB |
Staging과 Prod는 동일한 사양을 사용한다.
Prod 사양이 변경되면 Staging도 함께 변경한다.
Dev는 기능 검증을 위한 최소 Task 수를 사용한다.
Prod는 최소 2 Task와 Auto Scaling을 사용한다.
Staging은 Prod와 동일한 Task 수와 Auto Scaling 정책을 사용한다.
Terraform은 기본 Task Definition을 관리한다.
- CPU
- Memory
- Port Mapping
- Task Role
- Execution Role
- Environment
- Secrets
- Logging
- 초기 Docker Image
CD는 기존 Task Definition을 조회하고 Docker Image SHA를 변경하여 새 Revision을 등록한다.
CD와 Terraform의 충돌을 방지하기 위해 Task Definition 변경을 무시한다.
lifecycle {
ignore_changes = [
task_definition
]
}Staging과 Prod는 Auto Scaling이 desired_count를 변경할 수 있으므로 해당 속성도 무시할 수 있다.
Dev에서 Terraform으로 Task 수를 직접 관리한다면 desired_count를 무시하지 않는다.
환경별 Namespace를 분리한다.
Dev
Backend → ai-server:8000 → AI
Staging
Backend → ai-server:8000 → AI
Prod
Backend → ai-server:8000 → AI
Namespace:
needu-dev
needu-staging
needu-prod
Staging과 Prod는 동일한 Service Connect 설정을 사용한다.
| 항목 | Dev | Staging | Prod |
|---|---|---|---|
| MySQL | 소형 | db.t4g.medium | db.t4g.medium |
| MySQL Storage | 개발용 | gp3 50GiB | gp3 50GiB |
| PostgreSQL | 소형 | db.t4g.small | db.t4g.small |
| PostgreSQL Storage | 개발용 | gp3 20GiB | gp3 20GiB |
| Engine Version | 동일 | 동일 | 동일 |
| pgvector Version | 동일 | 동일 | 동일 |
| Multi-AZ | OFF | Prod 동일 | 초기 OFF |
| Public Access | OFF | OFF | OFF |
| 삭제 보호 | OFF | OFF | ON |
| Backup | 짧은 보존 | 리허설용 | 운영 기준 |
Dev에서도 ECS와 RDS 연결을 검증해야 하므로 별도 RDS를 사용한다.
그러나 운영 데이터나 Prod와 동일한 DB 성능을 요구하지 않는다.
Staging과 Prod는 다음 항목을 동일하게 유지한다.
- Engine
- Engine Version
- Instance Class
- Storage
- Parameter Group
- pgvector
- 문자셋
- Collation
- 주요 네트워크 설정
데이터와 삭제 보호 정책은 환경별로 분리한다.
Prod에는 다음 설정을 적용한다.
deletion_protection = trueTerraform에서 실수로 삭제되지 않도록 prevent_destroy를 적용한다.
Staging은 리허설 종료 후 삭제해야 하므로 별도 삭제 정책을 사용한다.
- Kakao OAuth State
- AI 대화방 Session
- Rate Limit
- Redis Pub/Sub
- 공유 캐시
| 항목 | Dev | Staging | Prod |
|---|---|---|---|
| ElastiCache | O | O | O |
| 목적 | 기능 검증 | 운영 동작 검증 | 실제 서비스 |
| Node 사양 | 소형 | Prod 동일 | 운영 사양 |
| Redis Version | 동일 | 동일 | 동일 |
| 데이터 | 테스트 | 검증용 | 운영 |
Staging과 Prod는 동일한 ElastiCache 구성을 사용한다.
환경별 설정값은 Parameter Store에 저장한다.
Terraform은 Parameter 이름과 IAM 접근 권한을 관리한다.
실제 비밀 값은 Terraform 코드에 작성하지 않는다.
/needu/common/frontend-build/
/needu/dev/frontend/
/needu/dev/backend/
/needu/dev/ai/
/needu/dev/ai-catalog/
/needu/staging/frontend/
/needu/staging/backend/
/needu/staging/ai/
/needu/staging/ai-catalog/
/needu/staging/migration/
/needu/prod/frontend/
/needu/prod/backend/
/needu/prod/ai/
/needu/prod/ai-catalog/
ECS Task Definition의 secrets를 통해 Parameter Store 값을 주입한다.
Task Execution Role에는 필요한 조회 권한을 부여한다.
Parameter 변경 후 해당 서비스를 재배포한다.
기존 ECR Repository를 shared State에서 관리한다.
need-u/frontend
need-u/backend
need-u/ai
| 항목 | 정책 |
|---|---|
| Tag | Git SHA |
| latest | 사용하지 않음 |
| Mutability | IMMUTABLE |
| 관리 State | shared |
| Rollback | 이전 Image 보존 |
Dev는 개발 버전을 배포한다.
Staging은 Prod 배포 후보 이미지를 배포한다.
Prod는 Staging에서 검증한 동일 Image를 배포한다.
MySQL 상품 조회
│
▼
PostgreSQL Catalog 동기화
│
▼
S3 Input 생성
AI 팀원 Mac
│
├── S3 Input Download
├── Local Model 실행
└── S3 Output Upload
S3 Output
│
▼
Upstage Embedding
│
▼
PostgreSQL 저장
Dev에서는 테스트 데이터를 사용하여 Catalog Sync / Import를 검증한다.
Staging에서는 Prod와 동일한 Task Definition 및 실행 절차를 검증한다.
Prod에서는 실제 Catalog 데이터를 처리한다.
환경별 Bucket을 분리한다.
Dev Catalog Bucket
Staging Catalog Bucket
Prod Catalog Bucket
Object 구조:
jobs/
└── <job_id>/
├── input/
│ └── products.json
└── output/
└── enriched-products.json
보안 정책:
- Public Access Block
- Encryption
- Versioning
- IAM 최소 권한
- 환경별 접근 제한
| 항목 | 설정 |
|---|---|
| Task Definition | needu-{env}-ai-catalog-sync |
| Image | AI Image |
| MySQL | Read |
| PostgreSQL | Write |
| S3 | Input Write |
| Logging | CloudWatch |
| 항목 | 설정 |
|---|---|
| Task Definition | needu-{env}-ai-catalog-import |
| Image | AI Image |
| S3 | Output Read |
| PostgreSQL | Write |
| 외부 API | Upstage |
| Logging | CloudWatch |
Sync와 Import는 별도 Task Role을 사용한다.
DB 접근은 Security Group과 DB 계정 권한으로 제어한다.
AI 팀원 Mac은 DB에 직접 접근하지 않고 S3를 통해 데이터를 주고받는다.
| 경로 | 권한 |
|---|---|
| jobs//input/ | Read |
| jobs//output/ | Write |
환경별 Bucket 접근 권한을 분리한다.
운영용 S3 접근은 필요한 사용자에게만 허용한다.
| 대상 | Execution Role | Task Role |
|---|---|---|
| Frontend | ECR, Logs, SSM | 필요 시 |
| Backend | ECR, Logs, SSM | CloudWatch 등 |
| AI | ECR, Logs, SSM | 필요 시 |
| Catalog Sync | ECR, Logs, SSM | S3 Input Write |
| Catalog Import | ECR, Logs, SSM | S3 Output Read |
| Migration | ECR, Logs, SSM | 필요한 AWS API |
| Role | State | 대상 |
|---|---|---|
| CI Role | shared | FE / BE / AI CI |
| Dev CD Role | dev | Dev 배포 |
| Staging CD Role | staging | Staging 배포 |
| FE Prod CD Role | prod | Prod FE |
| BE Prod CD Role | prod | Prod BE |
| AI Prod CD Role | prod | Prod AI |
| Role | 관리 State | 권한 |
|---|---|---|
| Terraform Plan Role | bootstrap | Plan |
| Terraform Dev Role | bootstrap | Dev 변경 |
| Terraform Staging Role | bootstrap | Staging 변경 |
| Terraform Prod Role | bootstrap | Prod 변경 및 승인된 Shared 변경 |
각 Role은 해당 환경의 State와 AWS 리소스에만 접근하도록 제한한다.
GitHub Actions는 Access Key 대신 OIDC를 사용한다.
환경별 GitHub Environment를 제한한다.
| Role | Environment |
|---|---|
| Terraform Plan | terraform-plan |
| Terraform Dev | dev |
| Terraform Staging | staging |
| Terraform Prod | production |
Trust Policy에는 다음 조건을 사용한다.
- GitHub Repository
- aud
- sub
- GitHub Environment
Staging과 Prod는 승인된 Workflow에서만 변경할 수 있도록 한다.
Schema Migration은 테이블·컬럼·인덱스 등 DB 구조를 변경하는 작업이다.
Rolling Deployment 중에는 구버전과 신버전이 동시에 실행될 수 있으므로 호환성을 고려한다.
새 Schema 추가
│
▼
구버전·신버전 호환 코드 배포
│
▼
데이터 이전
│
▼
기존 Schema 제거
Data Migration은 V1 DB 데이터를 V2 RDS로 이전하는 작업이다.
V1 MySQL / PostgreSQL
│
▼
Migration Task
│
▼
Staging RDS
│
▼
Migration 검증
│
▼
Prod 이전 절차 확정
- Row Count
- PK / FK
- Index
- Null
- 데이터 타입
- 문자셋
- Collation
- pgvector
- 이전 시간
- 데이터 정합성
- 실패 복구
- 변경분 동기화
Dev는 운영 데이터 전체를 복사하는 환경이 아니다.
기능 검증에 필요한 테스트 데이터만 사용한다.
V1에서 필요한 상품 데이터 및 Catalog 데이터는 별도로 복사할 수 있다.
사용자 개인정보가 포함된 테이블은 원칙적으로 복사하지 않는다.
V1 상품 데이터 / Catalog
│
▼
필요 데이터 선별
│
▼
Dev RDS
데이터 복사 시 임시로 허용한 네트워크 접근은 작업 후 제거한다.
Staging에서는 Prod와 동일한 인프라 환경에서 V1 → V2 데이터 이전을 검증한다.
Dev에서 수행한 단순 기능 테스트와 달리 실제 운영 전환에 필요한 절차를 확인한다.
Terraform Apply
│
▼
Prod 동등 인프라 생성
│
├── ALB
├── ECS
├── Service Connect
├── RDS
├── ElastiCache
└── AI Catalog
V1 DB
│
▼
Migration Task
│
▼
Staging RDS
Staging에는 검증용 복제 데이터를 사용한다.
운영 데이터에 대한 직접 변경을 방지한다.
Migration 이후 Staging ECS에서 다음을 확인한다.
- FE 페이지 접근
- BE API 정상 동작
- AI Service 호출
- Redis 연결
- DB 조회 및 쓰기
- AI Catalog 처리
- 사용자 주요 기능
- 배포 및 Rollback
검증 완료
│
▼
검증 결과 기록
│
▼
필요한 Snapshot 보존
│
▼
Terraform Destroy 승인
│
▼
Staging 리소스 삭제
1. V2 Prod 인프라 구축
│
▼
2. v2.needu.gift 사전 검증
│
▼
3. Staging 전체 인프라 생성
│
▼
4. Staging DB Migration 리허설
│
▼
5. Staging 서비스 검증
│
▼
6. V1 → Prod DB Migration
│
▼
7. Prod 최종 데이터 정합성 검증
│
▼
8. needu.gift DNS 전환
│
▼
9. V2 안정화
│
▼
10. V1 리소스 정리
V1 운영 중에도 데이터가 계속 변경될 수 있다.
따라서 최종 이전 시 다음 중 하나를 결정한다.
- 서비스 쓰기 중단
- 변경분 동기화
- CDC
선택한 절차를 Staging에서 먼저 검증한다.
- Route 53
- Backend API Base URL
- Kakao Redirect URI
- Cookie Domain
- CORS
- 외부 Callback URL
DNS 복귀와 별도로 DB 데이터 복구 절차를 준비한다.
Prod 전환 후 발생한 신규 데이터를 어떻게 처리할지도 사전에 결정한다.
- AWS Console 변경 사항도 Terraform 코드에 반영한다.
- State별 리소스 소유권을 유지한다.
- 환경 간 IAM 접근을 제한한다.
- Terraform Plan을 확인한 후 적용한다.
- 자동 배포
- 테스트 데이터 사용
- 경량 리소스
- 필요 시 다중 Task 검증
- Prod 접근 제한
- Prod와 동일한 인프라 구성
- Prod 배포 후보 검증
- DB Migration 리허설
- 승인 기반 배포
- 필요 시 생성·삭제
- Snapshot 및 로그 보존
- Prod 데이터 변경 금지
- 승인 기반 배포
- RDS 삭제 보호
- 운영 데이터 백업
- CloudWatch Alarm
- Auto Scaling
- Rollback 절차
- 최소 권한 IAM
-
Terraform Data Sources https://developer.hashicorp.com/terraform/language/data-sources
-
Terraform S3 Backend https://developer.hashicorp.com/terraform/language/backend/s3
-
Terraform Lifecycle https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle
-
Terraform Modules https://developer.hashicorp.com/terraform/language/modules
-
ECS Service Connect https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-connect.html
-
ECS Auto Scaling https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-auto-scaling.html
-
Amazon RDS https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Welcome.html
-
Amazon ElastiCache https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/WhatIs.html
-
Parameter Store https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html
NeedU V2는 Terraform으로 총 5개의 State를 관리한다.
| State | 목적 | 특징 |
|---|---|---|
| bootstrap | Terraform 운영 기반 | State Bucket, Terraform Role |
| shared | 공용 리소스 | ECR, CI Role, 공통 Parameter |
| dev | 개발·통합 테스트 | 경량 인프라, 자동 배포 |
| staging | 운영 배포·Migration 검증 | Prod 동등 인프라, 수동 생성·삭제 |
| prod | 실제 사용자 서비스 | 운영 사양, 데이터 보호 |
- Dev는 개발 및 통합 테스트를 위한 경량 환경이다.
- Staging은 Prod와 동일한 인프라 구성에서 배포와 DB Migration을 검증한다.
- Prod는 실제 사용자 서비스를 위한 운영 환경이다.
- Dev와 Prod는 동일한 애플리케이션 코드베이스를 사용하지만 리소스 사양과 운영 정책이 다르다.
- Staging과 Prod는 인프라 구성 및 주요 설정을 동일하게 유지한다.
- 환경별 데이터, 도메인, IAM, Parameter Store, Security Group은 분리한다.
- Terraform은 인프라 구조를 관리하고 GitHub Actions는 애플리케이션 배포를 관리한다.