Files
ExperionCrawler/fastTable/idea-fastTable.md
2026-04-30 08:16:21 +09:00

10 KiB
Raw Blame History

fastTable fastRecord 필요성

- 현재 데이터 저장 간격(1분) 으로는 상세한 필드 데이터의 변동을 캐치 하기 힘듬.
- 정해진 시간동안 초 단위로 데이터를 받아서 평균을 넘어서는 데이터 분류 등에 분석을 위한 데이터 재료로 사용

Expected Fucnctional Act Sequence

- UI : 에서 최대 8개 까지 태그명을 선정 및 수집기간(시간 , 일) 선정 하고 시작하면, 
- 테이블 완성() 테이블은 미리 만들어 놓은 형태여도 좋고, 컬럼의 태그명만 바꾸는 방식도 좋다
- OPC UA 서버로 부터 받는 Realtime 테이블에서 선정된 태그값을 초 단위 (사용자 지정 가능)로 데이터 수집
- 정해진 시간이 만료되면 수집동작 종료
- 수집되고 있는 또는 수집된 데이터를 realtime trend graph로 표시
- UI : 사용자 필요에 따라 전체 테이블 내용 또는 부분 시간 구간을 Excel로 Export 할수있게
- UI : 테이블 삭제 또는 데이터로 보관 가능? 하게

Claude 가 더 추가하거나 유용한 방식이 있으면 아래에 적어주세요


추가 아이디어 (Claude 제안, 2026-04-28)

핵심 설계 결정

1. 데이터 출처 — 별도 OPC UA Subscription 신설 권장

  • 기존 ExperionRealtimeService의 Subscription은 SamplingInterval 500ms / PublishingInterval 1000ms로 고정
  • fastRecord는 분해능이 핵심이므로 별도 Subscription 생성:
    • SamplingInterval: 100/250/500/1000ms 중 사용자 선택
    • PublishingInterval: SamplingInterval과 동일하게
    • 세션 종료 시 Subscription dispose → 평소엔 부하 없음
  • 대안(기존 _pendingUpdates ConcurrentDictionary 폴링)은 분해능 한계(500ms) 때문에 부적합

2. 스토리지 — 단일 hypertable + session_id 컬럼 (Long 형태)

fast_session (메타)
  id, name, started_at, ended_at, status, sampling_ms,
  duration_sec, tag_list (jsonb), row_count, retention_days, pinned

fast_record (TimescaleDB hypertable)
  session_id, recorded_at, tagname, value
  → hypertable on recorded_at, chunk_time_interval = 1 day
  → index (session_id, tagname, recorded_at)
  • Long 형태(태그 1행/시점) 권장 이유: 태그 개수 가변, 태그별 NULL 처리 단순, TimescaleDB 압축 효율
  • 조회 시 서버 또는 클라이언트에서 PIVOT → Wide 변환 (그래프/Excel용)

3. 데이터 규모 추정

시나리오 행수 비고
8태그 × 1s × 1시간 28,800 즉시 처리
8태그 × 1s × 24시간 691,200 TimescaleDB 무난
8태그 × 100ms × 1시간 288,000 TimescaleDB 권장
8태그 × 100ms × 24시간 6,912,000 retention/압축 필수
  • 세션당 최대 행수 가드(예: 5,000,000) → 도달 시 자동 종료 + 상태 RowLimitReached

4. 세션 상태 머신

Pending → Running → Completed
                 ↘ Cancelled (사용자 중지)
                 ↘ Failed     (OPC 연결 끊김 등)
                 ↘ RowLimitReached
  • 동시 Running 세션 최대 N개 제한(권장 3개) — OPC UA Subscription 부하 고려
  • 앱 재기동 시 Running 세션은 Failed 처리(중간값 보존, 재개 X — 단순화)

추가 기능 제안

