Cloudflare Migration
GitHub Actions 기반의 실행 환경을 Cloudflare Workers로 전환하고, 데이터 저장소를 GitHub에서 R2로 이전하는 마이그레이션이 완료되었습니다.
완료된 변경사항
섹션 제목: “완료된 변경사항”1. 실행 환경: GitHub Actions → Cloudflare Workers
섹션 제목: “1. 실행 환경: GitHub Actions → Cloudflare Workers”- 모든 데이터 처리 로직이 Workers에서 실행
- Cloudflare Queues를 통한 안정적인 작업 분산
- Cron 트리거로 스케줄링된 작업 실행
2. 데이터 저장소: GitHub → R2
섹션 제목: “2. 데이터 저장소: GitHub → R2”- Raw JSON 데이터는 R2에 저장
- 메타데이터만 GitHub에 동기화 (audit trail)
- D1 데이터베이스로 상태 및 메타데이터 관리
3. Cloudflare Queues 추가
섹션 제목: “3. Cloudflare Queues 추가”- 작업 분할 및 안정적인 처리
- 자동 재시도 및 DLQ(Dead Letter Queue) 지원
- Rate limiting을 통한 외부 서비스 보호
새로운 아키텍처
섹션 제목: “새로운 아키텍처”┌─────────────────────────────────────────────────────────────────┐│ Cloudflare Workers ││ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ││ │ HTTP API │ │ Scheduled │ │ Queue │ ││ │ Handler │ │ (Cron) │ │ Consumers │ ││ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ ││ │ │ │ ││ └────────────────┼────────────────┘ ││ │ ││ ┌───────────────────────┴───────────────────────┐ ││ │ Business Services │ ││ │ Research │ Dataset │ Metadata │ Queue │ ││ └───────────────────────┬───────────────────────┘ ││ │ ││ ┌───────────────────────┴───────────────────────┐ ││ │ Storage Services │ ││ │ HybridStorage │ R2Storage │ GitHubStorage │ ││ └───────────────────────┬───────────────────────┘ │└──────────────────────────┼──────────────────────────────────────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼┌───────────────┐ ┌───────────────┐ ┌───────────────┐│ R2 │ │ D1 │ │ GitHub ││ (Raw Data) │ │ (Metadata) │ │ (Audit Trail) │└───────────────┘ └───────────────┘ └───────────────┘파일 구조
섹션 제목: “파일 구조”src/├── index.ts # 앱 진입점 (HTTP, Cron, Queue handlers)├── routes/│ ├── index.ts # 라우트 export│ ├── health.ts # 헬스체크│ ├── research.ts # 리서치 API│ ├── seeds.ts # 시드 API│ ├── datasets.ts # 데이터셋 API (NEW)│ ├── metadata.ts # 메타데이터 API (NEW)│ └── queues.ts # 큐 관리 API (NEW)├── services/│ ├── index.ts # 서비스 export│ ├── storage.service.ts # GitHub Storage│ ├── r2-storage.service.ts # R2 Storage (NEW)│ ├── hybrid-storage.service.ts # Hybrid Storage (NEW)│ ├── queue.service.ts # Queue Service (NEW)│ ├── dataset.service.ts # Dataset Service (NEW)│ ├── metadata.service.ts # Metadata Service (NEW)│ ├── research.service.ts│ └── seed.service.ts├── schemas/│ ├── index.ts│ ├── common.ts│ ├── research.ts│ ├── seed.ts│ ├── checkpoint.ts│ ├── metadata.ts # Metadata Schemas (NEW)│ └── queue.ts # Queue Schemas (NEW)└── lib/ ├── index.ts ├── path.ts ├── errors.ts ├── domain.ts ├── kv.ts ├── liveness.ts ├── dataset-utils.ts ├── checkpoint.ts ├── r2.ts # R2 Utilities (NEW) ├── d1.ts # D1 Utilities (NEW) └── queue.ts # Queue Processors (NEW)
migrations/└── 001_init.sql # D1 Database Schema (NEW)
.github/workflows/├── deploy.yml # Workers 배포└── metadata-sync.yml # 메타데이터 GitHub 동기화 (NEW)API 엔드포인트
섹션 제목: “API 엔드포인트”기존 엔드포인트 (유지)
섹션 제목: “기존 엔드포인트 (유지)”GET /health- 헬스체크GET /api/v1/research/:country/:category/:date- 리서치 조회POST /api/v1/research- 리서치 생성GET /api/v1/seeds- 시드 목록POST /api/v1/seeds- 시드 생성
새로운 엔드포인트
섹션 제목: “새로운 엔드포인트”-
GET /api/v1/datasets- 데이터셋 목록 -
GET /api/v1/datasets/stats- 데이터셋 통계 -
GET /api/v1/datasets/:country/:category/:date- 특정 날짜 청크 목록 -
GET /api/v1/datasets/:country/:category/:date/:chunk- 특정 청크 조회 -
POST /api/v1/datasets/:country/:category/:date/:chunk- 청크 저장 -
DELETE /api/v1/datasets/:country/:category/:date/:chunk- 청크 삭제 -
GET /api/v1/metadata/snapshot- 스냅샷 메타데이터 -
POST /api/v1/metadata/sync- GitHub 동기화 트리거 -
GET /api/v1/metadata/by-country/:country- 국가별 메타데이터 -
GET /api/v1/metadata/by-category/:category- 카테고리별 메타데이터 -
GET /api/v1/metadata/by-date-range- 날짜 범위 메타데이터 -
GET /api/v1/metadata/tasks- 작업 통계 -
POST /api/v1/queues/research- 리서치 배치 생성 -
POST /api/v1/queues/liveness- Liveness 배치 생성 -
POST /api/v1/queues/contract- 계약 배치 생성 -
GET /api/v1/queues/batch/:batchId- 배치 상태 조회 -
POST /api/v1/queues/trigger/metadata-sync- 메타데이터 동기화 트리거 -
POST /api/v1/queues/trigger/research-discovery- 리서치 발견 트리거
Cloudflare Queues 구성
섹션 제목: “Cloudflare Queues 구성”큐 목록
섹션 제목: “큐 목록”| 큐 이름 | 용도 | Batch Size | Timeout | Retries |
|---|---|---|---|---|
| newsfork-research-{env} | 리서치 작업 | 10 | 30s | 3 |
| newsfork-contract-{env} | 계약 생성 | 10 | 30s | 3 |
| newsfork-liveness-{env} | Liveness 체크 | 50-100 | 10s | 3 |
| newsfork-dlq-{env} | Dead Letter Queue | - | - | - |
메시지 타입
섹션 제목: “메시지 타입”research_discovery: 리서치 발견 작업research_batch: 리서치 배치 처리metadata_sync: 메타데이터 동기화contract_generate: 계약 생성contract_validate: 계약 검증contract_batch: 계약 배치 처리liveness_check: 단일 Liveness 체크liveness_batch: Liveness 배치 체크
설정 및 배포
섹션 제목: “설정 및 배포”1. Cloudflare 리소스 생성
섹션 제목: “1. Cloudflare 리소스 생성”# R2 버킷 생성wrangler r2 bucket create newsfork-datasets-devwrangler r2 bucket create newsfork-metadata-dev
# D1 데이터베이스 생성wrangler d1 create newsfork-metadata-dev
# 큐 생성wrangler queues create newsfork-research-devwrangler queues create newsfork-contract-devwrangler queues create newsfork-liveness-devwrangler queues create newsfork-dlq-dev
# KV 네임스페이스 생성wrangler kv:namespace create DOMAIN_KV2. wrangler.jsonc 업데이트
섹션 제목: “2. wrangler.jsonc 업데이트”생성된 리소스 ID를 wrangler.jsonc에 업데이트:
- R2 bucket_name
- D1 database_id
- KV namespace id
- Queue names
3. D1 스키마 적용
섹션 제목: “3. D1 스키마 적용”wrangler d1 execute METADATA_DB --file=./migrations/001_init.sql4. 시크릿 설정
섹션 제목: “4. 시크릿 설정”wrangler secret put GH_TOKENwrangler secret put GH_OWNERwrangler secret put GH_REPO5. 배포
섹션 제목: “5. 배포”# 개발 환경pnpm run dev
# 스테이징 배포pnpm run deploy:staging
# 프로덕션 배포pnpm run deploy:production데이터 흐름
섹션 제목: “데이터 흐름”리서치 배치 처리
섹션 제목: “리서치 배치 처리”1. API 호출: POST /api/v1/queues/research └─> QueueService.createResearchBatch() └─> URL 목록을 청크로 분할 (예: 100개씩) └─> 각 청크를 RESEARCH_QUEUE에 전송 └─> 배치 메타데이터를 D1에 저장
2. Queue Consumer └─> processResearchQueue() 호출 └─> 청크 처리 (URL 정규화, 도메인 추출) └─> 결과를 R2에 저장 └─> D1에 배치 진행 상태 업데이트
3. 완료 후 └─> metadata_sync 작업 자동 트리거 └─> R2 메타데이터를 GitHub에 동기화메타데이터 동기화
섹션 제목: “메타데이터 동기화”1. Cron 트리거 (매 6시간) 또는 API 호출 └─> RESEARCH_QUEUE에 metadata_sync 메시지 전송
2. Queue Consumer └─> handleMetadataSync() 호출 └─> R2에서 모든 데이터셋 메타데이터 집계 └─> GitHub에 metadata/snapshot.json 커밋
3. GitHub Actions (선택적) └─> metadata-sync.yml 워크플로우 └─> Worker API에서 스냅샷 조회 └─> GitHub 저장소에 커밋삭제된 파일
섹션 제목: “삭제된 파일”CLI 도구 (Workers로 대체)
섹션 제목: “CLI 도구 (Workers로 대체)”cli/research-engine.tscli/contract-engine.ts
GitHub Actions 워크플로우 (Workers로 대체)
섹션 제목: “GitHub Actions 워크플로우 (Workers로 대체)”.github/workflows/research-dev.yml.github/workflows/research-staging.yml.github/workflows/research-prod.yml.github/workflows/research-pipeline.yml.github/workflows/contract-pipeline.yml.github/workflows/seed-dev.yml.github/workflows/seed-staging.yml.github/workflows/seed-prod.yml.github/workflows/seed-promotion.yml
테스트
섹션 제목: “테스트”로컬 테스트
섹션 제목: “로컬 테스트”# 로컬 Workers 실행 (Miniflare)pnpm run dev:local
# 테스트 실행pnpm test
# Workers 전용 테스트pnpm run test:localAPI 테스트
섹션 제목: “API 테스트”# 헬스체크curl http://localhost:8787/health
# 데이터셋 목록curl http://localhost:8787/api/v1/datasets
# 메타데이터 스냅샷curl http://localhost:8787/api/v1/metadata/snapshot
# 리서치 배치 생성curl -X POST http://localhost:8787/api/v1/queues/research \ -H "Content-Type: application/json" \ -d '{"country":"SG","category":"news","urls":["https://example.com"]}'모니터링
섹션 제목: “모니터링”Cloudflare Dashboard
섹션 제목: “Cloudflare Dashboard”- Workers Analytics: 요청 수, 지연 시간, 에러율
- Queues: 메시지 처리량, 재시도 횟수, DLQ 상태
- R2: 스토리지 사용량, 요청 수
- D1: 쿼리 성능, 스토리지 사용량
메타데이터 동기화
섹션 제목: “메타데이터 동기화”- GitHub 저장소의
metadata/snapshot.json확인 - 마지막 동기화 시간, 총 데이터셋 수, 레코드 수
주의사항
섹션 제목: “주의사항”- Workers 실행 시간 제한: 각 작업이 30초 내에 완료되도록 설계
- Queue 재시도: 실패한 작업은 최대 3회 재시도 후 DLQ로 이동
- Rate Limiting: Liveness 체크 시 도메인당 100ms 딜레이 적용
- 메모리 제한: Workers의 128MB 메모리 제한 고려
- R2 비용: 스토리지 및 요청 비용 모니터링 필요