title: content-orchestration 자체교정 설계서 (L1) date: 2026-02-25T19:30:00+09:00 type: design layer: L1 status: in-review tags: [content-orchestration, self-healing, L1, error-recovery] author: self-healing-pl project: content-orchestration reviewed_by: "jarvis" reviewed_at: "2026-02-25T19:45:00+09:00" approved_by: "" approved_at: ""
content-orchestration 자체교정(Self-Healing) 설계서 (L1)
Task ID: dc1d0d04-5bca-4d69-abc7-e0b4f3e40c79
작성일: 2026-02-25
작성자: self-healing-pl
근거 문서:
- L1:
content-orchestration-design-pipeline.md(파이프라인 설계서, 승인) - L1:
content-orchestration-design-db.md(DB 설계서, 검수 완료) - L1:
content-orchestration-design-external.md(외부 연동 설계서, 승인)
1. 자체교정 개요
1-1. 자체교정이란
자체교정(Self-Healing)은 파이프라인 실행 중 발생하는 오류를 사람 개입 없이 자동으로 탐지하고 복구하는 메커니즘이다. 파이프라인 설계서 섹션 3의 교정 등급(L1~L5)을 기반으로, 등급별로 자동 복구 범위와 에스컬레이션 판단 기준을 정의한다.
핵심 목표: 파이프라인 장애 시 CEO 개입을 최소화하고, 자동 교정 성공률 80%+ 달성 (Phase 3 목표)
1-2. L1~L5 등급 정의 (상세)
| 등급 | 이름 | 교정 행동 | 자동화 수준 | 판단 기준 | Phase |
|---|---|---|---|---|---|
| L1 | 즉시 자동 수정 | 동일 작업 재실행 (파라미터 변경 없음) | 완전 자동 | 일시적 오류 (네트워크, DB 연결, 타임아웃) | Phase 1 |
| L2 | 재시도 후 수정 | 대기 후 재시도 또는 파라미터 미세 조정 | 완전 자동 | Rate Limit, API 일시 과부하, QA 미달 | Phase 1 |
| L3 | 대체 전략 | Fallback 경로 전환 (다른 소스/모델/채널) | 자동 (설정 범위 내) | 특정 소스/채널 지속 실패, AI 모델 장애 | Phase 2 |
| L4 | 품질 강등 | 콘텐츠 재생성 → 실패 시 holding 전환 | 반자동 (자비스 검수) | AI 생성 품질 반복 미달, QA 3회 연속 실패 | Phase 2 |
| L5 | 인간 에스컬레이션 | CEO/VP에게 알림, 수동 해결 대기 | 수동 | 인증 실패, 3회 연속 자동 교정 실패, 전체 채널 실패, 비용 영향 | Phase 1 |
1-3. 자체교정 적용 범위
| 파이프라인 단계 | 적용 자체교정 등급 | 외부 연동 |
|---|---|---|
| Stage 1: 수집 (Collect) | L1, L2, L3 | RSS 17개 피드 |
| Stage 2: 생성 (Generate) | L1, L2, L4 | Gemini Flash API |
| Stage 3: 승인 (Approve) | — (자체교정 대상 아님, CEO 액션) | — |
| Stage 4: 배포 (Publish) | L1, L2, L3 | Brevo, AppPro 블로그 DB, getlate.dev |
| 외부 연동: Brevo | L1, L2, L5 | Brevo API |
| 외부 연동: getlate.dev | L1, L2, L3 | getlate REST API |
| 외부 연동: 블로그 DB | L1, L5 | Turso (apppro-kr) |
1-4. 자체교정 vs 에스컬레이션 판단 기준
에러 발생
│
├─ 인증 실패 (auth_fail)? ─→ 즉시 L5 에스컬레이션 (CEO 키 갱신 필요)
│
├─ 동일 에러 3회 연속? ─→ L5 에스컬레이션 (자동 교정 한계)
│
├─ 전체 채널/소스 실패? ─→ L5 에스컬레이션 (시스템 장애 의심)
│
├─ 비용 영향 (Rate Limit 초과 등)? ─→ L2 자동 지연 후 재시도
│
├─ 대체 경로 가능? ─→ L3 Fallback 전환
│
├─ 품질 문제? ─→ L4 재생성 시도 (최대 2회)
│
└─ 일시적 오류? ─→ L1/L2 즉시 재시도
2. 등급별 자체교정 시나리오 (상세)
2-1. L1: 즉시 자동 수정
원칙: 동일 파라미터로 1회 재시도. 성공하면 auto_fix_result='success', 실패하면 L2로 에스컬레이트.
| # | 시나리오 | 감지 방법 | 교정 행동 | 대기 시간 | 재시도 횟수 |
|---|---|---|---|---|---|
| 1 | RSS 피드 HTTP 5xx | fetch 응답 코드 >= 500 | 동일 URL 재요청 | 5초 | 1회 |
| 2 | DB 연결 일시 오류 | LibSQL 연결 예외 | 재연결 후 동일 쿼리 | 3초 | 1회 |
| 3 | Brevo API 네트워크 에러 | fetch timeout 또는 네트워크 예외 | 동일 요청 재전송 | 5초 | 1회 |
| 4 | getlate API 일시 에러 | HTTP 5xx 또는 timeout | 동일 요청 재전송 | 5초 | 1회 |
| 5 | slug 중복 (블로그) | SQL ON CONFLICT 감지 | slug에 날짜+순번 자동 추가 ({slug}-2026-02-25-2) | 0초 | 즉시 |
| 6 | RSS XML 파싱 부분 실패 | rss-parser 예외 (개별 피드) | 해당 피드 skip, 나머지 계속 | 0초 | — |
L1 교정 코드 패턴:
try {
result = await action()
} catch (error) {
// L1: 즉시 재시도
await sleep(waitMs)
try {
result = await action()
logAutoFix(errorId, 'success', 'L1 즉시 재시도 성공')
} catch (retryError) {
logAutoFix(errorId, 'failed', 'L1 재시도 실패 → L2 전환')
// L2로 에스컬레이트
}
}
2-2. L2: 재시도 후 수정
원칙: 대기 시간을 늘리거나 파라미터를 미세 조정한 후 재시도. 최대 3회.
| # | 시나리오 | 감지 방법 | 교정 행동 | 재시도 전략 |
|---|---|---|---|---|
| 1 | Brevo Rate Limit (HTTP 429) | 응답 코드 429 | 60초 대기 후 재시도 → 발송 시간을 다음 날 06:00 KST로 변경 | 60초 → 120초 → 다음 날 재예약 |
| 2 | RSS 피드 타임아웃 | 10초 초과 | 타임아웃 15초로 확장 후 재시도 | 10초 → 15초 → 20초 |
| 3 | AI API 타임아웃 | Gemini API fetch timeout | 30초 대기 후 재시도 | 30초 → 60초 → 포기 |
| 4 | QA 미달 (score < 6/8) | validateQuality 함수 | 프롬프트 온도 0.7→0.5로 낮추어 재생성 | 최대 2회 재생성 |
| 5 | JSON 파싱 실패 | JSON.parse 예외 | 이스케이프 보정 → 필드별 추출 시도 | 2단계 파싱 시도 |
| 6 | getlate 월간 한도 근접 | 포스트 수 추적 | 우선순위 낮은 플랫폼 skip | 즉시 |
| 7 | 블로그 DB INSERT 실패 | SQL 예외 (non-auth) | 5초 대기 후 1회 재시도 | 5초 대기 → 1회 |
L2 백오프 전략:
재시도 간격 = baseDelay * (2 ^ attemptNumber)
- 1회: 5초 (또는 60초 for rate limit)
- 2회: 10초 (또는 120초)
- 3회: 20초 (또는 다음 날 재예약)
최대 재시도: 3회
3회 실패 시: error_logs에 기록 + L5 에스컬레이션
2-3. L3: 대체 전략
원칙: 원래 경로가 실패하면 사전 정의된 대체 경로로 전환. Phase 2에서 구현.
| # | 시나리오 | 감지 조건 | 대체 전략 | Phase |
|---|---|---|---|---|
| 1 | 특정 RSS 소스 3회 연속 실패 | error_logs에서 동일 component + 동일 URL 3건 (24시간 내) | 해당 소스 자동 비활성화, 동일 카테고리의 대체 소스로 교체 | Phase 2 |
| 2 | SNS 특정 플랫폼 실패 | getlate 응답에서 플랫폼별 status='failed' | 해당 플랫폼만 skip, 나머지 정상 진행 | Phase 1 (부분) |
| 3 | Gemini API 장기 장애 | 연속 3회 AI API 실패 (1시간 내) | Claude API로 모델 전환 (content_generation_config에서 model 변경) | Phase 2 |
| 4 | Brevo 발송 한도 초과 | HTTP 402 또는 일일 300통 도달 | scheduledAt을 다음 날로 자동 재예약 | Phase 1 (부분) |
L3 대체 소스 매핑 (Phase 2):
카테고리별 대체 소스 우선순위:
news (영문): The Verge → TechCrunch → Ars Technica → Techmeme
official: OpenAI Blog → Google AI Blog → DeepMind → Hugging Face → NVIDIA
news (한국): AI타임스 → ZDNet Korea → 전자신문 → ITWorld Korea → 테크니들
community: Hacker News Best → Hacker News Latest → Techmeme
2-4. L4: 품질 강등
원칙: AI 생성 콘텐츠 QA 점수 부족 시 재생성. 3회 실패 시 holding 전환. Phase 2에서 구현.
| # | 시나리오 | 감지 조건 | 교정 행동 |
|---|---|---|---|
| 1 | QA 6/8 미만 (1차) | validateQuality score < 6 | 프롬프트 온도 0.7→0.5, 재생성 (2차 시도) |
| 2 | QA 6/8 미만 (2차) | 2차 재생성도 score < 6 | 프롬프트 길이 제한 완화 (max_tokens +500), 재생성 (3차 시도) |
| 3 | QA 6/8 미만 (3차) | 3차 재생성도 score < 6 | content_queue.status='failed' + error_logs(error_type='quality_fail', escalated=1) |
| 4 | 특정 필라 반복 실패 | 동일 pillar에서 3일 연속 QA 실패 | optimization_history에 기록 + 해당 필라 프롬프트 템플릿 검토 에스컬레이션 |
L4 품질 강등 플로우:
AI 생성 완료
│
↓
QA 검증 (8항목)
│
├─ score >= 6/8: PASS → content_queue(draft)
│
└─ score < 6/8: FAIL
│
├─ 1차 실패: 온도 0.7→0.5, 재생성
├─ 2차 실패: max_tokens +500, 재생성
└─ 3차 실패: error_logs + escalated=1
content_queue.status='failed'
2-5. L5: 인간 에스컬레이션
원칙: 자동 교정이 불가능하거나 3회 연속 실패한 경우. CEO/VP에게 알림 후 수동 해결 대기.
| # | 시나리오 | 에스컬레이션 트리거 | 알림 대상 | 알림 방법 |
|---|---|---|---|---|
| 1 | API 인증 실패 (auth_fail) | HTTP 401/403 (모든 외부 연동) | CEO | 즉시 텔레그램 (Phase 2) / 대시보드 에러 표시 (Phase 1) |
| 2 | 3회 연속 자동 교정 실패 | error_logs에서 동일 component 3건 (auto_fix_result='failed') | VP/자비스 | vice-reply.sh (Phase 2) |
| 3 | 전체 채널 배포 실패 | content_distributions에서 해당 content_id의 모든 레코드가 failed | VP/자비스 | vice-reply.sh (Phase 2) |
| 4 | 전체 RSS 피드 실패 | collect 실행 시 모든 17개 피드 실패 | VP/자비스 | pipeline_logs status='failed' + error_logs escalated=1 |
| 5 | DB 인증 토큰 만료 | Turso 연결 auth 에러 | CEO | 즉시 에스컬레이션 (토큰 갱신 필요) |
Phase 1 에스컬레이션 표시 방법 (Telegram 미연동):
error_logs.escalated = 1설정- 대시보드
/api/pipeline/errors엔드포인트에서escalated=1건 우선 표시 - pipeline_logs metadata에
"escalated": true기록
Phase 2 에스컬레이션 알림:
vice-reply.sh또는ceo-reply.sh를 통한 Telegram 자동 알림 (외부 연동 설계서 섹션 2-4 참조)
3. error_logs 기반 자동 교정 메커니즘
3-1. error_logs 스캔 주기 및 방법
| 스캔 시점 | 방법 | 목적 |
|---|---|---|
| 파이프라인 실행 전 | runSelfHealingCycle() 호출 | 이전 실행에서 남은 미해결 에러 교정 시도 |
| 파이프라인 실행 중 | 각 단계에서 에러 발생 즉시 | 실시간 교정 (L1/L2) |
| Cron 실행 시 | /api/cron/pipeline 시작 시 | 누적 미해결 에러 배치 교정 |
스캔 쿼리:
-- 미해결 + 자동 교정 미시도 에러 조회
SELECT * FROM error_logs
WHERE resolved_at IS NULL
AND (auto_fix_attempted = 0 OR auto_fix_result = 'failed')
AND escalated = 0
ORDER BY occurred_at ASC
LIMIT 20;
3-2. 자동 교정 실행 플로우
[1] error_logs 스캔 (미해결 건 조회)
│
↓
[2] 에러별 교정 등급 판단
│
├─ component + error_type 조합으로 등급 결정
│ (아래 3-3 매핑 테이블 참조)
│
↓
[3] 등급별 교정 실행
│
├─ L1: 즉시 재실행
│ ├─ auto_fix_attempted = 1
│ ├─ 교정 실행
│ └─ auto_fix_result = 'success' / 'failed'
│
├─ L2: 대기 후 재시도 (백오프)
│ ├─ retry_count 확인 (3 미만인 경우만)
│ ├─ auto_fix_attempted = 1
│ ├─ sleep(backoff) → 재실행
│ └─ auto_fix_result = 'success' / 'failed'
│
├─ L3: Fallback 전환 (Phase 2)
│ ├─ 대체 경로 조회
│ ├─ 대체 경로로 재실행
│ └─ auto_fix_action에 전환 내용 기록
│
├─ L4: 품질 재생성 (Phase 2)
│ ├─ 파라미터 조정
│ ├─ 재생성 실행
│ └─ 3회 실패 시 escalated=1
│
└─ L5: 에스컬레이션
├─ escalated = 1
├─ auto_fix_result = 'skipped'
└─ 알림 전송 (Phase 2: Telegram)
│
↓
[4] 결과 기록
│
├─ 성공: resolved_at = now, resolution_type = 'auto_fixed'
└─ 실패: auto_fix_result = 'failed'
(3회 실패 시 escalated = 1)
3-3. component + error_type → 교정 등급 매핑
| component | error_type | 교정 등급 | 자동 교정 액션 |
|---|---|---|---|
rss_collector | timeout | L1→L2 | 재시도 (timeout 확장) |
rss_collector | api_error (HTTP 5xx) | L1 | 5초 후 재시도 |
rss_collector | api_error (HTTP 4xx) | L3 | 대체 소스 전환 (Phase 2) |
rss_collector | validation_fail | L1 | 해당 피드 skip |
ai_generator | timeout | L2 | 30초 후 재시도 |
ai_generator | api_error | L2→L3 | 재시도 → 모델 전환 (Phase 2) |
ai_generator | auth_fail | L5 | 즉시 에스컬레이션 |
qa_checker | quality_fail | L2→L4 | 재생성 (온도 조정) |
publisher | timeout | L1 | 5초 후 재시도 |
publisher | validation_fail | L1 | slug 변경 후 재시도 |
publisher | auth_fail | L5 | 즉시 에스컬레이션 |
brevo | rate_limit | L2 | 60초 대기 → 다음 날 재예약 |
brevo | auth_fail | L5 | 즉시 에스컬레이션 |
brevo | api_error | L1→L2 | 재시도 → 파라미터 검증 |
brevo | validation_fail | L2 | 요청 파라미터 검증 후 재시도 |
sns_publisher | auth_fail (NO_ACCOUNTS) | L3 | 해당 플랫폼 skip |
sns_publisher | api_error | L1 | 30초 후 재시도 |
sns_publisher | timeout | L1 | 재시도 → 해당 플랫폼 skip |
scheduler | api_error | L2 | Cron 다음 실행 시 재시도 |
3-4. auto_fix 업데이트 플로우
-- 1단계: 교정 시도 시작
UPDATE error_logs
SET auto_fix_attempted = 1,
auto_fix_action = '교정 액션 설명'
WHERE id = ?;
-- 2단계-A: 교정 성공
UPDATE error_logs
SET auto_fix_result = 'success',
resolved_at = (unixepoch() * 1000),
resolution_type = 'auto_fixed'
WHERE id = ?;
-- 2단계-B: 교정 실패
UPDATE error_logs
SET auto_fix_result = 'failed'
WHERE id = ?;
-- 2단계-C: 에스컬레이션 (교정 불가 또는 3회 실패)
UPDATE error_logs
SET auto_fix_result = 'skipped',
escalated = 1
WHERE id = ?;
3-5. 에스컬레이션 트리거 조건
-- 동일 component에서 3회 연속 자동 교정 실패 확인
SELECT COUNT(*) as fail_count
FROM error_logs
WHERE component = ?
AND auto_fix_result = 'failed'
AND occurred_at > (unixepoch() * 1000 - 86400000) -- 최근 24시간
AND resolved_at IS NULL;
-- fail_count >= 3 → escalated = 1
4. 자체교정 코드 구조
4-1. 파일 구조
content-pipeline/src/lib/
└── self-healing.ts ← 자체교정 핵심 로직
├── detectErrors() — error_logs 미해결 에러 스캔
├── classifyError() — 에러 등급 판단 (L1~L5)
├── attemptAutoFix() — 등급별 자동 수정 실행
├── escalateIfNeeded() — 에스컬레이션 판단 + 처리
├── logFixAttempt() — 교정 시도/결과 error_logs 업데이트
└── runSelfHealingCycle() — 통합 실행 (Cron에서 호출)
4-2. 핵심 함수 명세
detectErrors(): Promise<ErrorLog[]>
미해결 에러를 error_logs에서 조회한다.
- 입력: 없음
- 출력: 미해결 ErrorLog 배열 (최대 20건)
- 쿼리:
resolved_at IS NULL AND escalated = 0조건 - 정렬:
occurred_at ASC(오래된 에러부터 처리)
classifyError(error: ErrorLog): HealingLevel
에러의 component와 error_type 조합으로 교정 등급을 판단한다.
- 입력: ErrorLog 객체
- 출력:
'L1' | 'L2' | 'L3' | 'L4' | 'L5' - 로직: 섹션 3-3 매핑 테이블 기반
- 특수 케이스:
auth_fail은 항상 L5
attemptAutoFix(error: ErrorLog, level: HealingLevel): Promise<FixResult>
등급에 따라 자동 교정을 실행한다.
- 입력: ErrorLog, HealingLevel
- 출력:
{ success: boolean, action: string, nextLevel?: HealingLevel } - L1: 동일 작업 즉시 재실행
- L2: 백오프 대기 후 재시도 (파라미터 조정 포함)
- L3: Fallback 경로 전환 후 재실행 (Phase 2)
- L4: 품질 파라미터 조정 후 재생성 (Phase 2)
- L5:
{ success: false, action: 'escalated' }반환
escalateIfNeeded(error: ErrorLog): Promise<boolean>
에스컬레이션 필요 여부를 판단하고, 필요 시 escalated=1 설정.
- 입력: ErrorLog
- 출력: boolean (에스컬레이션 발생 여부)
- 판단 기준:
error_type === 'auth_fail'→ 즉시- 동일 component 24시간 내 3회 교정 실패 → 에스컬레이션
- 전체 채널 실패 (content_distributions 전부 failed) → 에스컬레이션
runSelfHealingCycle(): Promise<HealingReport>
전체 자체교정 사이클을 실행한다. Cron 또는 파이프라인 시작 전에 호출.
- 입력: 없음
- 출력:
{ total: number, fixed: number, escalated: number, skipped: number } - 플로우:
detectErrors()호출 → 미해결 에러 목록- 각 에러에 대해
classifyError()→attemptAutoFix()→logFixAttempt() - 교정 실패 시
escalateIfNeeded()호출 - 결과 리포트 반환 (pipeline_logs metadata에 기록)
4-3. 타입 정의
type HealingLevel = 'L1' | 'L2' | 'L3' | 'L4' | 'L5';
interface FixResult {
success: boolean;
action: string; // 교정 액션 설명
nextLevel?: HealingLevel; // 실패 시 다음 시도 등급
}
interface HealingReport {
total: number; // 스캔된 에러 수
fixed: number; // 자동 교정 성공 수
escalated: number; // 에스컬레이션 수
skipped: number; // 교정 불필요/스킵 수
}
// 에러 분류 매핑 타입
interface ErrorClassification {
component: string;
errorType: string;
level: HealingLevel;
autoFixAction: string;
maxRetries: number;
backoffMs: number;
}
5. Cron 연계 방법
5-1. 파이프라인 실행 전 Self-Healing 선행
/api/cron/pipeline Cron 핸들러에서 파이프라인 실행 전에 자체교정 사이클을 먼저 실행한다.
/api/cron/pipeline 실행 (매일 KST 06:00, 월~금)
│
├─ [1] runSelfHealingCycle() ← 이전 실행 잔류 에러 교정
│ │
│ ├─ 미해결 에러 스캔 + 자동 교정 시도
│ └─ 결과 pipeline_logs 기록 (pipeline_name='self-healing')
│
├─ [2] Stage 1: collect ← RSS 수집
│ │
│ └─ 수집 중 에러 → 즉시 L1/L2 교정 (인라인)
│
├─ [3] Stage 2: generate ← AI 콘텐츠 생성
│ │
│ └─ 생성 중 에러 → 즉시 L1/L2/L4 교정 (인라인)
│
├─ [4] Stage 4: publish ← 승인된 콘텐츠 배포
│ │
│ └─ 배포 중 에러 → 즉시 L1/L2 교정 (인라인)
│
└─ [5] 최종 결과 기록
│
└─ pipeline_logs (전체 실행 결과 + self-healing 결과 metadata)
5-2. 자체교정 전용 Cron 분리 여부
Phase 1: 파이프라인 Cron과 통합 (별도 Cron 불필요)
- 파이프라인 실행이 1일 1회(KST 06:00)이므로, 그 시작 시
runSelfHealingCycle()호출로 충분 - 파이프라인 실행 중 발생하는 에러는 각 단계에서 인라인으로 L1/L2 교정
Phase 2+: 별도 Cron 고려
- 파이프라인 실행 빈도가 높아지면 (예: 1일 3회), self-healing 전용 Cron을 분리할 수 있음
/api/cron/self-healing— 매 6시간 실행, 누적 에러 교정
5-3. pipeline_logs 기록 형식
{
"pipeline_name": "self-healing",
"status": "completed",
"trigger_type": "scheduled",
"items_processed": 5,
"metadata": {
"total_errors": 5,
"fixed": 3,
"escalated": 1,
"skipped": 1,
"details": [
{"error_id": "err-001", "component": "rss_collector", "result": "success", "level": "L1"},
{"error_id": "err-002", "component": "brevo", "result": "escalated", "level": "L5"}
]
}
}
6. Phase별 구현 범위
Phase 1 MVP (1주): L1 + L2 + L5 에스컬레이션
구현 범위:
| 구현 항목 | 상세 |
|---|---|
| self-healing.ts 파일 생성 | detectErrors, classifyError, attemptAutoFix (L1/L2만), escalateIfNeeded, runSelfHealingCycle |
| L1 즉시 재시도 | RSS 재시도, DB 재연결, API 재시도, slug 변경 |
| L2 백오프 재시도 | Rate Limit 대기, 타임아웃 확장, QA 재생성 (기존 2회 재시도 로직 연계) |
| L5 에스컬레이션 기록 | error_logs.escalated=1 설정, 대시보드 표시 |
| Cron 연계 | /api/cron/pipeline 시작 시 runSelfHealingCycle() 호출 |
| error_logs 자동 기록 | 모든 파이프라인 단계에서 에러 발생 시 error_logs INSERT |
| pipeline_logs 기록 | self-healing 실행 결과를 pipeline_logs에 기록 |
Phase 1에서 하지 않는 것:
- L3 대체 전략 (RSS 소스 자동 교체, AI 모델 전환)
- L4 품질 강등 (프롬프트 파라미터 동적 조정)
- Telegram 에스컬레이션 알림 (대시보드 표시만)
- 자체교정 전용 Cron 분리
- 자체교정 성공률 대시보드
Phase 2 (2주): L3 대체 전략 + L4 품질 강등 + 알림
구현 범위:
| 구현 항목 | 상세 |
|---|---|
| L3 대체 전략 | RSS 소스 자동 교체, SNS 플랫폼별 skip, AI 모델 fallback (Gemini→Claude) |
| L4 품질 강등 | 프롬프트 온도/길이 동적 조정, content_generation_config 연계, 3회 실패 시 holding |
| Telegram 에스컬레이션 알림 | escalated=1 시 vice-reply.sh/ceo-reply.sh 자동 호출 |
| 대체 소스 매핑 DB화 | RSS 소스별 대체 URL을 channels config에 저장 |
| optimization_history 연계 | L4 파라미터 변경 시 optimization_history에 기록 |
| 에러 패턴 분석 | 동일 component/error_type 반복 횟수 추적, 패턴 기반 사전 교정 |
Phase 3 (3주+): 고도화
구현 범위:
| 구현 항목 | 상세 |
|---|---|
| 자체교정 성공률 대시보드 | 최근 7일/30일 교정 성공률 시각화 (목표 80%+) |
| 자체교정 전용 Cron | /api/cron/self-healing (매 6시간) |
| 예측적 교정 | error_logs 패턴 학습 → 장애 예측 → 사전 조치 (특정 시간대 피드 실패 예측 등) |
| 교정 히스토리 분석 | 어떤 교정 액션이 가장 효과적인지 통계 분석 |
| 자동 채널 비활성화 | 특정 채널 7일 연속 실패 시 channels.is_active=0 자동 전환 |
7. 전체 자체교정 데이터 흐름
파이프라인 실행 (Cron / 수동)
│
├─ [선행] runSelfHealingCycle()
│ ├─ error_logs 스캔 (미해결 건)
│ ├─ 등급 판단 → 자동 교정 시도
│ ├─ 성공: resolved_at 기록
│ ├─ 실패: escalated=1
│ └─ pipeline_logs 기록 (self-healing 결과)
│
├─ Stage 1~4 실행
│ ├─ 에러 발생 시:
│ │ ├─ error_logs INSERT (component, error_type, error_message)
│ │ ├─ 인라인 L1/L2 교정 시도
│ │ ├─ 성공: auto_fix_result='success', resolved_at 기록
│ │ └─ 실패: auto_fix_result='failed'
│ │ (다음 runSelfHealingCycle에서 재시도)
│ │
│ └─ 정상 완료 시:
│ └─ pipeline_logs 기록 (status='completed')
│
└─ 대시보드 반영
├─ /api/pipeline/errors → 미해결 에러 목록 (escalated 우선)
├─ /api/pipeline/logs → self-healing 실행 이력
└─ 에러 카운트 배지 (미해결 N건 표시)
리뷰 로그
[self-healing-pl 초안 작성] 2026-02-25 19:30
- L1~L5 등급별 자체교정 시나리오 상세 설계 완료 (파이프라인 설계서 섹션 3 기반 확장)
- error_logs 기반 자동 교정 메커니즘: 스캔→분류→교정→기록 4단계 플로우
- component + error_type → 교정 등급 매핑 테이블 18개 시나리오
- self-healing.ts 코드 구조: 6개 핵심 함수 명세 (detectErrors, classifyError, attemptAutoFix, escalateIfNeeded, logFixAttempt, runSelfHealingCycle)
- Cron 연계: 파이프라인 실행 전 self-healing 선행 실행 설계
- Phase별 구현 범위: Phase 1(L1+L2+L5), Phase 2(L3+L4+알림), Phase 3(예측적 교정)
- DB 설계서 error_logs 테이블과 완전 연계 (auto_fix_attempted, auto_fix_result, escalated, resolved_at, resolution_type)
- 자비스 1차 검수 요청
[자비스 1차 검수] 2026-02-25 19:45
검수 결과: 수정 없이 승인 ✅ (9개 항목 전부 통과)
- ✅ L1~L5 등급 상세화 — 파이프라인 설계서 기반 적용 범위(Stage별/연동별) 완전 명세
- ✅ 18개 시나리오 매핑 — component+error_type 조합 테이블로 구현 모호성 제거
- ✅ auth_fail 통일 — 모든 component에서 L5 즉시 에스컬레이션으로 일관성 확보
- ✅ Phase MVP 범위 명확 — Phase 1(L1+L2+L5만), "하지 않는 것" 명시
- ✅ error_logs DB 완전 연계 — auto_fix_attempted/result/action, escalated, resolved_at, resolution_type 전부 활용 시점 명세
- ✅ self-healing.ts 6개 함수 — detectErrors/classifyError/attemptAutoFix/escalateIfNeeded/logFixAttempt/runSelfHealingCycle 명세 완전
- ✅ Cron 선행 실행 — 파이프라인 실행 전 runSelfHealingCycle() 호출로 잔류 에러 선처리
- ✅ Telegram 보안 준수 — Phase 2에서도 vice-reply.sh/ceo-reply.sh 간접 호출
- ✅ SQL 명세 완전 — 스캔 쿼리 + auto_fix 업데이트 3분기(성공/실패/에스컬레이션) SQL 포함
특이사항: sns_publisher auth_fail → L3(해당 플랫폼 skip) 처리는 이 경우가 실제 "인증 실패"가 아닌 "계정 미연결(NO_ACCOUNTS)"이어서 L3가 더 적절. 의도적 설계로 판단. ✅