CI CD 파이프라인 재설계 - 100-hours-a-week/KTB4-4th-wiki GitHub Wiki
Need U V2에서는 ECS 기반 인프라 전환에 맞춰 애플리케이션 CI/CD 구조를 재구성한다.
V1에서는 main 기준 이미지 빌드와 EC2 + SSM 기반 배포를 사용했지만, V2에서는 Dev 환경을 추가하고 ECS Rolling Update 기반으로 배포한다.
CI/CD의 핵심 목표는 다음과 같다.
- Dev에서 검증한 동일한 Docker Image를 Prod에 배포한다.
- CI와 CD의 역할 및 AWS 권한을 분리한다.
- Dev 환경은 항상
dev브랜치의 최신 상태를 유지한다. - Production 배포는 승인 절차를 거친다.
- 배포 성공 여부를 명확하게 기록한다.
- Dev / Prod / Rollback이 동일한 배포 절차를 사용한다.
- 환경별 설정값은 Docker Image가 아닌 런타임에 주입한다.
Build Once, Deploy Many
Docker Image는 dev에 Merge될 때 한 번만 생성한다.
feature/*
│
▼
PR → dev
│
▼
CI
│
├── Test
├── Build
└── Docker Image Build
│
▼
ECR
<Git Commit SHA>
Dev에서 검증한 Image를 Production에서도 그대로 사용한다.
ECR
└── need-u/<service>:<SHA>
│
├── Dev
│
└── Prod
Prod 배포 과정에서는 Docker Image를 다시 Build하지 않는다.
dev Branch에 Merge되면 다음 과정이 자동으로 수행된다.
dev Push
│
▼
CI
│
├── Test
├── Docker Build
└── ECR Push
│
▼
Dev Deploy
│
▼
Dev ECS
따라서 Dev 환경은 항상 dev Branch의 최신 상태를 유지한다.
Production 배포는 dev → main Merge를 기준으로 시작한다.
Dev 검증 완료
│
▼
dev → main PR
│
▼
배포 판단 Review
│
▼
Merge
│
▼
Production 승인
│
▼
배포 전 검증
│
▼
Prod ECS 배포
│
▼
prod- Tag 생성
dev → main PR은 단순 코드 Merge가 아니라 Production 배포 여부를 판단하는 단계로 사용한다.
| 기록 | 의미 |
|---|---|
main |
Production에 배포하기로 결정한 코드 |
prod- Tag |
Production에 실제로 배포가 성공한 코드 |
Production 배포가 성공한 경우에만 다음 형식의 Git Tag를 생성한다.
prod-YYYYMMDD-N
prod- Tag는 Production에 실제 배포된 Dev Commit SHA를 가리킨다. Merge Commit 자체가 아니라 Docker Image에 사용한 SHA를 기준으로 기록한다.
Rollback은 prod- Tag가 존재하는 SHA만 허용한다.
Application PR 검증 과정에서는 AWS 권한을 사용하지 않는다.
Terraform PR은 Plan을 위해 AWS를 조회해야 하므로, Cloud 팀 승인 후 읽기 전용 Plan Role로만 접근한다.
AWS 권한은 실제 Image Push, Deployment, Plan, Apply가 필요한 Job에만 부여한다.
Application PR
└── AWS 권한 없음
Terraform PR
└── Plan Role (Cloud 팀 승인 후, Read Only)
dev Push
├── CI Role
└── Dev CD Role
Production
└── Prod CD Role
Terraform Apply
├── Dev Role (dev)
└── Prod Role (prod, shared)
| 단계 | 자동 실행 | 사람이 수행 |
|---|---|---|
feature → dev PR |
테스트, 통합 테스트, Docker Build 검사 | Code Review |
dev Merge |
Image Build → ECR Push → Dev 자동 배포 | Dev 검증 |
| Dev 검증 | - | 기능 및 서비스 동작 확인 |
dev → main PR |
기본 CI 검사 | Prod 배포 판단 |
dev → main Merge |
배포 SHA 추출 | Production 승인 |
| 승인 완료 | SHA 검증 → Prod 배포 | - |
| 배포 성공 |
prod- Tag 생성 |
- |
전체 흐름은 다음과 같다.
feature/*
│
▼
PR → dev
│
├── Unit Test
├── Integration Test
├── Lint / Format
└── Docker Build Check
│
▼
dev Merge
│
├── Docker Build
├── ECR Push
└── Dev 자동 배포
│
▼
Dev 검증
│
▼
dev → main PR
│
▼
Merge
│
▼
Production 승인
│
├── Dev 실행 SHA 확인
├── ECR Image 확인
└── Prod Deploy
│
▼
prod- Tag
Dev 검증이 진행되는 동안에는 새로운 변경사항을 dev에 Merge하지 않는다.
Frontend
└── .github/workflows/
├── ci.yml
├── deploy.yml
├── prod-deploy.yml
└── rollback.yml
Backend
└── .github/workflows/
├── ci.yml
├── deploy.yml
├── prod-deploy.yml
└── rollback.yml
AI
└── .github/workflows/
├── ci.yml
├── deploy.yml
├── prod-deploy.yml
├── rollback.yml
├── catalog-sync.yml
└── catalog-import.yml
Cloud
└── .github/workflows/
├── terraform-pr.yml # fmt, validate, plan (shared / dev / prod)
└── terraform-apply.yml # shared apply, dev apply → prod apply
bootstrap/은 Terraform Role 자체를 만들기 때문에 파이프라인에 포함하지 않고 Cloud 팀이 로컬에서 적용한다.
deploy.yml은 재사용 Workflow로 사용한다. Dev, Prod, Rollback 모두 동일한 배포 절차를 사용하며 환경과 Image SHA만 다르게 전달한다.
| Environment | 용도 | 승인 |
|---|---|---|
dev |
Dev 배포 | 없음 |
production |
Prod 배포 및 Prod AI Catalog 실행 | Cloud 팀 |
| Environment | 용도 | 승인 |
|---|---|---|
terraform-plan |
Terraform Plan (shared / dev / prod) | Cloud 팀 |
dev |
Dev Terraform Apply | 없음 |
production |
Shared 및 Prod Terraform Apply | Cloud 팀 |
Shared는 Dev·Prod 모두에 영향을 주므로 production Environment를 사용해 Prod와 같은 승인을 거친다.
승인이 필요한 Environment를 사용하는 Job은 승인이 완료되기 전까지 실행되지 않는다.
| 변수 | 값 |
|---|---|
AWS_CI_ROLE_ARN |
V2 CI Role ARN |
AWS_ECR_REPOSITORY_URI |
<account>.dkr.ecr.ap-northeast-2.amazonaws.com/need-u/<service> |
| 변수 | Dev | Production |
|---|---|---|
AWS_CD_ROLE_ARN |
Dev CD Role | 서비스별 Prod CD Role |
SERVICE_DOMAIN |
dev.needu.gift |
v2.needu.gift → 전환 후 needu.gift
|
AI Repository에는 다음 값도 둔다.
| 변수 | 용도 |
|---|---|
AWS_TASK_SUBNET_IDS |
Catalog Task 실행 Subnet |
AWS_CATALOG_SYNC_SG_ID |
Catalog Sync Security Group |
AWS_CATALOG_IMPORT_SG_ID |
Catalog Import Security Group |
Subnet과 Security Group ID는 Terraform Output 값을 사용한다.
| 변수 | Environment | 값 |
|---|---|---|
AWS_TERRAFORM_PLAN_ROLE_ARN |
terraform-plan |
Terraform Plan Role |
AWS_TERRAFORM_ROLE_ARN |
dev |
Terraform Dev Role |
AWS_TERRAFORM_ROLE_ARN |
production |
Terraform Prod Role (Shared 포함) |
feature/*
│
▼
dev
│
▼
main
dev와 main은 Branch Protection을 적용한다.
- PR을 통한 Merge
- 필수 CI 검사 통과
- Review 완료 후 Merge
dev → main은 Merge Commit 방식만 허용한다. Production Workflow가 HEAD^2에서 Dev SHA를 추출하므로 Squash Merge와 Rebase Merge는 허용하지 않는다.
dev → main Merge는 Merge Commit 방식을 사용한다.
Production Workflow는 Merge Commit의 두 번째 Parent에서 Dev에서 검증한 SHA를 추출한다.
main Merge Commit
├── Parent 1 = 기존 main
└── Parent 2 = 검증 완료된 dev SHA
따라서 Production에 배포할 Image는 Parent 2의 SHA를 사용한다.
| 서비스 |
feature → dev PR |
dev → main PR |
dev Push |
|---|---|---|---|
| Backend | Unit Test, Build, Integration Test, Docker Build Check | Unit Test, Build | Image Build → ECR → Dev Deploy |
| Frontend | Format, Type Check, Lint, Build, Docker Build Check | Format, Type Check, Lint, Build | Sentry 공통값 로드 → Image Build → ECR → Dev Deploy |
| AI | Dependency Sync, Unit Test, Ruff, Docker Build Check | Dependency Sync, Unit Test, Ruff | Image Build → ECR → Dev Deploy |
Docker Build Check는 feature → dev PR에서 수행한다.
dev → main PR에서는 이미 Dev에서 실제 Image가 Build되고 배포되었으므로 다시 수행하지 않는다.
PR
├── Unit Test
├── Build
│
└── feature → dev인 경우
├── MySQL Integration Test
└── Docker Build Check
dev Push
├── Unit Test
├── Build
├── Docker Build
├── ECR Push
└── Dev Deploy
Integration Test에서는 MySQL 8.4 Service Container를 사용한다.
services:
mysql:
image: mysql:8.4
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: needu_test
MYSQL_USER: test
MYSQL_PASSWORD: test
Docker Image Tag는 Git Commit SHA를 사용한다.
need-u/backend:<github.sha>
npm ci
↓
Format Check
↓
Next.js Type Generation
↓
Type Check
↓
Lint
↓
Build
feature → dev PR에서는 추가로 Docker Build Check를 수행한다.
Frontend Image Build 시 환경별 Backend 주소를 넣지 않는다.
Docker Build
└── BACKEND_API_BASE_URL ×
ECS Runtime
└── BACKEND_API_BASE_URL ○
Docker Build 시 사용하는 값은 공통 Sentry 설정이다.
/needu/common/frontend-build/
├── NEXT_PUBLIC_SENTRY_DSN
├── SENTRY_ORG
├── SENTRY_PROJECT
└── SENTRY_AUTH_TOKEN
SENTRY_RELEASE는 Git SHA를 사용하고, SENTRY_AUTH_TOKEN은 Docker BuildKit Secret으로 전달한다.
uv sync --frozen --dev
│
▼
pytest tests/unit
│
▼
ruff check .
feature → dev PR에서는 Docker Build Check를 추가한다.
AI Runtime과 Catalog Sync / Import는 동일한 Image를 사용한다.
need-u/ai:<SHA>
│
├── AI Service
├── Catalog Sync
└── Catalog Import
배포 로직은 각 저장소의 deploy.yml에 정의한다.
입력값:
environment
image_tag
verify_dev_match
deploy.yml
│
├── Image SHA 형식 확인
├── Environment별 Resource 이름 결정
├── OIDC → AWS Role
├── ECR Image 존재 확인
│
├── Production인 경우
│ └── Dev 실행 SHA와 동일한지 확인
│
├── 현재 Task Definition 조회
├── Image만 새 SHA로 변경
├── 새 Task Definition Revision 등록
├── ECS Service Rolling Update
├── Service 안정화 대기
│
├── AI
│ └─ Catalog Sync / Import Task Definition도 같은 SHA로 갱신
│
└── Smoke Test
Terraform에서 Task Definition의 기본 구조를 관리하고, CD에서는 Image만 변경한다.
| 설정 | Frontend | Backend | AI |
|---|---|---|---|
| Service | frontend |
backend |
ai |
| Container | frontend |
backend |
ai |
| Catalog Task Definition 갱신 | — | — | Sync / Import |
| Smoke Test | / |
/api/<BE 지정 경로> |
외부 Smoke Test 없음 |
AI는 외부 ALB에 직접 노출되지 않기 때문에 Service 안정화와 Service Connect Metric을 통해 배포 상태를 확인한다.
Backend의 /actuator/health는 /api/* 경로에 포함되지 않으므로 외부 Smoke Test 주소로 사용하지 않는다.
서비스와 환경별로 GitHub Actions concurrency Group을 분리한다.
deploy-dev-frontend
deploy-dev-backend
deploy-dev-ai
deploy-production-frontend
deploy-production-backend
deploy-production-ai
동일 서비스에 동시에 여러 Deployment가 실행되는 것을 방지한다. 실행 중인 Deployment는 중단하지 않고 끝까지 진행한다.
main Push가 발생하면 prod-deploy.yml을 실행한다.
Merge Commit의 두 번째 Parent에서 검증된 Dev SHA를 가져온다.
git rev-parse HEAD^2
Merge Commit이 아니면 배포를 중단한다.
추출한 SHA를 deploy.yml에 전달한다.
environment = production
image_tag = Dev SHA
verify_dev_match = true
Production Environment 승인이 완료된 후 다음을 확인한다.
ECR에 해당 SHA Image 존재
+
현재 Dev에서 실행 중인 SHA == 배포 요청 SHA
둘 중 하나라도 일치하지 않으면 Production 배포를 중단한다.
Production 배포 Workflow는 Merge Commit에서 추출한 SHA를 고정해 사용한다. 승인 대기 중 Dev에 새로운 배포가 발생하면 현재 Dev 실행 SHA 검증이 실패하므로 Production 배포를 중단하고 다시 검증한다.
배포가 모두 성공하면 다음 Tag를 생성한다.
prod-YYYYMMDD-<run_number>
이 Tag는 실제 Production 배포에 성공한 버전을 나타낸다.
Rollback은 rollback.yml을 수동 실행한다.
입력:
image_tag = 되돌아갈 Git SHA
Rollback 전에 다음을 확인한다.
입력 SHA
│
├── 40자리 SHA 형식
├── prod- Tag 존재
└── ECR Image 존재
prod- Tag가 없는 SHA는 Production 배포 이력이 없으므로 Rollback 대상으로 허용하지 않는다.
Rollback 역시 기존 deploy.yml을 호출한다.
rollback.yml
│
▼
deploy.yml
│
▼
Production 승인
│
▼
ECS 배포
새 Task가 정상적으로 실행되지 않거나 Health Check에 실패한 경우 ECS Deployment Circuit Breaker가 이전 정상 Deployment로 되돌린다.
Deployment
│
▼
Task 실행 실패 / Health Check 실패
│
▼
Circuit Breaker
│
▼
자동 Rollback
ECS Deployment Circuit Breaker와 rollback = true를 활성화한다.
Backend는 ALB 5xx Metric을 기준으로 CloudWatch Alarm을 연결한다.
Backend 5xx 증가 → ECS Deployment Alarm → Deployment Rollback
CloudWatch Alarm만 생성해서는 자동 Rollback되지 않는다. ECS Service의 Deployment Alarm으로 연결하고 Rollback 옵션을 활성화한다.
AI는 ALB 뒤에 없으므로 Service Connect HTTP Metric(HTTPCode_Target_5XX_Count, RequestCount)을 ECS Deployment Alarm에 연결한다.
AI SSE 응답이 HTTP 200 이후 Streaming 과정에서 끊기는 문제는 5xx로 집계되지 않을 수 있으므로 운영자가 판단하여 수동 Rollback한다.
Terraform에서 CPU / Memory 등의 Task Definition 설정을 변경했지만 Image 자체는 바뀌지 않는 경우 같은 SHA를 재배포할 수 있다.
마지막 dev Push의 CI 실행에서 Deploy to Dev Job만 Re-run한다.
전체 Workflow를 다시 실행하지 않는다. ECR이 IMMUTABLE이므로 전체 Workflow를 재실행하면 같은 SHA Image Push 단계에서 실패할 수 있다.
현재 Production SHA를 rollback.yml에 입력한다. 현재 Production 버전에는 이미 prod- Tag가 존재하므로 검증을 통과한다.
배포 과정에서 AWS에 등록된 최신 Task Definition을 조회하므로 Terraform에서 변경한 설정이 반영된다.
[1] AWS
Catalog Sync
│
├── MySQL 상품 조회
├── PostgreSQL Catalog 동기화
└── S3 Input 생성
│
▼
[2] Local
AI 팀원 Mac
│
├── S3 Input Download
├── Local Model 설명 생성
└── S3 Output Upload
│
▼
[3] AWS
Catalog Import
│
├── S3 Output 조회
├── Upstage Embedding
└── PostgreSQL 저장
Dev에서 전체 과정을 먼저 검증한 후 Production에서 실행한다. Production 실행은 Cloud 팀 승인을 거친다.
catalog-sync.yml은 수동으로 실행하며, 사용자는 Environment(dev / production)를 선택한다.
job_id는 Workflow가 자동 생성한다.
YYYYMMDD-<github.run_number>
예: 20261007-145
Catalog Sync Workflow
│
├── job_id 생성
├── ECS RunTask
├── Task 종료 대기
├── Exit Code 확인
└── S3 Input 존재 확인
성공 조건:
Task Exit Code = 0
+
jobs/<job_id>/input/products.json 존재
ecs:RunTask 호출 성공만으로 Batch 성공으로 판단하지 않고 실제 Task 종료까지 기다린 뒤 Exit Code를 확인한다.
AI 팀원은 Catalog Sync 화면에 표시된 job_id를 사용한다.
JOB_ID=<catalog-sync Job ID>
BUCKET=<catalog-bucket>
aws s3 cp \
"s3://$BUCKET/jobs/$JOB_ID/input/products.json" \
./products.json
# Local Model로 설명 생성 → enriched-products.json
aws s3 cp \
./enriched-products.json \
"s3://$BUCKET/jobs/$JOB_ID/output/enriched-products.json"
Mac에서는 DB에 직접 접근하지 않고 Catalog S3에만 접근한다.
catalog-import.yml 역시 수동 Workflow로 실행한다.
입력값: environment, job_id
실행 전에 jobs/<job_id>/output/enriched-products.json 존재를 확인하고, 없으면 Import Task를 실행하지 않는다.
Catalog Import Workflow
│
├── job_id 검증
├── S3 Output 존재 확인
├── ECS RunTask
├── Task 종료 대기
└── Exit Code 확인
Task 내부에서는 다음을 수행한다.
S3 Output → Upstage Embedding → PostgreSQL + pgvector
Application CI/CD와 Terraform CI/CD는 분리한다.
Application Repository
└── Application Build / Deployment
Cloud Repository
└── AWS Infrastructure Plan / Apply
| State | 내용 | 적용 방법 |
|---|---|---|
bootstrap |
State Bucket, Terraform Role | Cloud 팀 로컬 (파이프라인 제외) |
shared |
ECR, CI Role, FE 공통 Parameter | 파이프라인 + Cloud 팀 승인 |
dev |
Dev 인프라 | 파이프라인 자동 |
prod |
Prod 인프라 | 파이프라인 + Cloud 팀 승인 |
적용 순서는 다음과 같다.
bootstrap → shared → dev → prod
(로컬) (승인) (자동) (Dev 검증 후 승인)
PR
│
├── terraform fmt
├── terraform validate
│
└── Terraform Plan (shared / dev / prod)
│
└── Cloud 팀 승인 → Read Only Plan Role
PR Review
│
▼
main Merge
│
├── shared 변경 → Shared Apply (승인)
│
└── dev / prod 변경
│
▼
Dev Apply
│
▼
Dev Infrastructure 검증
│
▼
Production 승인
│
▼
Prod Apply
PR에서는 실제 Infrastructure 변경을 수행하지 않는다.
먼저 AWS 권한 없이 다음을 실행한다.
terraform fmt
terraform validate
Plan은 terraform-plan Environment를 이용한다. Cloud 팀 승인 후 Read Only Plan Role을 Assume한다.
Terraform PR
│
├── fmt
├── validate
│
└── Plan
├── Shared
├── Dev
└── Prod
변경된 폴더에 따라 Plan 대상을 정한다.
| 변경된 폴더 | Plan 대상 |
|---|---|
environments/shared/ |
Shared |
environments/dev/, environments/prod/
|
Dev, Prod |
modules/ |
Shared, Dev, Prod 모두 |
bootstrap/ |
없음 (로컬 적용) |
Plan은 읽기 전용으로 실행하며, 동시 Apply가 실행되지 않는 조건에서만 State Lock을 생성하지 않는다.
-lock=false
environments/shared/가 변경된 경우 main Merge 후 Shared Apply를 실행한다.
main Merge (shared 변경)
│
▼
Production 승인 (Cloud 팀)
│
▼
Shared Plan → Shared Apply
- Shared는 Dev·Prod 모두에 영향을 주므로
productionEnvironment 승인을 거친다. 예를 들어 ECR Lifecycle Policy를 잘못 바꾸면 Prod Rollback에 필요한 Image가 삭제될 수 있다. - Shared는 변경이 드물어 별도 Role 없이 Terraform Prod Role로 적용한다.
environments/dev/, environments/prod/ 또는 Dev·Prod가 사용하는 모듈이 변경되면 Dev Apply를 자동 실행한다.
main Merge
│
▼
Dev Plan → Dev Apply
│
▼
Dev 검증
│
▼
Production 승인
│
▼
Prod Plan → Prod Apply
Production에서는 승인 직후 Plan을 다시 생성한 뒤 동일 Job 안에서 Apply한다. PR 당시의 Plan과 실제 Apply 시점의 상태가 달라질 수 있기 때문이다.
Shared와 Dev·Prod를 함께 바꿔야 하는 경우 Shared 변경을 별도 PR로 먼저 Merge·적용한 뒤 Dev·Prod 변경 PR을 올린다.
- Dev·Prod는 Shared 리소스(ECR 등)를 이름으로 찾아 읽으므로 Shared가 먼저 적용되어야 한다.
- 순서를 어기면 Dev Apply가 "리소스 없음" 오류로 중단될 뿐 기존 인프라는 변경되지 않는다. Shared 적용 후 다시 실행한다.
- Shared와 Dev·Prod가 함께 사용하는 모듈(
parameters/,iam-github-oidc/)을 바꾸는 경우에도 같은 순서를 따른다. - Shared 변경이 잦아지면 파이프라인에서 순서를 자동 보장하도록 바꾼다.
| Role | 사용 위치 | 범위 |
|---|---|---|
| CI Role |
dev Push |
ECR Push, FE Build Parameter 조회 |
| Dev CD Role | environment:dev |
Dev ECS 배포, Dev Catalog 실행 |
| FE Prod CD Role | FE production
|
Prod FE 배포 |
| BE Prod CD Role | BE production
|
Prod BE 배포 |
| AI Prod CD Role | AI production
|
Prod AI 배포 및 Catalog 실행 |
Prod CD Role은 Production 배포 전 SHA 검증을 위해 자신과 동일한 서비스의 Dev Resource에 대한 조회 권한만 추가로 가진다.
AI CD Role은 Catalog 실행 과정에서 S3 파일 존재 여부를 확인할 수 있는 읽기 권한을 가진다.
| Role | 사용 위치 | 범위 | 생성 위치 |
|---|---|---|---|
| Terraform Plan Role | terraform-plan |
Read Only (Shared·Dev·Prod State 읽기 포함) | bootstrap |
| Terraform Dev Role | dev |
Dev Infrastructure | bootstrap |
| Terraform Prod Role | production |
Prod Infrastructure + Shared 리소스 | bootstrap |
- Terraform Role은 파이프라인이 사용하는 Role이므로 파이프라인보다 먼저 존재해야 한다. 따라서
bootstrap에서 Cloud 팀이 로컬로 생성한다. -
bootstrapState Bucket에는 어떤 파이프라인 Role도 접근하지 않는다. - PR 신분에서는 Application / Terraform 어느 Role도 직접 Assume할 수 없다.
| 항목 | V1 | V2 |
|---|---|---|
| Image Build |
main Push |
dev Push |
| 주요 CI 검증 |
dev → main PR |
feature → dev PR |
| Dev Environment | 없음 | 자동 배포 |
| Prod 배포 | SHA 수동 입력 |
dev → main Merge에서 SHA 자동 결정 |
| 배포 대상 | SSM → EC2 Script | ECS Rolling Update |
| FE Build 설정 | Prod Frontend Parameter 전체 | 공통 Build Parameter만 |
| 성공 버전 기록 | EC2 Tag File |
prod- Git Tag |
| 자동 Rollback | Deployment Script | ECS Circuit Breaker + ECS Deployment Alarm |
| AWS 인증 | GitHub OIDC | 환경·역할별 GitHub OIDC |
| Infrastructure 관리 | Console | Terraform (bootstrap / shared / dev / prod) |
| 확인 항목 | 기대 결과 |
|---|---|
FE / BE / AI dev Merge |
Image 생성 → Dev 자동 배포 |
| Dev Smoke Test | 정상 응답 |
연속 dev Merge |
최신 Image가 Dev에서 실행 |
| Dev Deployment Job Re-run | 동일 SHA + 최신 Task Definition으로 재배포 |
| 확인 항목 | 기대 결과 |
|---|---|
dev → main Merge |
Production 승인 대기 |
| 승인 완료 | SHA 검증 후 Deployment |
| Deployment 성공 |
prod- Tag 생성 |
| Dev SHA와 다른 SHA | Deployment 중단 |
| Merge Commit이 아닌 Main Commit | Deployment 중단 |
| 확인 항목 | 기대 결과 |
|---|---|
prod- Tag 존재 SHA |
Rollback 가능 |
| Tag 없는 SHA | Rollback 거부 |
| Health Check 실패 | ECS 자동 Rollback |
| Backend 5xx 증가 | Alarm 기반 자동 Rollback |
| AI 5xx 증가 | Service Connect Alarm 기반 자동 Rollback |
| 확인 항목 | 기대 결과 |
|---|---|
| Dev Role → Prod Service 변경 | AWS에서 거부 |
| FE Prod Role → BE Prod 변경 | AWS에서 거부 |
| Application PR Workflow → AWS Login | AWS에서 거부 |
| Terraform Plan 승인 전 실행 | 승인 대기 |
| Terraform Dev Role → Shared·Prod 변경 | AWS에서 거부 |
파이프라인 Role → bootstrap State Bucket 접근 |
AWS에서 거부 |
| 확인 항목 | 기대 결과 |
|---|---|
| Shared 변경 PR Merge | Production 승인 후 Shared Apply |
| Dev·Prod 변경 PR Merge | Dev 자동 Apply → Prod 승인 대기 |
| Shared 적용 전 Dev가 Shared 리소스 참조 | Dev Apply 중단, 기존 인프라 변경 없음 |
modules/ 변경 PR |
Shared·Dev·Prod Plan 모두 표시 |
| 확인 항목 | 기대 결과 |
|---|---|
| Dev Sync → Local → Import | 정상 완료 |
| Sync Task | Exit Code 0 + Input 생성 |
| Output 없는 Import | 실행 전 실패 |
| Import Task | Exit Code 0 + PostgreSQL 저장 |
| Prod Catalog 실행 | Cloud 팀 승인 대기 |
| 확인 항목 | 기대 결과 |
|---|---|
| Dev Backend Task 2개 | Kakao 로그인 정상 |
| FE Image를 Dev / Prod 각각 실행 | 각 환경 Backend와 Sentry 환경 정상 분리 |
/api/v1/* 요청 |
ALB를 통해 Backend 정상 처리 |
GitHub
│
┌───────────────┴───────────────┐
│ │
Application Repositories Cloud Repository
FE / BE / AI Terraform
│ │
▼ ▼
CI Terraform PR
│ ├── fmt
│ ├── validate
│ └── plan (shared / dev / prod)
▼ │
Docker Image ▼
│ main Merge
▼ │
ECR (shared) ┌──────────┴──────────┐
│ ▼ ▼
┌────┴────┐ Shared Apply Dev Apply
│ │ (승인) │
▼ ▼ ▼
Dev Prod Prod Apply
│ │ (승인)
│ Approval
│ │
└─────────┘
bootstrap (Cloud 팀 로컬)
└── State Bucket, Terraform Role
AI 별도 운영 흐름
Catalog Sync → S3 Input → AI Team Mac → S3 Output → Catalog Import → PostgreSQL
- GitHub Reusable Workflows: https://docs.github.com/en/actions/using-workflows/reusing-workflows
- GitHub Concurrency: https://docs.github.com/en/actions/using-jobs/using-concurrency
- GitHub OIDC for AWS: https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-aws
- AWS ECS Deploy Task Definition Action: https://github.com/aws-actions/amazon-ecs-deploy-task-definition
- Amazon ECS CloudWatch Metrics: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/available-metrics.html
- Next.js Environment Variables: https://nextjs.org/docs/app/guides/environment-variables