title: content-pipeline 정상화 플랜 date: 2026-02-26 status: in_progress reviewed_by: "jarvis" approved_by: "jarvis" execution_status: "Tasks 1-3 complete, Task 4 blocked by Vercel deployment limit" okr_target: "O3 콘텐츠 OKR RED 해소" task_id: "2cb751a5-ec2d-4d27-bafb-601f664abc98"
content-pipeline 정상화 플랜
L0: 목표
content-pipeline의 API 404 이슈를 해결하고, 파이프라인을 정상 운영 상태로 복구하여 O3(콘텐츠) OKR RED 지표를 개선할 수 있는 상태로 만든다.
성공 기준:
/api/cron/pipelineAPI가 200 응답 반환/api/cron/publishAPI가 200 응답 반환/api/pipeline/approveAPI가 정상 동작- RSS 수집 → 콘텐츠 생성(mock) → draft 저장까지 E2E 동작 확인
L1: 문제 분석
근본 원인: production 브랜치 미동기화
| 항목 | 상태 |
|---|---|
| main 브랜치 | Phase 1 코드 전부 포함 (stage-collect/generate/publish, approve/reject API, cron handler) |
| production 브랜치 | 7dce24f에서 멈춤 — Phase 1 핵심 코드 3커밋 누락 (5d38d30, 40a30e7, 463f60d) |
| staging 브랜치 | main + README 1줄 추가 (실질적으로 main과 동일) |
| Vercel 배포 | content-pipeline-sage.vercel.app — production 브랜치 기반 배포 |
production vs main 차이: 39파일, 4,199줄 누락.
누락된 핵심 파일:
src/pipeline/stage-collect.ts(RSS 수집 스테이지)src/pipeline/stage-generate.ts(AI 생성 스테이지)src/pipeline/stage-publish.ts(발행 스테이지)src/app/api/cron/pipeline/route.ts가 import하는 모듈들src/lib/pipeline-logger.ts,src/lib/notifications.ts등
이로 인해 Vercel에 배포된 코드에 API 라우트가 빌드 시 실패하거나 누락되어 404 발생.
환경변수 이슈
| 변수 | 로컬 .env | Vercel |
|---|---|---|
TURSO_DB_URL | O | O (Production only) |
TURSO_DB_TOKEN | O | O (Production only) |
CONTENT_OS_DB_URL | O | O (Production only) |
CONTENT_OS_DB_TOKEN | O | O (Production only) |
BREVO_API_KEY | O | O (Production only) |
CRON_SECRET | X | X |
GOOGLE_API_KEY | X | X |
ANTHROPIC_API_KEY | O | X |
문제점:
CRON_SECRET미설정 → Vercel Cron이 API 호출해도 401 Unauthorized 반환GOOGLE_API_KEY미설정 → AI 생성 시 mock 모드로 동작 (기능은 됨)- 모든 env가 Production 환경에만 설정 → Preview(staging) 배포에서는 DB 연결 불가
코드 구조 분석 (정상)
파이프라인 아키텍처는 올바르게 설계됨:
Stage 1: collect (RSS 수집) → collected_news 저장
Stage 2: generate (AI 생성) → content_queue(draft) 저장
Stage 3: approve (CEO 승인) → content_queue(approved) 전환
Stage 4: publish (블로그 발행) → blog_posts INSERT + content_distributions 기록
- Cron
/api/cron/pipeline: Stage 1+2 실행 (월~금 UTC 21:00 = KST 06:00) - Cron
/api/cron/publish: 승인된 게시물 자동 발행 (매 6시간) - API
/api/pipeline/approve: 승인 + Stage 4 자동 트리거
L2: 실행 계획
Task 1: production 브랜치를 main과 동기화
방법: production 브랜치를 main의 최신 커밋으로 fast-forward merge
cd projects/content-pipeline
git checkout production
git merge main --ff-only
git push origin production
예상 결과: Vercel이 production 브랜치 push를 감지하여 자동 배포 트리거. 리스크: 낮음. main에는 이미 검증된 코드만 존재. fast-forward이므로 충돌 없음.
Task 2: CRON_SECRET 환경변수 설정
# 랜덤 secret 생성
openssl rand -hex 32
# Vercel에 설정 (Production + Preview 모두)
vercel env add CRON_SECRET production
vercel env add CRON_SECRET preview
주의: Vercel Cron은 자동으로 authorization: Bearer <CRON_SECRET> 헤더를 설정함. vercel.json의 cron path와 코드의 인증 로직이 일치하므로, secret만 설정하면 자동 동작.
Task 3: 환경변수를 Preview 환경에도 추가
현재 모든 env가 Production에만 설정됨. staging 브랜치 Preview 배포를 위해:
vercel env add CONTENT_OS_DB_URL preview
vercel env add CONTENT_OS_DB_TOKEN preview
vercel env add TURSO_DB_URL preview
vercel env add TURSO_DB_TOKEN preview
vercel env add BREVO_API_KEY preview
Task 4: 배포 후 API 검증
배포 완료 후 다음 순서로 검증:
# 1. API 응답 확인 (CRON_SECRET 없이 → 401 기대)
curl -s https://content-pipeline-sage.vercel.app/api/cron/pipeline | jq .
# 2. CRON_SECRET으로 인증하여 pipeline 실행
curl -s -H "Authorization: Bearer <CRON_SECRET>" \
https://content-pipeline-sage.vercel.app/api/cron/pipeline | jq .
# 3. publish cron 확인
curl -s -H "Authorization: Bearer <CRON_SECRET>" \
https://content-pipeline-sage.vercel.app/api/cron/publish | jq .
# 4. content_queue에 draft 생성되었는지 확인
# (pipeline API의 응답에 contentQueueId가 포함됨)
Task 5: mock → 실제 AI 생성 전환 (CEO 블로킹)
GOOGLE_API_KEY 설정 시 Gemini Flash로 실제 콘텐츠 생성 가능. CEO 발급 필요.
현재는 mock 모드로 동작하며, 파이프라인 E2E 플로우는 정상 동작.
타임라인
| 단계 | 소요시간 | 블로커 |
|---|---|---|
| Task 1: branch 동기화 | 5분 | 없음 |
| Task 2: CRON_SECRET 설정 | 5분 | 없음 |
| Task 3: Preview env 설정 | 10분 | 없음 |
| Task 4: API 검증 | 10분 | Vercel 빌드 대기 (~3분) |
| Task 5: AI 생성 전환 | CEO 발급 후 | GOOGLE_API_KEY 블로킹 |
예상 총 소요: 30분 (Task 1~4)
리스크
| 리스크 | 확률 | 대응 |
|---|---|---|
| fast-forward merge 불가 | 낮음 (이미 확인: production은 main의 조상) | force merge 대신 rebase 후 push |
| Vercel 빌드 실패 | 낮음 (main은 이미 빌드 성공 이력) | 빌드 로그 확인 후 수정 |
| Vercel Cron 미동작 | 중간 (Hobby Plan 제한) | 수동 curl로 대체, 로컬 cron 설정 |
| DB 연결 실패 | 낮음 (env vars 확인 완료) | Turso 대시보드에서 DB 상태 확인 |