보안 개선: - 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>
4.7 KiB
4.7 KiB
Rate Limiting KV Migration - 작업 완료 요약
작업 개요
Rate Limiting 시스템을 인메모리 Map에서 Cloudflare KV로 마이그레이션하여 분산 환경에서 일관된 동작을 보장합니다.
변경 사항 요약
해결된 문제
✅ Workers 인스턴스 간 Rate Limit 데이터 공유 ✅ Worker 재시작 시에도 Rate Limit 상태 유지 ✅ 분산 환경에서 일관된 Rate Limiting 동작 ✅ 자동 만료 (KV TTL) - 메모리 효율성
수정된 파일 (4개)
wrangler.toml- KV Namespace 바인딩 추가src/types.ts- Env 인터페이스에 RATE_LIMIT_KV 추가src/security.ts- checkRateLimit() 함수 KV 기반으로 재구현src/index.ts- checkRateLimit() 호출 시 KV 전달
문서 업데이트
CLAUDE.md- Rate Limiting 섹션, Configuration 섹션 업데이트KV_MIGRATION_GUIDE.md- 상세 마이그레이션 가이드 (신규)DEPLOYMENT_SUMMARY.md- 배포 절차 요약 (신규)
배포 가이드
1. KV Namespace 생성 (최초 1회)
wrangler kv:namespace create RATE_LIMIT_KV
출력된 id 값을 복사합니다.
2. wrangler.toml 수정
22번 줄의 YOUR_KV_NAMESPACE_ID를 실제 ID로 변경:
[[kv_namespaces]]
binding = "RATE_LIMIT_KV"
id = "abc123def456ghi789jkl012mno345pq" # ← 실제 ID로 변경
3. 로컬 테스트
npm run dev
다른 터미널에서 테스트:
curl -X POST http://localhost:8787/webhook \
-H "Content-Type: application/json" \
-H "X-Telegram-Bot-Api-Secret-Token: YOUR_WEBHOOK_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":"테스트"}}'
4. Production 배포
npm run deploy
5. 배포 확인
# 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 ms)
}
동작:
- KV에서 사용자별 카운터 조회
- 윈도우 만료 확인 (
now > resetAt)- 만료 시: 새 윈도우 시작 (
count=1) - 유효 시: count 증가
- 만료 시: 새 윈도우 시작 (
count >= 30→ Rate Limit 초과, 차단count < 30→ KV 업데이트, 허용
자동 만료: KV의 expirationTtl 사용 (60초)
에러 처리: KV 오류 시 요청 허용 (가용성 우선)
성능 영향
| 항목 | Before (Map) | After (KV) |
|---|---|---|
| 응답 시간 | ~1ms | ~20-50ms |
| 메모리 | 인스턴스별 | 0 (KV) |
| 일관성 | ❌ 분산 불일치 | ✅ 전역 일관성 |
| 재시작 | ❌ 데이터 손실 | ✅ 유지 |
결론: 약 20-50ms 지연 추가되지만, Telegram Webhook은 200ms 이내 응답 권장이므로 충분히 허용 가능.
비용 분석
Cloudflare Workers Free Plan
- KV 읽기: 100,000 reads/day (무료)
- KV 쓰기: 1,000 writes/day (무료)
예상 사용량
- 1 메시지 = 1 read + 1 write
- 일일 1,000 메시지까지 무료
- 현재 사용량: ~100 메시지/일 → $0 (무료)
모니터링
KV Dashboard
https://dash.cloudflare.com → Workers & Pages → KV → telegram-summary-bot-RATE_LIMIT_KV
CLI 명령어
# Namespace 목록
wrangler kv:namespace list
# 특정 사용자 Rate Limit 조회
wrangler kv:key get "ratelimit:821596605" --namespace-id=YOUR_KV_ID
# 모든 키 목록
wrangler kv:key list --namespace-id=YOUR_KV_ID
# 로그 확인
wrangler tail
롤백 절차 (문제 발생 시)
git revert HEAD
npm run deploy
또는 수동 롤백:
wrangler.toml에서 KV Namespace 제거src/types.ts,src/security.ts,src/index.ts이전 버전 복원npm run deploy
체크리스트
배포 전
wrangler kv:namespace create RATE_LIMIT_KV실행wrangler.toml에 실제 KV Namespace ID 입력- 로컬 테스트 (
npm run dev) 성공
배포 후
npm run deploy성공- Health Check 정상
- 실제 Telegram 메시지 테스트
- KV Dashboard에서 키 생성 확인
- 30회 연속 메시지로 Rate Limit 동작 확인
추가 리소스
- 상세 가이드:
KV_MIGRATION_GUIDE.md - 배포 요약:
DEPLOYMENT_SUMMARY.md - 프로젝트 문서:
CLAUDE.md,README.md - Cloudflare KV Docs: https://developers.cloudflare.com/kv/
작업 완료 시각: 2026-01-19 상태: ✅ 코드 변경 완료 / ⏳ 배포 대기 중 다음 단계: KV Namespace 생성 → wrangler.toml 수정 → 배포