Current Setup Analysis
📋 에러 메시지 분석
섹션 제목: “📋 에러 메시지 분석”에러 1: KV Namespace 부재
섹션 제목: “에러 1: KV Namespace 부재”KV namespace 'DOMAIN_KV' not found for staging environment발생 위치: verify-resources.sh 실행 중
근본 원인:
- 프로비저닝 실패:
provision_kv_namespace함수가 KV를 생성하지 못함 - ID 추출 실패: 생성은 성공했지만 ID 추출 로직이 실패
- 환경 불일치:
wrangler.jsonc에staging_kv_namespace_idplaceholder가 남아있음
에러 2: tmate Action 파라미터 오류
섹션 제목: “에러 2: tmate Action 파라미터 오류”Unexpected input(s) 'limit-access-to-this-repository', 'timeout-minutes'발생 위치: deploy.yml의 모든 tmate action
근본 원인: mxschmitt/action-tmate@v3에서 지원하지 않는 파라미터 사용
에러 3: 실행 시간 과다
섹션 제목: “에러 3: 실행 시간 과다”증상: Provision 단계에서 시간이 너무 오래 걸림
근본 원인:
- 순차적 리소스 생성 (D1 → KV → Queue)
- 재시도 로직으로 인한 추가 지연
- 각 리소스마다 여러 API 호출
🔍 현재 설정 확인
섹션 제목: “🔍 현재 설정 확인”1. wrangler.jsonc 설정
섹션 제목: “1. wrangler.jsonc 설정”Staging 환경 KV 설정
섹션 제목: “Staging 환경 KV 설정”"kv_namespaces": [ { "binding": "DOMAIN_KV", "id": "staging_kv_namespace_id", // ❌ Placeholder "preview_id": "staging_kv_preview_id" }]문제점:
- ✅ D1 Database: 실제 ID 존재 (
220e9fe1-9401-4297-8cf2-0eeb9ca39ee8) - ❌ KV Namespace: Placeholder만 존재 (
staging_kv_namespace_id) - ❌ 실제 KV Namespace ID가 설정되지 않음
2. 프로비저닝 로직 분석
섹션 제목: “2. 프로비저닝 로직 분석”provision_kv_namespace 함수 흐름
섹션 제목: “provision_kv_namespace 함수 흐름”1. KV Namespace 리스트 조회 └─> wrangler kv namespace list --env staging
2. DOMAIN_KV 검색 └─> get_kv_id_from_list() 함수로 ID 추출
3. ID가 없으면 생성 시도 └─> create_kv_namespace() 함수 호출
4. 생성 후 ID 추출 └─> grep으로 32자 hex ID 추출
5. wrangler.jsonc 업데이트 └─> update_wrangler_config() 함수 호출실패 지점 추정:
- Step 1: 리스트 조회 실패 (인증 문제?)
- Step 2: ID 추출 실패 (파싱 로직 문제?)
- Step 3: 생성 실패 (권한 문제?)
- Step 4: ID 추출 실패 (출력 형식 문제?)
3. 로컬 환경 vs CI 환경
섹션 제목: “3. 로컬 환경 vs CI 환경”로컬 환경 (dev)
섹션 제목: “로컬 환경 (dev)”# 로컬에서 사용pnpm dev:local
# wrangler.jsonc의 dev 환경"kv_namespaces": [ { "binding": "DOMAIN_KV", "id": "dev_kv_namespace_id", // Placeholder "preview_id": "dev_kv_preview_id" }]특징:
- 로컬 모드에서는 placeholder로도 작동 가능
- 실제 리소스는 로컬 시뮬레이션
CI 환경 (staging/production)
섹션 제목: “CI 환경 (staging/production)”# CI에서 사용wrangler deploy --env staging
# wrangler.jsonc의 staging 환경"kv_namespaces": [ { "binding": "DOMAIN_KV", "id": "staging_kv_namespace_id", // ❌ Placeholder "preview_id": "staging_kv_preview_id" }]문제점:
- 실제 Cloudflare 리소스 필요
- Placeholder로는 작동하지 않음
- 프로비저닝이 실패하면 배포 불가
🎯 문제점 진단
섹션 제목: “🎯 문제점 진단”Critical 문제
섹션 제목: “Critical 문제”1. KV Namespace 프로비저닝 실패
섹션 제목: “1. KV Namespace 프로비저닝 실패”증상: verify-resources.sh에서 KV 부재 감지
가능한 원인:
원인 A: 생성 실패
- API 토큰 권한 부족 (
KV:Edit권한 없음) - 네트워크 문제
- Cloudflare API 일시적 장애
원인 B: ID 추출 실패
wrangler kv namespace create출력 형식 변경- grep 패턴이 실제 출력과 불일치
- 생성 후 전파 시간 부족
원인 C: 환경 불일치
--env staging플래그가 올바르게 작동하지 않음- 다른 계정의 리소스를 확인
확인 방법:
# 수동으로 생성 시도wrangler kv namespace create DOMAIN_KV --env staging
# 출력 확인# 예상 출력 형식:# { binding = "DOMAIN_KV", id = "abc123...", preview_id = "def456..." }2. tmate Action 파라미터 오류
섹션 제목: “2. tmate Action 파라미터 오류”현재 코드:
uses: mxschmitt/action-tmate@v3with: limit-access-to-this-repository: true # ❌ timeout-minutes: 30 # ❌올바른 파라미터:
uses: mxschmitt/action-tmate@v3with: limit-access-to-actor: true # ✅ connect-timeout-seconds: 1800 # ✅ (30분 = 1800초)High Priority 문제
섹션 제목: “High Priority 문제”3. 프로비저닝 시간 과다
섹션 제목: “3. 프로비저닝 시간 과다”현재 흐름:
D1 프로비저닝 (30초) ↓KV 프로비저닝 (30초) ↓Queue 프로비저닝 (60초) ↓총 시간: 120초+개선 방안: 병렬 처리
D1 프로비저닝 (30초) ┐KV 프로비저닝 (30초) ├→ 병렬 실행 ┘Queue 프로비저닝 (60초) ← 순차 (의존성)총 시간: 90초 (25% 단축)4. Cloudflare 가이드 미준수
섹션 제목: “4. Cloudflare 가이드 미준수”미준수 사항:
- ❌ 로컬 시뮬레이션:
wrangler dev --remote미사용 - ❌ 실시간 로그:
wrangler tail통합 없음 - ❌ 롤백 메커니즘: 없음
- ❌ KISS 원칙: 복잡한 프로비저닝 로직
🔧 개선 기획안 상세
섹션 제목: “🔧 개선 기획안 상세”Phase 1: 즉시 수정 (Critical) - 1시간
섹션 제목: “Phase 1: 즉시 수정 (Critical) - 1시간”1.1 tmate Action 파라미터 수정
섹션 제목: “1.1 tmate Action 파라미터 수정”파일: .github/workflows/deploy.yml
변경 전:
- name: Setup tmate session (on failure) if: failure() uses: mxschmitt/action-tmate@v3 with: limit-access-to-this-repository: true timeout-minutes: 30변경 후:
- name: Setup tmate session (on failure) if: failure() uses: mxschmitt/action-tmate@v3 with: limit-access-to-actor: true connect-timeout-seconds: 1800위치: 4곳 (validate, provision, deploy, deploy-production)
1.2 KV Namespace 생성 로직 개선
섹션 제목: “1.2 KV Namespace 생성 로직 개선”파일: .github/scripts/lib/cloudflare-resources.sh
개선 사항:
A. 생성 후 즉시 검증
create_kv_namespace() { local env="$1" local namespace="DOMAIN_KV"
# 생성 시도 local create_output create_output=$(npx wrangler kv namespace create "$namespace" --env "$env" 2>&1)
# 생성 성공 확인 if echo "$create_output" | grep -qiE "created|success|id\s*="; then # 생성 전파 대기 (Cloudflare API 전파 시간) echo "⏳ Waiting for namespace propagation..." >&2 sleep 3
# 즉시 리스트하여 ID 추출 local kv_list local retry_count=0 local max_retries=5
while [[ $retry_count -lt $max_retries ]]; do kv_list=$(npx wrangler kv namespace list --env "$env" 2>&1) local kv_id kv_id=$(get_kv_id_from_list "$env" "$kv_list")
if [[ -n "$kv_id" ]] && [[ ${#kv_id} -eq 32 ]]; then echo "✅ KV namespace created and verified: $kv_id" >&2 echo "$kv_id" return 0 fi
retry_count=$((retry_count + 1)) echo "⏳ Retry $retry_count/$max_retries..." >&2 sleep 2 done
echo "❌ Failed to extract KV namespace ID after creation" >&2 echo "Create output: $create_output" >&2 echo "List output: $kv_list" >&2 return 1 fi
# 생성 실패 echo "❌ Failed to create KV namespace" >&2 echo "Output: $create_output" >&2 return 1}B. 에러 메시지 개선
# 더 명확한 에러 메시지if [[ -z "$kv_id" ]]; then echo "::error::KV namespace '${KV_NAMESPACE}' not found for ${ENV} environment" >&2 echo "::error::Available namespaces:" >&2 echo "$KV_LIST" | head -20 >&2 echo "::error::To create: wrangler kv namespace create ${KV_NAMESPACE} --env ${ENV}" >&2 exit 1fi1.3 wrangler.jsonc Placeholder 검증 강화
섹션 제목: “1.3 wrangler.jsonc Placeholder 검증 강화”파일: .github/scripts/lib/wrangler-config.sh
개선: Placeholder가 남아있으면 명확한 에러
validate_wrangler_config() { local env="$1"
# Placeholder 확인 if grep -q "\"id\": \"${env}_kv_namespace_id\"" wrangler.jsonc; then echo "::error::KV namespace ID is still a placeholder for ${env}" >&2 echo "::error::Run provision-resources.sh to update it" >&2 return 1 fi
# ... 기존 검증}Phase 2: 성능 개선 (High) - 2시간
섹션 제목: “Phase 2: 성능 개선 (High) - 2시간”2.1 병렬 리소스 프로비저닝
섹션 제목: “2.1 병렬 리소스 프로비저닝”파일: .github/scripts/steps/provision-resources.sh
개선 후:
# D1과 KV를 병렬로 프로비저닝provision_resources_parallel() { local env="$1"
echo "🚀 Provisioning resources in parallel..." >&2
# D1 프로비저닝 (백그라운드) provision_d1_database "$env" > /tmp/d1-output.txt 2>&1 & local d1_pid=$!
# KV 프로비저닝 (백그라운드) provision_kv_namespace "$env" > /tmp/kv-output.txt 2>&1 & local kv_pid=$!
# 대기 및 결과 확인 local d1_exit=0 local kv_exit=0
wait $d1_pid || d1_exit=$? wait $kv_pid || kv_exit=$?
# 결과 확인 if [[ $d1_exit -ne 0 ]]; then echo "❌ D1 provisioning failed" >&2 cat /tmp/d1-output.txt >&2 return 1 fi
if [[ $kv_exit -ne 0 ]]; then echo "❌ KV provisioning failed" >&2 cat /tmp/kv-output.txt >&2 return 1 fi
# ID 추출 local d1_id d1_id=$(cat /tmp/d1-output.txt | tail -1)
local kv_id kv_id=$(cat /tmp/kv-output.txt | tail -1)
# wrangler.jsonc 업데이트 update_wrangler_config "$env" "$d1_id" "$kv_id"
# Queue는 순차적으로 (의존성 없음이지만 안전을 위해) provision_queues "$env"}예상 시간 절약: 120초 → 90초 (25% 단축)
Phase 3: Cloudflare 가이드 준수 (Medium) - 3시간
섹션 제목: “Phase 3: Cloudflare 가이드 준수 (Medium) - 3시간”3.1 로컬 시뮬레이션 강화
섹션 제목: “3.1 로컬 시뮬레이션 강화”파일: package.json
추가 스크립트:
{ "scripts": { "dev:remote:staging": "wrangler dev --remote --env staging", "dev:remote:production": "wrangler dev --remote --env production" }}사용법:
# Staging 환경과 동일한 리소스로 로컬 테스트pnpm dev:remote:staging
# Production 환경과 동일한 리소스로 로컬 테스트pnpm dev:remote:production장점:
- ✅ 로컬에서 실제 Cloudflare 리소스 사용
- ✅ CI 환경과 100% 동일한 환경 재현
- ✅ 배포 전 문제 발견 가능
3.2 실시간 로그 모니터링 통합
섹션 제목: “3.2 실시간 로그 모니터링 통합”파일: .github/workflows/deploy.yml
배포 후 로그 확인 추가:
- name: Post-deployment Log Check if: success() run: | echo "📊 Checking deployment logs..." timeout 30 wrangler tail --env "${{ steps.env.outputs.environment }}" --format pretty | head -50 || true env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}3.3 롤백 메커니즘 추가
섹션 제목: “3.3 롤백 메커니즘 추가”파일: scripts/rollback.sh (신규)
#!/usr/bin/env bash# Rollback to previous deployment
set -euxo pipefail
ENV="${1:-staging}"
echo "🔄 Rolling back ${ENV} environment..."
# 이전 배포 확인PREVIOUS=$(wrangler deployments list --env "$ENV" 2>&1 | grep -v "Version" | head -2 | tail -1 | awk '{print $1}')
if [[ -z "$PREVIOUS" ]]; then echo "❌ No previous deployment found" exit 1fi
echo "📋 Previous version: $PREVIOUS"
# 롤백 실행wrangler rollback --env "$ENV" --message "Rollback to $PREVIOUS via script"
echo "✅ Rolled back to version: $PREVIOUS"package.json에 추가:
{ "scripts": { "rollback:staging": "bash scripts/rollback.sh staging", "rollback:production": "bash scripts/rollback.sh production" }}Phase 4: KISS 원칙 적용 (Simplification) - 2시간
섹션 제목: “Phase 4: KISS 원칙 적용 (Simplification) - 2시간”4.1 환경별 리소스 사전 생성 스크립트
섹션 제목: “4.1 환경별 리소스 사전 생성 스크립트”파일: scripts/setup-cloudflare-resources.sh (신규)
#!/usr/bin/env bash# One-time setup: Create all Cloudflare resources for all environments# Run this once manually, then CI only verifies
set -euxo pipefail
ENVIRONMENTS=("dev" "staging" "production")
echo "🔧 Setting up Cloudflare resources for all environments..."echo "⚠️ This script should be run ONCE manually"echo ""
for env in "${ENVIRONMENTS[@]}"; do echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "Environment: $env" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# D1 Database echo "🗄️ D1 Database..." wrangler d1 create "newsfork-metadata-${env}" 2>&1 | grep -v "already exists" || echo " (already exists)"
# KV Namespace echo "🔑 KV Namespace..." wrangler kv namespace create DOMAIN_KV --env "$env" 2>&1 | grep -v "already exists" || echo " (already exists)"
# Queues echo "📬 Queues..." for queue in research contract liveness seed domain; do wrangler queues create "newsfork-${queue}-${env}" 2>&1 | grep -v "already exists" || echo " (already exists)" done
# DLQ echo "📮 Dead Letter Queues..." wrangler queues create "newsfork-dlq-${env}" 2>&1 | grep -v "already exists" || echo " (already exists)" wrangler queues create "newsfork-seed-dlq-${env}" 2>&1 | grep -v "already exists" || echo " (already exists)" wrangler queues create "newsfork-domain-dlq-${env}" 2>&1 | grep -v "already exists" || echo " (already exists)"
echo ""done
echo "✅ Resource setup completed"echo ""echo "📝 Next steps:"echo " 1. Update wrangler.jsonc with actual resource IDs"echo " 2. Run: pnpm run provision:update-config"장점:
- ✅ 한 번만 실행
- ✅ CI에서는 검증만 수행 (빠름)
- ✅ KISS 원칙 준수
4.2 프로비저닝 로직 단순화
섹션 제목: “4.2 프로비저닝 로직 단순화”현재: 복잡한 재시도 및 에러 처리
개선: 단순한 “존재 확인 → 없으면 생성 → 검증”
# 단순화된 프로비저닝provision_resource_simple() { local resource_type="$1" # "d1", "kv", "queue" local resource_name="$2" local env="$3"
# 존재 확인 if resource_exists "$resource_type" "$resource_name" "$env"; then echo "✅ $resource_name already exists" return 0 fi
# 생성 echo "🔨 Creating $resource_name..." if create_resource "$resource_type" "$resource_name" "$env"; then echo "✅ $resource_name created" return 0 else echo "❌ Failed to create $resource_name" return 1 fi}📊 개선 효과 예상
섹션 제목: “📊 개선 효과 예상”Before (현재)
섹션 제목: “Before (현재)”❌ KV Namespace 부재 → 배포 실패❌ tmate Action 오류 → 디버깅 불가❌ 프로비저닝 시간: 120초+❌ 로컬-CI 환경 불일치❌ 롤백 불가After (개선 후)
섹션 제목: “After (개선 후)”✅ KV Namespace 자동 생성 및 검증✅ tmate Action 정상 동작✅ 프로비저닝 시간: 90초 (25% 단축)✅ 로컬-CI 환경 일치 (wrangler dev --remote)✅ 롤백 메커니즘 추가✅ 실시간 로그 모니터링✅ KISS 원칙 준수🎯 구현 우선순위
섹션 제목: “🎯 구현 우선순위”Phase 1: 즉시 수정 (Critical) - 1시간
섹션 제목: “Phase 1: 즉시 수정 (Critical) - 1시간”- ✅ tmate Action 파라미터 수정 (4곳)
- ✅ KV Namespace 생성 로직 개선
- ✅ 에러 메시지 명확화
Phase 2: 성능 개선 (High) - 2시간
섹션 제목: “Phase 2: 성능 개선 (High) - 2시간”- ✅ 병렬 리소스 프로비저닝
- ✅ 리소스 존재 확인 최적화
Phase 3: 가이드 준수 (Medium) - 3시간
섹션 제목: “Phase 3: 가이드 준수 (Medium) - 3시간”- ✅ 로컬 시뮬레이션 강화 (
wrangler dev --remote) - ✅ 실시간 로그 모니터링 통합
- ✅ 롤백 메커니즘 추가
Phase 4: 단순화 (Low) - 2시간
섹션 제목: “Phase 4: 단순화 (Low) - 2시간”- ✅ 프로비저닝 로직 단순화
- ✅ 환경별 리소스 사전 생성 스크립트
📝 체크리스트
섹션 제목: “📝 체크리스트”즉시 수정 필요
섹션 제목: “즉시 수정 필요”- tmate Action 파라미터 수정 (4곳)
- KV Namespace 생성 로직 개선
- 에러 메시지 명확화
- Placeholder 검증 강화
성능 개선
섹션 제목: “성능 개선”- 병렬 리소스 프로비저닝
- 리소스 존재 확인 최적화
Cloudflare 가이드 준수
섹션 제목: “Cloudflare 가이드 준수”-
wrangler dev --remote스크립트 추가 - 실시간 로그 모니터링 통합
- 롤백 메커니즘 추가
단순화
섹션 제목: “단순화”- 프로비저닝 로직 단순화
- 환경별 리소스 사전 생성 스크립트
작성 일시: 2026-01-28
우선순위: Critical
예상 소요 시간: 8시간 (단계별 구현)