5. 실시간 트렌드 그래프 — uPlot 권장

  • Chart.js: 친숙하지만 10만점 초과 시 버벅임
  • uPlot: 시계열 특화, 100만점도 부드러움. CDN 단일 파일(~50KB)
  • 다운샘플링: LTTB 알고리즘으로 화면 픽셀 폭에 맞춰 축소(예: 화면 1200px → 1200점)
  • 라이브 갱신: 1~2초 간격 폴링으로 새 데이터만 append

6. 통계 + 이상치 분석 (사용자가 언급한 "평균을 넘어서는 데이터 분류")

  • 세션 종료 후 또는 실시간 패널에 표시:
    • 태그별 mean / stddev / min / max / median / p95 / p99
    • 이상치 강조: |value - mean| > k × stddev (k 사용자 설정, 기본 3)
    • 임계값 알람: 태그별 상/하한 설정 → 초과 구간 그래프에 색상 강조
    • 변화율(slope): Δvalue/Δt 급변 구간 표시
  • DB 부하 없이 클라이언트 JS로 계산 가능 (8태그 × ~30만점 수준)

7. Excel/CSV Export — 클라이언트 사이드

  • xlsx.full.min.js가 이미 wwwroot에 추가되어 있음 → 즉시 활용
  • Wide 포맷: recorded_at | tag1 | tag2 | ...
  • 옵션: 전체 / 그래프 현재 줌 구간만 / 시간 슬라이더로 지정한 구간
  • 행수 50,000 초과 시 CSV 권장 (Excel 시트당 1,048,576행 제한 고려)
  • 큰 세션은 서버에서 스트리밍 응답(text/csv)으로 제공하는 엔드포인트 추가 권장

8. 보관/정리 정책

  • 세션별 retention_days 필드 (기본 30, 무한=NULL)
  • pinned 플래그(불 표시) → 자동 정리 제외
  • ExperionFastCleanupService BackgroundService — 일 1회 새벽 만료 세션 + 데이터 삭제
  • TimescaleDB drop_chunks 활용 가능

9. 사용성 개선

  • 세션 템플릿: 자주 쓰는 태그 조합 + 설정 저장 → 원클릭 시작
  • 진행률 표시: (현재행수 / 예상행수) × 100, 남은 시간 추정
  • 다중 태그 단위 그룹: 같은 단위 태그를 같은 Y축으로 묶고 다른 단위는 보조 Y축
  • 태그별 색상 자동 할당 + 토글로 표시/숨김
  • 그래프 위에 마우스 호버 → 모든 태그의 해당 시점 값 툴팁
  • 시간 동기화 표시: 서버 시각(UTC) ↔ 브라우저 KST 변환 (이력 조회와 동일 패턴)

10. Subscription 동시성 / 안전성

  • 같은 nodeId를 여러 fast 세션이 동시 구독해도 OPC SDK가 처리 — 단, 각 Subscription 별도 비용
  • 세션 시작 시 노드 유효성 사전 검증(Read 단발) → bad이면 시작 거부
  • OPC 연결 끊김 시 → 세션 자동 Failed + 그때까지 데이터 보존
  • 메모리 보호: 콜백마다 직접 INSERT가 아니라 기존 패턴(ConcurrentDictionary 버퍼 + 1~2초 배치 INSERT)

11. 라이브 vs 완료 화면 통합

  • 동일 화면에서 상태에 따라 컨트롤만 다르게:
    • Running: [중지] 버튼, 라이브 갱신 ON, 진행률
    • Completed: [Excel] [CSV] [삭제] [고정/해제] 버튼, 통계 패널, 줌/팬

구현 플랜

전체 구조

[OPC UA Server]
      │
      ├──(기존) Subscription 1 → realtime_table → history_table (60s)
      │
      └──(신규) Subscription per fastSession
              ├── 콜백 → ConcurrentDictionary 버퍼
              └── 2s 배치 → fast_record (TimescaleDB hypertable)

Task A — DB 스키마 + 엔티티

파일 작업
ExperionEntities.cs FastSession, FastRecord 엔티티 추가
ExperionDbContext.cs DbSet<FastSession>, DbSet<FastRecord>, 테이블 DDL, hypertable 생성(SELECT create_hypertable('fast_record', 'recorded_at', if_not_exists => TRUE))
IExperionServices.cs IExperionFastService 인터페이스 + FastSessionStatus/FastSessionInfo/FastQueryResult record

