---
task_id: task-2026
type: context
scope: task
created: 2026-04-20
updated: 2026-04-20
status: completed
---

# 맥락 노트: task-2026

**task**: task-2026

---

## 결정 근거

### 3 Step Why 자문

**1st Why: "왜 이 설계가 필요한가?"**
현재 MVP 파이프라인은 인메모리 딕셔너리 기반으로, 서버 재시작 시 상태 유실, 비동기 실패 복구 불가, 부분 롤백 불가. 프로덕션 수준으로 올리려면 상태 머신, 재시도, 롤백, 실시간 UI 갱신이 필요.

**2nd Why: "왜 기존 MVP 확장이 최선인가?"**
기존 MVP 구조(pipeline.py + schemas/pipeline.py)가 이미 D→B→A 단계, PipelineStatus 상태 enum, 재시도 로직의 뼈대를 갖추고 있음. 처음부터 새로 만드는 것보다 기존 구조를 확장하는 것이 리스크 최소화 + 테스트 호환 유지에 유리.

**3rd Why: "왜 이것이 다른 대안보다 나은가?"**
- 대안 1(Celery/ARQ 풀스택 도입): 인프라 복잡성 증가, 현재 규모에서 과도
- 대안 2(완전 새 설계): 기존 API 계약 파괴, 프론트엔드 호환성 깨짐
- 선택: 기존 BackgroundTasks 유지 + 상태 모델 강화 + 프론트 폴링 고도화 → 비용 대비 효과 최대

### PipelineRun 타입 결정: dict 통일
- 초기 설계: `_pipeline_runs: dict[str, PipelineRun]`으로 Pydantic 모델 직접 저장
- 문제: run_pipeline에서 dict처럼 접근 (`run["status"]`) → 타입 혼합
- 결정: `dict[str, dict[str, Any]]`로 통일, PipelineRun은 생성자에서만 사용하고 model_dump()으로 dict 변환
- 근거: 기존 API 호환성 유지 + pyright 타입 안전성

### 폴링 전략: setTimeout 지수 백오프
- 기존: setInterval 5초 고정
- 변경: setTimeout 기반, 5s→10s→20s→40s→60s 지수 백오프
- 상태 변화 감지 시 5초로 리셋
- 근거: 장시간 실행 파이프라인에서 불필요한 API 호출 감소

## 참조 자료

- 기존 MVP: `/home/jay/projects/InsuRo/server/pipeline.py`
- 스키마: `/home/jay/projects/InsuRo/server/schemas/pipeline.py`
- AutomationStepper: `/home/jay/projects/InsuRo/src/components/AutomationStepper.tsx`
- 폴링 훅: `/home/jay/projects/InsuRo/src/hooks/use-pipeline-status.ts`

## 주의사항

- 현재 인메모리 저장소 → 서버 재시작 시 파이프라인 상태 유실 (DB 이관 필요)
- C 단계(PUBLISH)는 STAGE_ORDER에 포함했지만 실제 구현은 미포함 (미리보기 전용)
- Supabase Realtime 미구현 → 폴링 폴백만 가동
