Files
HC900-Crawler/docs/작업플랜-셀프서비스-분석리포트-MVP.md
windpacer 37a464ab96 feat(report): P0 셀프서비스 결정론 리포트 — 메트릭 3종·엑셀 토큰 채움·fastRecord 소스
운전원이 올린 엑셀 템플릿의 {{ metric=...; column=... }} 토큰을, 선택한 날짜의
결정론 계산값으로 채워 다운로드하는 셀프서비스 리포트 레이어(P0).

- 메트릭 3종: energy_efficiency·yield·control_residual (분 버킷 피벗, 클린필터,
  KST→UTC 경계). history_table(60s)·fast_record(s/min) 동일 long 포맷이라 source만 교체.
- 컬럼→태그 매핑은 기존 appsettings SteamAdvisor:Columns 재사용(7컬럼 무료).
- EPPlus 토큰 치환 + 셀 주석에 해상도 메타(source/sampling/n/keep) 부착.
- report_template/report_run 테이블 + cells_json 감사 박제.
- 리포트 탭(웹 UI) + 샘플 템플릿.

검증: 빌드 0에러. E2E 라운드트립 실동작(2026-05-15 C-6111 효율 0.778·수율 0.872·
잔차 mean 0.746 — 오프라인 검증값과 일치). 결정론 검증 게이트 준수(표본0=N/A, 0 날조 금지).

⚠️ EPPlus는 NonCommercial 컨텍스트 — 상용 출시 전 라이선스 정리 필요.

설계: docs/작업플랜-셀프서비스-분석리포트-MVP-P0-상세설계.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 00:14:35 +09:00

8.6 KiB
Raw Blame History

작업 플랜 — 셀프서비스 결정론 분석·리포트 레이어 (MVP 아키텍처 스케치)

2026-06-12. 출처: 논의-AI운전원-제어-아이디어.md §방향전환. 제품 한 줄: "운전원 소유의, 결정론적·해상도 가변 캡처→분석→리포트 레이어 — DCS/MES가 못 하고 전산팀을 안 거치는." 데이터 자체가 상품 → 거기에 의미층(KB/태그매핑) + 결정론 계산 + 운전원 포맷을 얹어 판다.


0. 핵심 설계 전제 (이미 성립)

전제 근거 (현 코드)
캡처 2소스가 동일 long 포맷 (tagname, recorded_at, value) history_table(60s 상시) · fast_record(on-demand s/min, FastController)
→ 메트릭 SQL은 소스 테이블만 파라미터로 양쪽 동작 "해상도 가변"이 추가비용 0
엑셀 폼 읽기/쓰기 인프라 존재 wwwroot/js/xlsx.full.min.js (SheetJS) 클라이언트 탑재
캡처 UI/세션관리 가동 FastController(start/stop/sessions), FastSession(sampling_ms·duration_sec·tag_list·retention)
의미층(moat) 존재 tag_metadata + KB 문서(단일진실원) + loop→필드계기 매핑 + pid_equipment
시각화 패턴 존재 온도프로파일/trend.js, fast.html 패널

1. 컴포넌트 (레이어)

┌─ 캡처 레이어 (Source) ────────────────────────────────────┐
│  history_table (상시 60s)   │   fast_record (on-demand s/min) │
│            └──────────── 동일 스키마 ─────────────┘           │
└──────────────────────────┬──────────────────────────────────┘
                           ▼
┌─ 의미층 (Semantic / moat) ──────────────────────────────────┐
│  tag_metadata · KB 문서 · loop→필드계기 매핑 · pid_equipment   │
│  "C-6111 효율" → 구체 태그/공식/단위 resolve                   │
└──────────────────────────┬──────────────────────────────────┘
                           ▼
┌─ 메트릭 엔진 (결정론 로직 = 오늘 내가 짠 SQL의 승격) ────────────┐
│  Metric(source, tags|loop|column, period) → value+meta         │
│  · 자동 데이터 클리닝(드롭아웃/양자화 필터)                      │
│  · 출력 메타: source, sampling_ms, n, cleaned_fraction          │
└──────────────────────────┬──────────────────────────────────┘
              ┌────────────┴────────────┐
              ▼                         ▼
┌─ 시각화 ────────────┐   ┌─ 리포트/폼 바인딩 (= 돈) ──────────────┐
│ 기간선택 → 메트릭     │   │ 운전원 엑셀폼(named cells) = 계약       │
│ 곡선+이상플래그+숫자  │   │ → 엔진이 값 채움 → Daily/Monthly/Yearly │
│ (온도프로파일 일반화) │   │ → 다운로드 (SheetJS/ClosedXML)         │
└─────────────────────┘   └─────────────────────────────────────┘

2. 메트릭 레지스트리 (오늘 작업의 제품화)

각 메트릭 = 순수 함수: (source_table, 대상[column|loop|tags], period) → {values, meta}. 선언적 정의(레지스트리/config, 하드코딩 금지):