Task B — FastService (백그라운드 + 컨트롤러)

파일 작업
Infrastructure/OpcUa/ExperionFastService.cs (신규) IHostedService + IExperionFastService 구현. 세션별 Subscription 관리, 콜백 → 버퍼, FlushLoop 2s, 자동 종료(만료/행수초과/외부중지)
ExperionDbContext.cs BatchInsertFastRecordsAsync(IEnumerable<FastRecord>), GetFastSessionsAsync(), GetFastRecordsAsync(sessionId, from?, to?), DeleteFastSessionAsync(sessionId)
Web/Controllers/ExperionControllers.cs ExperionFastController 추가:
POST /api/fast/start (tags, samplingMs, durationSec, name, retentionDays)
POST /api/fast/{id}/stop
GET /api/fast/sessions
GET /api/fast/{id} (세션 메타)
GET /api/fast/{id}/records?from&to&format=long|wide
GET /api/fast/{id}/csv (스트리밍)
DELETE /api/fast/{id}
POST /api/fast/{id}/pin
Web/Program.cs ExperionFastService Singleton + HostedService 등록
Web/appsettings.json Fast 섹션 — MaxConcurrentSessions:3, MaxRowsPerSession:5000000, FlushIntervalMs:2000

Task C — UI: 09 fastRecord 탭

파일 작업
wwwroot/index.html 사이드바 09번 pane-fast 섹션 추가:
- 좌측: 세션 목록(상태/이름/태그수/시작시각/진행률)
- 우측 상단: [신규 세션] 버튼 → 모달(태그 선택 8개, 샘플링 select, 기간 select, 이름, retention)
- 우측: 선택 세션의 트렌드 그래프 + 통계 + 이상치 패널 + Export 버튼
wwwroot/lib/uPlot.iife.min.js uPlot 라이브러리 추가 (CDN에서 다운로드한 파일)
wwwroot/lib/uPlot.min.css uPlot 스타일
wwwroot/js/app.js fastSessionsLoad(), fastStart(), fastStop(id), fastDelete(id), fastPin(id), fastSelect(id), fastRenderChart(), fastRenderStats(), fastExportXlsx(), fastExportCsv(), fastLivePollStart/Stop
wwwroot/css/style.css .fast-session-list, .fast-progress, .fast-stats-grid, .fast-outlier, 모달 스타일

Task D — 정리/보관 백그라운드

파일 작업
Infrastructure/OpcUa/ExperionFastCleanupService.cs (신규) BackgroundService — 일 1회(03:00) 만료된 세션 + record 삭제. pinned=true 제외
Web/Program.cs HostedService 등록

Task E — 안정성 / QA

  • 노드 유효성 사전 검증(시작 시 Read 1회) — bad이면 400 반환
  • 동시 세션 수 제한 검사 — 초과 시 409
  • 세션 시작 시 OPC UA 연결 상태 확인 — 연결 안되어 있으면 400
  • 앱 종료 시 Running 세션 graceful 마무리(현재 버퍼 flush 후 status=Cancelled)
  • 앱 시작 시 Running 상태 잔류 세션 → Failed 마킹
  • 단위/통합 테스트는 기존 패턴 따름(현 프로젝트엔 테스트 없음 — 수동 QA 시나리오 문서화)

Task F — 문서화

  • CLAUDE.md에 작업 이력 항목 추가
  • appsettings.json 신규 키 설명

우선순위 추천

  1. MVP: Task A + B(start/stop/sessions/records 엔드포인트 4개) + C(목록/시작/중지/단순 그래프) — 핵심 가치 검증
  2. 분석: 통계 패널 + 이상치 강조 + 임계값
  3. Export: xlsx + csv 스트리밍
  4. 운영: Task D 정리, retention/pinned, 동시성 제한, 진행률
  5. 고급: 템플릿, 다중 Y축, LTTB 다운샘플링 최적화