iran 프로젝트의 gear-parent-flow 패턴을 차용하여 시스템 전체 데이터 흐름을
노드/엣지로 시각화하는 별도 React 앱 추가. 메인 SPA와 완전 분리.
## 인프라
- @xyflow/react 추가
- frontend/system-flow.html (별도 entry HTML)
- frontend/src/systemFlowMain.tsx (React entry)
- vite.config.ts: rollupOptions.input에 systemFlow 추가
- 빌드 산출물: dist/system-flow.html + dist/assets/systemFlow-*.js (231kB, 메인과 분리)
## 매니페스트 (frontend/src/flow/manifest/)
카테고리별 JSON 분할 + 빌드 시 병합:
- 01-ingest.json (6) — snpdb, vessel_store, refresh
- 02-pipeline.json (7) — 7단계 분류 파이프라인
- 03-algorithms.json (12) — zone/dark/spoofing/risk/transship 등
- 04-fleet.json (9) — fleet_tracker, polygon_builder, gear_correlation, parent_inference
- 05-output.json (8) — event/violation/kpi/stats/alert/redis
- 06-storage.json (18) — 핵심 DB 테이블
- 07-backend.json (15) — Spring Boot 컨트롤러 + endpoint
- 08-frontend.json (17) — 프론트 화면 (menu 매핑 포함)
- 09-decision.json (8) — 운영자 의사결정 액션
- 10-external.json (2) — iran, redis
- edges.json (133) — data/trigger/feedback 분류
## 뷰어 컴포넌트
- SystemFlowViewer.tsx — 3단 레이아웃 + React Flow + 상태 관리
- components/FilterBar.tsx — 검색/단계/메뉴/상세필터 + 레이아웃 토글
- components/NodeListSidebar.tsx — 좌측 카테고리별 노드 리스트
- components/NodeDetailPanel.tsx — 우측 선택 정보 + incoming/outgoing 흐름
- components/nodeShapes.ts — kind별 모양/색상 헬퍼
- SystemFlowViewer.css — 전용 다크 테마 스타일
## 기능
- stage(단계) ⇄ menu(메뉴) 두 가지 그룹화 토글
- 통합 검색 (label/file/symbol/tag)
- 다중 필터 (kind/trigger/status)
- 노드 모양: kind별 (algorithm=다이아몬드, decision=마름모, api=6각형 등)
- 엣지 색상: data=회색, trigger=녹색, feedback=노란 점선
- 딥링크: /system-flow.html#node=<id> (산출문서에서 직접 참조)
## /version 스킬 통합
- CLAUDE.md에 "/version 스킬 사후 처리" 섹션 추가
Claude가 /version 호출 후 자동으로 manifest.meta version/updatedAt/releaseDate 갱신
- .gitea/workflows/deploy.yml에 archive 보존 단계 추가
/deploy/kcg-ai-monitoring-archive/system-flow/v{version}_{date}/ 영구 누적
(nginx 노출 X, 서버 로컬 보존)
- docs/system-flow-guide.md 작성 (URL, 노드 ID 명명, 산출문서 참조법, 갱신 절차)
## URL
- 운영: https://kcg-ai-monitoring.gc-si.dev/system-flow.html
- 메인 SPA에 링크 노출 없음 (개발 단계 페이지)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
173 lines
5.7 KiB
JSON
173 lines
5.7 KiB
JSON
[
|
|
{
|
|
"id": "api.events_get",
|
|
"label": "GET /api/events",
|
|
"shortDescription": "이벤트 목록 조회",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "on_demand",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/event/EventController.java",
|
|
"symbol": "EventController.list",
|
|
"inputs": ["prediction_events"]
|
|
},
|
|
{
|
|
"id": "api.events_ack",
|
|
"label": "PATCH /api/events/{id}/ack",
|
|
"shortDescription": "이벤트 확인 처리",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "user_action",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/event/EventController.java",
|
|
"symbol": "EventController.ack",
|
|
"outputs": ["event_workflow"]
|
|
},
|
|
{
|
|
"id": "api.events_status",
|
|
"label": "PATCH /api/events/{id}/status",
|
|
"shortDescription": "이벤트 상태 변경",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "user_action",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/event/EventController.java",
|
|
"symbol": "EventController.updateStatus",
|
|
"outputs": ["event_workflow"]
|
|
},
|
|
{
|
|
"id": "api.alerts_get",
|
|
"label": "GET /api/alerts",
|
|
"shortDescription": "경보 목록 조회",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "on_demand",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/event/AlertController.java",
|
|
"symbol": "AlertController.list",
|
|
"inputs": ["prediction_alerts"]
|
|
},
|
|
{
|
|
"id": "api.stats_kpi",
|
|
"label": "GET /api/stats/kpi",
|
|
"shortDescription": "실시간 KPI 조회",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "on_demand",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/stats/StatsController.java",
|
|
"symbol": "StatsController.kpi",
|
|
"inputs": ["prediction_kpi_realtime"]
|
|
},
|
|
{
|
|
"id": "api.stats_hourly",
|
|
"label": "GET /api/stats/hourly",
|
|
"shortDescription": "시간별 통계 조회",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "on_demand",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/stats/StatsController.java",
|
|
"symbol": "StatsController.hourly"
|
|
},
|
|
{
|
|
"id": "api.stats_daily",
|
|
"label": "GET /api/stats/daily",
|
|
"shortDescription": "일별 통계 조회",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "on_demand",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/stats/StatsController.java",
|
|
"symbol": "StatsController.daily"
|
|
},
|
|
{
|
|
"id": "api.stats_monthly",
|
|
"label": "GET /api/stats/monthly",
|
|
"shortDescription": "월별 통계 조회",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "on_demand",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/stats/StatsController.java",
|
|
"symbol": "StatsController.monthly"
|
|
},
|
|
{
|
|
"id": "api.enforcement_records",
|
|
"label": "GET/POST /api/enforcement/records",
|
|
"shortDescription": "단속 결과 조회/등록",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "user_action",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/enforcement/EnforcementController.java",
|
|
"symbol": "EnforcementController.records"
|
|
},
|
|
{
|
|
"id": "api.enforcement_plans",
|
|
"label": "GET/POST /api/enforcement/plans",
|
|
"shortDescription": "단속 계획 조회/생성",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "user_action",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/enforcement/EnforcementController.java",
|
|
"symbol": "EnforcementController.plans"
|
|
},
|
|
{
|
|
"id": "api.parent_inference_review",
|
|
"label": "GET /api/parent-inference/review",
|
|
"shortDescription": "모선 추론 리뷰 큐 조회",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "on_demand",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/fleet/ParentInferenceWorkflowController.java",
|
|
"symbol": "ParentInferenceWorkflowController.review"
|
|
},
|
|
{
|
|
"id": "api.parent_inference_confirm",
|
|
"label": "POST /api/parent-inference/groups/{key}/{sub}/review",
|
|
"shortDescription": "모선 후보 확정/반려",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "user_action",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/fleet/ParentInferenceWorkflowController.java",
|
|
"symbol": "ParentInferenceWorkflowController.confirm"
|
|
},
|
|
{
|
|
"id": "api.parent_inference_exclusions",
|
|
"label": "GET/POST /api/parent-inference/exclusions",
|
|
"shortDescription": "후보 배제 목록 관리",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "user_action",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/fleet/ParentInferenceWorkflowController.java",
|
|
"symbol": "ParentInferenceWorkflowController.exclusions"
|
|
},
|
|
{
|
|
"id": "api.parent_inference_label_sessions",
|
|
"label": "GET/POST /api/parent-inference/label-sessions",
|
|
"shortDescription": "정답 라벨링 세션 관리",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "user_action",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/fleet/ParentInferenceWorkflowController.java",
|
|
"symbol": "ParentInferenceWorkflowController.labelSessions"
|
|
},
|
|
{
|
|
"id": "api.vessel_analysis",
|
|
"label": "GET /api/vessel-analysis",
|
|
"shortDescription": "선박 분석 결과 (iran 프록시)",
|
|
"stage": "API",
|
|
"kind": "api",
|
|
"trigger": "on_demand",
|
|
"status": "implemented",
|
|
"file": "backend/src/main/java/gc/mda/kcg/domain/analysis/VesselAnalysisProxyController.java",
|
|
"symbol": "VesselAnalysisProxyController.list"
|
|
}
|
|
]
|