Files
telegram-bot-workers/DEPLOYMENT_SUMMARY.md
kappa 4eb5bbd3d3 feat(security): API 키 보호, CORS 강화, Rate Limiting KV 전환
보안 개선:
- API 키 하드코딩 제거 (NAMECHEAP_API_KEY_INTERNAL)
- CORS 정책: * → hosting.anvil.it.com 제한
- /health 엔드포인트 DB 정보 노출 방지
- Rate Limiting 인메모리 Map → Cloudflare KV 전환
  - 분산 환경 일관성 보장
  - 재시작 후에도 유지
  - 자동 만료 (TTL)

문서:
- CLAUDE.md Security 섹션 추가
- KV Namespace 설정 가이드 추가
- 배포/마이그레이션 가이드 추가

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-19 15:20:14 +09:00

6.6 KiB

Rate Limiting KV Migration - 배포 요약

변경 사항

1. Rate Limiting 시스템 마이그레이션

  • 이전: 인메모리 Map (Worker 인스턴스별 독립)
  • 현재: Cloudflare KV (분산 환경 공유)

2. 해결된 문제

Workers 인스턴스 간 Rate Limit 데이터 공유 Worker 재시작 시에도 Rate Limit 상태 유지 분산 환경에서 일관된 Rate Limiting 동작 자동 만료 (KV TTL) - 메모리 효율성


수정된 파일

1. /Users/kaffa/telegram-bot-workers/wrangler.toml

[[kv_namespaces]]
binding = "RATE_LIMIT_KV"
id = "YOUR_KV_NAMESPACE_ID"  # 생성 후 실제 ID로 교체 필요

2. /Users/kaffa/telegram-bot-workers/src/types.ts

export interface Env {
  // ... 기존 필드들
  RATE_LIMIT_KV: KVNamespace;  // ✅ 추가
}

3. /Users/kaffa/telegram-bot-workers/src/security.ts

  • 인메모리 Map 제거 (rateLimitMap)
  • cleanupRateLimits() 함수 제거 (KV TTL로 자동 관리)
  • checkRateLimit() 함수 시그니처 변경:
    • 이전: checkRateLimit(userId: string): boolean
    • 현재: checkRateLimit(kv: KVNamespace, userId: string): Promise<boolean>

4. /Users/kaffa/telegram-bot-workers/src/index.ts

// 이전
if (!checkRateLimit(telegramUserId)) {
  // ...
}

// 현재
if (!(await checkRateLimit(env.RATE_LIMIT_KV, telegramUserId))) {
  // ...
}

5. /Users/kaffa/telegram-bot-workers/CLAUDE.md

  • Rate Limiting 섹션 업데이트 (KV 기반 설명 추가)
  • Configuration 섹션에 KV Namespaces 테이블 추가
  • Commands 섹션에 KV Namespace 생성 명령 추가

배포 전 필수 작업

Step 1: KV Namespace 생성

wrangler kv:namespace create RATE_LIMIT_KV

출력 예시:

⛅️ wrangler 3.x.x
-------------------
🌀 Creating namespace with title "telegram-summary-bot-RATE_LIMIT_KV"
✨ Success!
Add the following to your configuration file in your kv_namespaces array:
{ binding = "RATE_LIMIT_KV", id = "abc123..." }

Step 2: wrangler.toml 수정

출력된 id 값을 복사하여 wrangler.toml 22번 줄 수정:

id = "abc123def456ghi789jkl012mno345pq"  # ← 실제 ID로 변경

Step 3: TypeScript 컴파일 확인

npx tsc --noEmit

Step 4: 로컬 테스트

npm run dev

다른 터미널에서:

curl -X POST http://localhost:8787/webhook \
  -H "Content-Type: application/json" \
  -H "X-Telegram-Bot-Api-Secret-Token: test-secret" \
  -d '{"update_id":1,"message":{"message_id":1,"from":{"id":123,"is_bot":false,"first_name":"Test"},"chat":{"id":123,"type":"private"},"date":1234567890,"text":"테스트"}}'

Step 5: Production 배포

npm run deploy

Step 6: 배포 확인

# Health Check
curl https://telegram-summary-bot.kappa-d8e.workers.dev/health