metric id 정의 필요 태그(의미층이 resolve) 최소 sampling 출처(오늘 검증)
energy_efficiency steam/product (컬럼별) 리보일러 스팀 / 제품유량 (C-6111: FIQ-6115/FICQ-6118) 60s 검증 2·3회차
yield product/feed FICQ-6118/FICQ-6101 60s
control_residual (PVSP) 통계 (mean/sd/p95/이탈%) 루프 .PV/.SP 60s
excursion_time 민감단 목표대역 밖 체류% · 크기 · 빈도 T_C(TI-6111C) + 대역 60s 검증 2회차
settling 조건변경 후 재정착 일수 · 페널티 feed/T_C/steam/prod 검증 3회차 (/tmp/settling_probe.py)
dynamics ★fast FOPDT τ/deadtime, 오버슈트, 정착, 밸브 stiction/헌팅 루프 PV/OP/SP ≤1s (fast_record 필수) 미구현(주춧돌)

규칙:

  • 모든 메트릭은 자동 클리닝 내장(오늘 손으로 한 value BETWEEN ..., 0/스파이크 제거, KST/UTC). 채널별 양자화/RTD레인지 주의(메모리 참조).
  • 모든 출력에 sampling 컨텍스트 동봉 → 리포트 비교 안전성.
  • 결정론 검증 게이트: 빈 결과/날조 금지, 실패는 명시적 에러(메모리 deterministic-verification-gate).

3. 리포트/폼 바인딩 (핵심 상품)

계약 = 운전원이 만든 .xlsx 템플릿. 셀/네임드레인지에 메트릭 참조를 박는다:

예) 셀 B5 주석/네임:  {{ energy_efficiency | column=C-6111 | period=DAILY }}
    셀 C5:           {{ control_residual.sd | loop=TICA-6111A | period=DAILY }}
    범위 A10:G40:    {{ table: excursion_events | column=C-6111 | period=DAILY }}
  • 엔진이 플레이스홀더 파싱 → 메트릭 실행 → 그 위치에 값/표/미니차트 주입 → 다운로드.
  • 포맷 변경 = 운전원이 엑셀에서 셀 옮기고 토큰 바꾸면 끝. 전산팀 0, 리드타임 0.
  • 구현 선택지: 서버 ClosedXML/EPPlus(스케줄 배치용) + 클라이언트 SheetJS(즉시 미리보기/수동 export).

4. MVP 슬라이스 (가장 작은 판매가능 단위)

  1. 메트릭 3종(energy_efficiency, yield, control_residual)을 history_table 위 레지스트리 함수로 구현(오늘 SQL 승격).
  2. 운전원 엑셀 템플릿 1개 + 토큰 파서 → 선택 날짜로 채워 다운로드(ClosedXML).
  3. 같은 메트릭을 fast_record 소스로도 실행해 "해상도 가변" 실증(동일 코드, source만 교체).
  4. 시각화는 온도프로파일/trend.js 재활용해 메트릭 곡선 + 이상 플래그. → 데모 시나리오: "운전원이 자기 엑셀폼 올림 → 어제 날짜 선택 → 컬럼별 효율·수율·제어잔차가 그 폼 그대로 채워져 내려옴."

5. 스키마/잡 추가(최소)

  • metric_definition(id, formula_ref, required_tags_rule, min_sampling, unit, version) — 감사·버전.
  • report_template(id, name, owner, xlsx_blob, token_map) · report_run(template_id, period, generated_at, source, status, file).
  • Daily/Monthly/Yearly 자동생성 = 기존 Hc900HistoryServiceBackgroundService 패턴으로 스케줄.

6. 리스크 / 반드시 못박을 것

  • 정의 거버넌스: "효율/수율"의 컬럼별 공식은 합의·서명 필요 → 공식+버전을 리포트에 박아 감사 가능하게. 컬럼별 steam/product 매핑은 KB 문서(플랜트별)에서 확장.
  • 해상도 혼동: §2 sampling 메타 필수(안 하면 1s vs 60s 통계 오해).
  • 데이터 품질: 채널별 양자화/RTD레인지/드롭아웃 자동처리 — 메트릭이 "사람이 하기 힘든 부분"을 대신하는 핵심 가치.
  • 타임존: recorded_at=UTC, 운전원 리포트=KST(+9) — 엔진 단일 처리.
  • fast_record 보존/스토리지: on-demand·retention_days로 폭증 방지(이미 필드 존재).

7. 단계 (제안)

  • P0 (MVP): §4 슬라이스 — 메트릭 3종 + 엑셀폼 1개 + history 소스 + 1컬럼(C-6111). 상세 코딩설계 → 작업플랜-셀프서비스-분석리포트-MVP-P0-상세설계.md
  • P1: fast_record 소스 + dynamics 메트릭(루프 stiction/헌팅, step-test 셀프서비스).
  • P2: 토큰 파서 일반화 + 템플릿 업로드 UI + Daily 스케줄 자동생성.
  • P3: 멀티컬럼/멀티플랜트(KB 매핑 확장) + Monthly/Yearly + 모델학습 데이터 적재 연계.

근거: 본 세션 검증 1~3회차(에너지/품질 결정론 통계), FastController/fast_record, xlsx.full.min.js, tag_metadata+KB. 관련: plant-knowledge-document-first, deterministic-verification-gate, loop-field-instrument-value-mapping.