# 로그 스트리밍
npm run tail

기술 상세

Rate Limiting 동작 방식

Key 형식: ratelimit:{userId}

데이터 구조:

{
  count: number,      // 현재 윈도우 내 요청 수
  resetAt: number     // 윈도우 만료 시각 (Unix timestamp)
}

알고리즘:

  1. KV에서 ratelimit:{userId} 조회
  2. 데이터 없음 또는 윈도우 만료 (now > resetAt) → 새 윈도우 시작 (count=1, resetAt=now+60000)
  3. count >= 30 (기본값) → Rate Limit 초과, 요청 차단
  4. count < 30count++ 후 KV 업데이트

자동 만료:

  • KV의 expirationTtl 옵션 사용
  • 윈도우 종료 시 자동 삭제 (메모리 효율)

에러 처리:

  • KV 오류 발생 시: Rate Limit 통과 (서비스 가용성 우선)
  • 로그 기록: [RateLimit] KV 오류: ...

모니터링

KV Dashboard

https://dash.cloudflare.com → Workers & Pages → KV → telegram-summary-bot-RATE_LIMIT_KV

KV CLI 명령어

# Namespace 목록
wrangler kv:namespace list

# 특정 키 조회
wrangler kv:key get "ratelimit:821596605" --namespace-id=YOUR_KV_ID

# 모든 키 목록
wrangler kv:key list --namespace-id=YOUR_KV_ID

# 키 삭제 (테스트용)
wrangler kv:key delete "ratelimit:821596605" --namespace-id=YOUR_KV_ID

로그 확인

# 실시간 로그
wrangler tail

# Rate Limit 관련 로그만 필터링
wrangler tail --format json | jq 'select(.message | contains("RateLimit"))'

성능 영향

Before (인메모리 Map)

  • 응답 시간: ~1ms (동기)
  • 메모리: 인스턴스별 독립 (중복 저장)
  • 일관성: 분산 환경에서 불일치

After (KV)

  • 응답 시간: ~20-50ms (KV read/write 포함)
  • 메모리: 0 (KV로 오프로드)
  • 일관성: 전역 일관성 보장

영향 분석:

  • 약 20-50ms 지연 추가 (허용 가능한 수준)
  • Telegram Webhook 응답은 200ms 이내 권장 (충분히 만족)
  • 사용자 경험에 무시할 수 있는 영향

비용 분석

Cloudflare Workers Free Plan

  • KV 읽기: 100,000 reads/day (무료)
  • KV 쓰기: 1,000 writes/day (무료)

Rate Limiting 사용량

  • 1 메시지 = 1 read + 1 write (최악의 경우)
  • 일일 1,000 메시지까지 무료 (write limit 기준)
  • 초과 시: $0.50 per million writes

예상 사용량:

  • 현재 사용자 수: 소규모 (~10명)
  • 일일 메시지 수: ~100개
  • 예상 비용: $0 (무료 한도 내)

롤백 절차 (문제 발생 시)

Option 1: Git Revert

git revert HEAD
npm run deploy

Option 2: 수동 롤백

  1. wrangler.toml에서 KV Namespace 제거
  2. src/types.ts에서 RATE_LIMIT_KV 제거
  3. src/security.ts 이전 버전으로 복원
  4. src/index.ts 이전 버전으로 복원
  5. npm run deploy

추가 리소스


체크리스트

배포 전:

  • wrangler kv:namespace create RATE_LIMIT_KV 실행
  • wrangler.toml에 실제 KV Namespace ID 입력
  • npx tsc --noEmit 타입 에러 없음
  • npm run dev 로컬 테스트 성공
  • Rate Limit 테스트 (30회 연속 요청)

배포 후:

  • npm run deploy 성공
  • Health Check 정상 (/health 엔드포인트)
  • 실제 Telegram 메시지 테스트 성공
  • KV Dashboard에서 키 생성 확인
  • wrangler tail 로그 확인
  • 30회 연속 메시지로 Rate Limit 동작 확인

작업 완료 시각: 2026-01-19 배포 담당자: Claude Code (AI Assistant) 상태: 코드 변경 완료 / KV Namespace 생성 대기 중