e5d123e4c5
feat(prediction): dark 의심 점수화 + transship 베테랑 관점 재설계
...
12h 누적 분석 결과 dark/transship이 운영 불가 수준으로 판정되어
탐지 철학을 근본부터 전환.
## dark 재설계: 넓은 탐지 + 의도적 OFF 의심 점수화
기존 "필터 제외" 방식에서 "넓게 기록 + 점수 산출 + 등급별 알람"으로 전환.
해경 베테랑 관점의 8가지 패턴을 가점 합산하여 0~100점 산출.
- P1 이동 중 OFF (gap 직전 SOG > 2kn)
- P2 민감 수역 경계 근처 OFF (영해/접속수역/특정조업수역)
- P3 반복 이력 (7일 내 재발) — 가장 강력
- P4 gap 후 이동거리 비정상 (은폐 이동)
- P5 주간 조업 시간 OFF
- P6 gap 직전 이상 행동 (teleport/급변)
- P7 무허가 선박 가점
- P8 장기 gap (3h/6h 구간별)
- 감점: gap 시작 위치가 한국 AIS 수신 커버리지 밖
완전 제외:
- 어구 AIS (GEAR_PATTERN 매칭, fleet_tracker SSOT)
- 한국 선박 (MMSI 440*, 441*) — 해경 관할 아님
등급: CRITICAL(70+) / HIGH(50~69) / WATCH(30~49) / NONE
이벤트는 HIGH 이상만 생성 (WATCH는 DB 저장만).
신규 함수:
- algorithms/dark_vessel.py: analyze_dark_pattern, compute_dark_suspicion
- scheduler.py: _is_dark_excluded, _fetch_dark_history (사이클당 1회 7일 이력 일괄 조회)
pipeline path + lightweight path 모두 동일 로직 적용.
결과는 features JSONB에 {dark_suspicion_score, dark_patterns,
dark_tier, dark_history_7d, dark_history_24h, gap_start_*} 저장.
## transship 재설계: 베테랑 함정근무자 기준
한정된 함정 자원으로 단속 출동을 결정할 수 있는 신뢰도 확보.
상수 재조정:
- SOG_THRESHOLD_KN: 2.0 → 1.0 (완전 정박만)
- PROXIMITY_DEG: 0.001 → 0.0007 (~77m)
- SUSPECT_DURATION_MIN: 60 → 45 (gap tolerance 있음)
- PAIR_EXPIRY_MIN: 120 → 180
- GAP_TOLERANCE_CYCLES: 2 신규 (GPS 노이즈 완화)
필수 조건 (모두 충족):
- 한국 EEZ 관할 수역 이내
- 환적 불가 선종 제외 (passenger/military/tanker/pilot/tug/sar)
- 어구 AIS 양쪽 제외
- 45분 이상 지속 (miss_count 2 사이클까지 용인)
점수 체계 (base 40):
- 야간(KST 20~04): +15
- 무허가 가점: +20
- COG 편차 > 45°: +20 (나란히 가는 선단 배제)
- 지속 ≥ 90분: +20
- 영해/접속수역 위치: +15
등급: CRITICAL(90+) / HIGH(70~89) / WATCH(50~69)
WATCH는 저장 없이 로그만. HIGH/CRITICAL만 이벤트.
pair_history 구조 확장:
- 기존: {(a,b): datetime}
- 신규: {(a,b): {'first_seen', 'last_seen', 'miss_count', 'last_lat/lon/cog_a/cog_b'}}
- miss_count > GAP_TOLERANCE_CYCLES면 삭제 (즉시 리셋 아님)
## event_generator 룰 교체
- dark_vessel_long 룰 제거 → dark_critical, dark_high (features.dark_tier 기반)
- transship 룰 제거 → transship_critical, transship_high (features.transship_tier 기반)
- DEDUP: ILLEGAL_TRANSSHIP 67→181, DARK_VESSEL 127→131, ZONE_DEPARTURE 127→89
## 공통 정리
- scheduler.py의 _gear_re 삭제, fleet_tracker.GEAR_PATTERN 단일 SSOT로 통합
2026-04-09 07:42:15 +09:00
2e5d55a27f
fix(prediction): dark 판정에 한국 AIS 수신 영역 필터 추가
...
16:00 cron 1차 분석 결과, lightweight path가 6,500척 중 5,250척(80%)을
dark로 판정. 좌표 검증 결과 모두 30~37°N/122~125°E (동중국해/서해)로
한국 AIS 수신소 도달 한계 영역에 위치하여 정상 운항 중에도 20~24h 통째로
수신이 끊기는 자연 gap이 발생.
핫픽스: lightweight path에서 dark 판정 직후 마지막 위치가
북위 32~39.5, 동경 124~132 (한반도 + EEZ + 접속수역 여유 포함) 밖이면
dark를 False로 강제. 한국 측 관심 영역의 dark 탐지는 그대로 유지.
근본 개편(STATIONARY 정박 필터, 진입 후 단절 패턴, gap 임계값 재조정 등)은
12시간 추적 데이터 수집 후 내일 진행.
2026-04-08 16:11:02 +09:00
0a4d023c76
fix(prediction): output 5종 이상 정상화 (stats/event/lightweight)
...
5가지 출력 이상 동시 해결:
1. stats_aggregator (이상 1, 5)
- aggregate_hourly에 by_category, by_zone JSON 집계 추가
- hour_start를 KST 기준으로 변경 (대시보드 표기와 boundary 일치)
2. event_generator 룰 정리 (이상 2, 3, 4)
- critical_risk 임계값 90→70 (risk.py CRITICAL 분류와 일치)
- territorial_sea_violation, contiguous_zone_high_risk, special_zone_entry 신설
(실측 zone_code: TERRITORIAL_SEA/CONTIGUOUS_ZONE/ZONE_*)
- 잘못된 NLL/SPECIAL_FISHING_* 룰 제거
- HIGH_RISK_VESSEL 신규 카테고리 (50~69 MEDIUM, 70+ CRITICAL)
- break 제거: 한 분석결과가 여러 카테고리에 동시 매칭 가능
3. dedup window prime 분산 (이상 5)
- 30/60/120/360분 → 33/67/127/367분
- 5분 사이클 boundary와 LCM 회피하여 정시 일제 만료 패턴 완화
4. lightweight path 신호 보강 (이상 2, 3, 4 근본 해결)
- vessel_store._tracks의 24h 누적 궤적으로 dark/spoof/speed_jump 산출
- 6,500 vessels(전체 93%)의 is_dark, spoofing_score가 비로소 채워짐
- compute_lightweight_risk_score에 dark gap, spoofing 가점 추가
(max 60→100 가능, CRITICAL 도달 가능)
시간 처리 원칙 적용:
- DB 컬럼은 모두 timestamptz 확인 완료
- aggregate_hourly KST aware datetime 사용
- pandas Timestamp는 source-internal 비교만 (안전)
2026-04-08 15:18:18 +09:00
1897ff45d3
Merge pull request 'chore: main → develop back-merge (릴리즈 노트 동기화)' ( #20 ) from main into develop
2026-04-08 13:44:03 +09:00
30ef2cd593
Merge pull request 'release: 2026-04-08 (35건 커밋)' ( #19 ) from release/2026-04-08 into main
Build and Deploy KCG AI Monitoring (Frontend) / build-and-deploy (push) Successful in 16s
2026-04-08 13:43:24 +09:00
5d99ed0b77
docs: 릴리즈 노트 정리 (2026-04-08)
2026-04-08 13:42:41 +09:00
c4a621e1d7
Merge pull request 'feat(frontend): 디자인 시스템 SSOT 확립 + 전체 페이지 마이그레이션 + a11y 전수 처리' ( #18 ) from feature/design-system-showcase into develop
2026-04-08 13:40:00 +09:00
479a4bfc56
docs: 디자인 시스템 SSOT 개발 지침 + 릴리즈 노트 갱신
...
CLAUDE.md '디자인 시스템' 섹션 신규:
- 쇼케이스(/design-system.html)를 단일 진실 공급원으로 명시
- 공통 컴포넌트 목록 (Button/Input/Select/PageContainer/PageHeader/Badge 등)
- 카탈로그 API 사용 패턴 (getAlertLevelIntent/Label 등)
- CSS 작성 6대 규칙 (인라인 색상 금지, 하드코딩 Tailwind 색상 금지,
className override 정책, 시맨틱 토큰 우선, !important 절대 금지,
vendor prefix 수동 대응)
- 페이지 작성 표준 템플릿
- 접근성 (WCAG 2.1 Level A) 필수 사항
- 변경 사이클 (쇼케이스 → 카탈로그 → 컴포넌트 → 자동 반영)
- 금지 패턴 체크리스트
RELEASE-NOTES.md [Unreleased]에 디자인 시스템 SSOT 작업 항목 추가:
- 쇼케이스 페이지 + 신규 공통 컴포넌트 + 중앙 레지스트리
- 35+ feature 페이지 마이그레이션
- Badge intent 팔레트 테마 분리
- 접근성 전수 처리 (Select TypeScript 강제 등)
2026-04-08 13:29:28 +09:00
f4d56ea891
fix(frontend): 아이콘 전용 버튼 접근 이름 누락 7곳 보완
...
이전 스캐너가 놓친 패턴 — 모달 닫기 X 버튼과 토글 스위치 등:
- NoticeManagement: 모달 헤더 X → '닫기'
- ReportManagement: 업로드 패널 X → '업로드 패널 닫기'
- AIModelManagement: 규칙 토글 → role=switch + aria-checked + aria-label
API 예시 복사 → '예시 URL 복사'
- FileUpload: 파일 제거 X → '{파일명} 제거'
- NotificationBanner: 알림 닫기 X → '알림 닫기'
- SearchInput: 입력 aria-label (placeholder), 지우기 버튼 → '검색어 지우기'
검증:
- 개선된 스캐너로 remaining=0 확인 (JSX tag 중첩 파싱)
- tsc ✅
2026-04-08 13:16:20 +09:00
c51873ab85
fix(frontend): a11y/호환성 — backdrop-filter webkit prefix + Button/Input/Select 접근 이름
...
axe/forms/backdrop 에러 3종 모두 해결:
1) CSS: backdrop-filter Safari 호환성
- design-system CSS에 -webkit-backdrop-filter 추가
- trk-pulse 애니메이션을 outline-color → opacity로 변경
(composite만 트리거, paint/layout 없음 → 더 나은 성능)
2) 아이콘 전용 <button> aria-label 추가 (9곳):
- MainLayout 알림 버튼 → '알림'
- UserRoleAssignDialog 닫기 → '닫기'
- AIAssistant/MLOpsPage 전송 → '전송'
- ChinaFishing 좌/우 네비 → '이전'/'다음'
- 공통 컴포넌트 (PrintButton/ExcelExport/SaveButton) type=button 누락 보정
3) <input>/<textarea> 접근 이름 27곳 추가:
- 로그인 폼, ParentReview/LabelSession/ParentExclusion 폼 (10)
- NoticeManagement 제목/내용/시작일/종료일 (4)
- SystemConfig/DataHub/PermissionsPanel 검색·역할 입력 (5)
- VesselDetail 조회 시작/종료/MMSI (3)
- GearIdentification InputField에 label prop 추가
- AIAssistant/MLOpsPage 질의 input/textarea
- MainLayout 페이지 내 검색
- 공통 placeholder → aria-label 자동 복제 (3)
Button 컴포넌트에는 접근성 정책 JSDoc 명시 (타입 강제는 API 복잡도 대비
이득 낮아 문서 가이드 + 코드 리뷰로 대응).
검증:
- 실제 위반 지표: inaccessible button 0, inaccessible input 0, textarea 0
- tsc ✅ , eslint ✅ , vite build ✅
- dist CSS에 -webkit-backdrop-filter 확인됨
2026-04-08 13:04:23 +09:00
9dfa8f5422
fix(frontend): Select 접근성 — aria-label 필수 + 네이티브 <select> 보완
...
이슈: "Select element must have an accessible name" — 스크린 리더가 용도를
인지할 수 없어 WCAG 2.1 Level A 위반.
수정:
- Select 공통 컴포넌트 타입을 union으로 강제
- aria-label | aria-labelledby | title 중 하나는 TypeScript 컴파일 타임에 필수
- 누락 시 tsc 단계에서 즉시 실패 → 회귀 방지
- 네이티브 <select> 5곳 aria-label 추가:
- admin/SystemConfig: 대분류 필터
- detection/RealVesselAnalysis: 해역 필터
- detection/RealGearGroups: 그룹 유형 필터
- detection/ChinaFishing: 관심영역 선택
- detection/GearIdentification: SelectField에 label prop 추가
- 쇼케이스 FormSection Select 샘플에 aria-label 추가
이제 모든 Select 사용처가 접근 이름을 가지며,
향후 신규 Select 사용 시 tsc가 누락을 차단함.
2026-04-08 12:50:51 +09:00
da4dc86e90
refactor(frontend): 인라인 버튼/하드코딩 색상 전수 제거
...
Phase C-2 (인라인 <button>):
- TabBar/TabButton 공통 컴포넌트 신규 (underline/pill/segmented 3종)
- DataHub: 메인 탭 → TabBar + TabButton 전환, 필터 pill 전환,
CTA 버튼 (작업 등록/스토리지 관리/새로고침) → Button variant
- PermissionsPanel: 역할 생성/저장 → Button variant, icon 버튼 유지
- Python 일괄 치환: 51개 inline <button>에 type="button" 추가
- 남은 <button> type 누락 0건 (multi-line 포함)
Phase C-3 (하드코딩 색상):
- AdminPanel SERVER_STATUS 뱃지: getStatusIntent() 사용으로 통일
- bg-X-500/20 text-X-400 패턴 0건
Phase C-4 (인라인 style):
- LiveMapView BaseMap minHeight → className="min-h-[400px]"
- 나머지 89건 style={{}}은 모두 dynamic value
(progress width, toggle left, 데이터 기반 color 등)로 정당함
4개 catalog (eventStatuses/enforcementResults/enforcementActions/
patrolStatuses)에 intent 필드 추가, statusIntent.ts 공통 유틸 신규.
이제 모든 Badge가 쇼케이스 팔레트 자동 적용됨.
빌드 검증:
- tsc ✅ , eslint ✅ , vite build ✅
- 남은 위반 지표: Badge className 0, button-type-missing 0, 하드코딩 색상 0
2026-04-08 12:36:07 +09:00
2483174081
refactor(frontend): Badge className 위반 37건 전수 제거
...
- 4개 catalog(eventStatuses/enforcementResults/enforcementActions/patrolStatuses)에
intent 필드 추가 + getXxxIntent() 헬퍼 신규
- statusIntent.ts 공통 유틸: 한글/영문 상태 문자열 → BadgeIntent 매핑
+ getRiskIntent(0-100) 점수 기반 매핑
- 모든 Badge className="..." 패턴을 intent prop으로 치환:
- admin (AuditLogs/AccessControl/SystemConfig/NoticeManagement/DataHub)
- ai-operations (AIModelManagement/MLOpsPage)
- enforcement (EventList/EnforcementHistory)
- field-ops (AIAlert)
- detection (GearIdentification)
- patrol (PatrolRoute/FleetOptimization)
- parent-inference (ParentExclusion)
- statistics (ExternalService/ReportManagement)
- surveillance (MapControl)
- risk-assessment (EnforcementPlan)
- monitoring (SystemStatusPanel — ServiceCard statusColor → statusIntent 리팩토)
- dashboard (Dashboard PatrolStatusBadge)
이제 Badge의 테마별 팔레트(라이트 파스텔 + 다크 translucent)가 자동 적용되며,
쇼케이스에서 palette 조정 시 모든 Badge 사용처에 일관되게 반영됨.
2026-04-08 12:28:23 +09:00
85cb6b40a2
refactor(frontend): 복잡 페이지 PageContainer 적용 (Phase B-5)
...
- MonitoringDashboard: 표준 PageHeader
- MapControl: demo 배지
- RiskMap: 수집 중 배지 + secondary Button 2개 액션
- Dashboard: PageContainer 래핑 (커스텀 DEFCON 헤더는 유지)
- LiveMapView: PageContainer fullBleed + flex 레이아웃 유지
- VesselDetail: PageContainer fullBleed + -m-4 해킹 제거
- TransferDetection: PageHeader 적용
Phase B 전체 완료. 실제 프론트엔드의 모든 주요 페이지가 쇼케이스 기준
공통 컴포넌트(PageContainer/PageHeader/Button/Select/Badge)를 사용한다.
카탈로그/variant 변경 시 쇼케이스와 실 페이지 동시 반영됨.
최종 통계:
- 7개 batch에서 총 30+ 파일 마이그레이션
- PageContainer 도입률: ~100% (SPA 메인 라우트 기준)
- PageHeader 도입률: ~95%
- 신규 Button 컴포넌트 도입: admin/enforcement/parent-inference 등 주요 액션
빌드 검증:
- tsc ✅ , eslint ✅ (경고만), vite build ✅
2026-04-08 12:09:17 +09:00
64e24cea71
refactor(frontend): statistics/ai-ops/parent-inference PageContainer 적용
...
statistics:
- Statistics: icon=BarChart3, secondary 보고서 생성 Button
- ReportManagement: destructive '새 보고서' + Button 그룹 + demo
- ExternalService: demo
ai-operations:
- AIAssistant: PageContainer + h-full flex 조합 (chat 레이아웃)
- AIModelManagement: 운영 모델 상태 뱃지는 actions 슬롯 유지
- MLOpsPage: demo
parent-inference:
- ParentReview/LabelSession/ParentExclusion: size=lg + Select + primary Button
Phase B-4 완료. 총 9개 파일.
2026-04-08 12:04:05 +09:00
2976796652
refactor(frontend): enforcement/field-ops/patrol PageContainer/PageHeader 적용
...
- EnforcementHistory/EventList/EnforcementPlan: primary Button 액션
- EventList: Select 공통 컴포넌트로 등급 필터 치환
- AIAlert/ShipAgent/MobileService: PageContainer + PageHeader(demo)
- PatrolRoute/FleetOptimization: primary Button 액션 2개씩
Phase B-3 완료. 총 10개 파일.
2026-04-08 11:57:01 +09:00
a1c521792d
refactor(frontend): detection 계열 PageContainer/PageHeader 적용
...
- DarkVesselDetection: icon=EyeOff color=red
- GearDetection: icon=Anchor color=orange
- ChinaFishing: PageContainer size=sm (tab 기반 멀티뷰 루트)
GearIdentification/RealVesselAnalysis/RealGearGroups는 ChinaFishing의 서브
컴포넌트라 독립 마이그레이션 불필요.
2026-04-08 11:51:32 +09:00
4ee8f05dfd
refactor(frontend): admin 계열 PageContainer/PageHeader 적용
...
- AdminPanel: PageContainer + PageHeader(demo)
- AuditLogs/AccessLogs/LoginHistoryView: size=lg + primary Button
- AccessControl: size=lg + 우측 stats 유지 + ghost 새로고침 Button
- DataHub: PageContainer + demo 배지 + secondary 새로고침
- NoticeManagement: primary '새 알림 등록' Button
- SystemConfig: secondary 2개 액션 Button
인라인 <button>/<div className="p-5 space-y-4"> 패턴을 쇼케이스 공통 컴포넌트로
치환. admin 계열 9개 파일 중 7개 완료 (PermissionsPanel은 서브 컴포넌트라 제외).
UserRoleAssignDialog는 dialog라 제외.
2026-04-08 11:48:41 +09:00
52749638ef
refactor(frontend): 쇼케이스 SSOT 구조 — 카탈로그 레지스트리 + variant 메타
...
Phase A: 쇼케이스의 카탈로그/variant 정보를 중앙 상수로 끌어올림
- shared/constants/catalogRegistry.ts 신규
- 19+ 카탈로그의 id/showcaseId/titleKo/titleEn/description/source/items를
단일 레지스트리로 통합 관리
- 새 카탈로그 추가 = 레지스트리에 1줄 추가로 쇼케이스 자동 노출
- CATALOG_REGISTRY + getCatalogById()
- lib/theme/variantMeta.ts 신규
- BADGE_INTENT_META: 8 intent의 titleKo/titleEn/description
- BUTTON_VARIANT_META: 5 variant의 titleKo/titleEn/description
- BADGE_INTENT_ORDER/SIZE_ORDER, BUTTON_VARIANT_ORDER/SIZE_ORDER
- 쇼케이스 섹션 리팩토링 — 하드코딩 제거
- CatalogSection: CATALOG_REGISTRY 자동 열거 (CATALOGS 배열 삭제)
- BadgeSection: BADGE_INTENT_META에서 의미 가이드 + titleKo 참조
- ButtonSection: BUTTON_VARIANT_META에서 의미 가이드 + titleKo 참조
효과:
- 카탈로그의 라벨/색상/intent 변경 시 쇼케이스와 실 페이지 동시 반영
- Badge/Button의 variant 의미가 variantMeta 한 곳에서 관리됨
- 쇼케이스 섹션에 분산돼 있던 하드코딩 제거 (INTENT_USAGE, VARIANT_USAGE 등)
다음 단계: 실 페이지를 PageContainer/PageHeader/Button/Input으로 마이그레이션
2026-04-08 11:42:43 +09:00
4170824f15
feat(frontend): 쇼케이스 테마 전환 단축키 A 추가
2026-04-08 11:31:16 +09:00
d7f8db88ee
fix(frontend): Badge 다크 팔레트를 translucent로 통일 + 쇼케이스 한/영 병기
...
- badgeVariants 다크 팔레트를 classes 기반 4종 카탈로그와 동일 패턴으로 통일
- 이전: dark:bg-X-400 dark:text-slate-900 dark:border-X-600 (솔리드)
- 이후: dark:bg-X-500/20 dark:text-X-400 dark:border-X-500/30 (translucent)
- 라이트 팔레트는 그대로 유지 (이미 통일되어 있음)
- CatalogSection: 각 카탈로그 항목을 [code / 한글 배지 / 영문 배지] 3열 행으로 렌더
- 한글/영문 라벨 두 버전을 한눈에 비교 검토 가능
- 추적 ID Trk는 행 전체를 감싸서 호버/복사 동작
2026-04-08 11:28:02 +09:00
f589cb0f94
fix(frontend): 카탈로그 배지 테마 분리 + 단속 조치 가독성 수정
...
변경:
- badgeVariants 8 intent 모두 라이트/다크 팔레트 분리
- 다크: 밝은 솔리드 배경(-400) + slate-900 글자 + 강한 보더(-600)
- 라이트: 파스텔 배경(-100) + 진한 글자(-900) + 소프트 보더(-300)
- base에서 text-on-bright 제거 (intent별로 관리)
- classes 기반 카탈로그 4종에 dark: 변형 추가로 라이트 모드 대응:
- eventStatuses: bg-red-100 text-red-800 dark:bg-red-500/20 dark:text-red-400
- enforcementResults: 동일 패턴 (red/purple/yellow/green)
- patrolStatuses: border 포함 (7 상태)
- enforcementActions: classes 필드 신규 추가 (기존에 없어서 fallback grey로 떨어져
라이트 모드에서 글자 안 보이던 원인)
- CatalogSection fallback classes도 dark: 변형 추가 (안전장치)
- enforcementActions에 getEnforcementActionClasses() 헬퍼 신규
빌드 검증:
- tsc ✅ , vite build ✅
- CSS 확인: .dark\:bg-red-400:is(.dark *) 컴파일 정상
2026-04-08 11:23:38 +09:00
e0b51efc54
feat(frontend): 디자인 시스템 쇼케이스 페이지 + 신규 공통 컴포넌트
...
쇼케이스 (/design-system.html):
- 별도 Vite entry (System Flow 패턴 재사용, 메인 SPA 분리)
- 10개 섹션: Intro / Token / Typography / Badge / Button / Form /
Card / Layout / Catalog (19+) / Guide
- 추적 ID 체계 (TRK-CATEGORY-SLUG):
- hover 시 툴팁 + "ID 복사 모드"에서 클릭 시 클립보드 복사
- URL hash 딥링크 (#trk=TRK-BADGE-critical-sm) 스크롤+하이라이트
- 산출문서/논의에서 특정 변형 정확히 참조 가능
- Dark/Light 테마 토글로 양쪽 시각 검증
신규 공통 컴포넌트:
- Button (@shared/components/ui/button.tsx)
- 5 variant × 3 size = 15 변형
- primary/secondary/ghost/outline/destructive × sm/md/lg
- Input / Select / Textarea / Checkbox / Radio
- Input · Select 공통 inputVariants 공유 (sm/md/lg × default/error/success)
- PageContainer / PageHeader / Section (shared/components/layout/)
- PageContainer: size sm/md/lg + fullBleed (지도/풀화면 예외)
- PageHeader: title + description + icon + demo 배지 + actions 슬롯
- Section: Card + CardHeader + CardTitle + CardContent 단축
variants.ts 확장:
- buttonVariants / inputVariants / pageContainerVariants CVA 정의
- Button/Input/Select는 variants.ts에서 import하여 fast-refresh 경고 회피
빌드 검증 완료:
- TypeScript 타입 체크 통과
- ESLint 통과 (경고 0)
- vite build: designSystem-*.js 54KB (메인 SPA와 분리)
이 쇼케이스가 확정된 후 실제 40+ 페이지 마이그레이션 진행 예정.
2026-04-08 11:09:36 +09:00
a07b7d9ba5
docs: 릴리즈 노트 갱신 (UI 카탈로그 시스템)
2026-04-08 10:55:09 +09:00
a07c745cbc
feat(frontend): 40+ 페이지 Badge/시맨틱 토큰 마이그레이션
...
- 모든 feature 페이지의 Badge className 패턴을 intent/size prop으로 변환
- 컬러풀 액션 버튼 (bg-*-500/600/700 + text-heading) -> text-on-vivid
- 검색/필터 버튼 배경 bg-blue-400 + text-on-bright (밝은 배경 위 검정)
- ROLE_COLORS 4곳 중복 제거 (MainLayout/UserRoleAssignDialog/
PermissionsPanel/AccessControl) -> getRoleBadgeStyle 공통 호출
- PermissionsPanel 역할 생성/수정에 ColorPicker 통합
- MainLayout: PagePagination + scroll page state 제거 (데이터 페이지네이션 혼동)
- Dashboard RiskBar 단위 버그 수정 (0~100 정수 처리)
- ReportManagement, TransferDetection p-5 space-y-4 padding 복구
- EnforcementHistory 그리드 minmax 적용으로 컬럼 잘림 해소
- timeline 시간 formatDateTime 적용 (ISO T 구분자 처리)
- 각 feature 페이지가 공통 카탈로그 API (getXxxIntent/Label/Classes) 사용
2026-04-08 10:53:58 +09:00
5812d9dea3
feat(frontend): UI 공통 인프라 + 19개 분류 카탈로그 구축
...
- cn() 유틸 신규 (clsx + tailwind-merge, 시맨틱 토큰 classGroup 등록)
- theme.css @layer utilities로 직접 정의 (Tailwind v4 복합 이름 매핑 실패 대응):
text-heading/label/hint/on-vivid/on-bright, bg-surface-raised/overlay
- badgeVariants (CVA) 재구축: 8 intent x 4 size, rem 기반, !important 제거
- Badge 컴포넌트가 cn(badgeVariants, className)로 override 허용
- DataTable width 의미 변경: 고정 -> 선호 최소 너비 (minWidth), truncate + title 툴팁
- dateFormat.ts sv-SE 로케일로 YYYY-MM-DD HH:mm:ss 일관된 KST 출력
- ColorPicker 신규 (팔레트 + native color + hex 입력)
- shared/constants/ 19개 카탈로그: violation/alert/event/enforcement/patrol/
engine/userRole/device/parentResolution/modelDeployment/gearGroup/darkVessel/
httpStatus/userAccount/loginResult/permission/vesselAnalysis/connection/trainingZone
+ kpiUiMap. 백엔드 enum/code_master 기반 SSOT
- i18n ko/en common.json에 카테고리 섹션 추가
- adminApi.fetchRoles()가 updateRoleColorCache 자동 호출
- 공통 컴포넌트 (ExcelExport/NotificationBanner/Pagination/SaveButton) 시맨틱 토큰 적용
2026-04-08 10:53:40 +09:00
20d6743c17
feat(backend): Role.colorHex 추가 + V017 migration
...
- auth_role.color_hex VARCHAR(7) 컬럼 추가 (Flyway V017)
- 빌트인 5개 역할 기본 색상 시드 (ADMIN/OPERATOR/ANALYST/FIELD/VIEWER)
- Role 엔티티 + RoleCreate/UpdateRequest DTO + RoleManagementService
- PermTreeController 응답에 colorHex 필드 포함
2026-04-08 10:52:36 +09:00
7ed07093db
Merge pull request 'docs: 프로젝트 문서 최신화 (2026-04-08)' ( #16 ) from docs/project-status-2026-04-08 into develop
2026-04-08 07:11:07 +09:00
7f35103c60
docs: 프로젝트 문서 최신화 (2026-04-08)
...
## 메모리 갱신 (Claude 내부)
- project-snapshot.md: 48테이블, V001~V016, prediction e2e 정상, System Flow 뷰어, 데모계정 5종
- project-history.md: 2026-04-07~08 릴리즈 이력 요약 (MR #3~#15)
- next-task: 1순위를 UI/표기 다듬기로 전환
- api-types: /api/stats/hourly + V014~V016 보조 테이블 추가
- debugging: 최근 해결된 11개 이슈 패턴 정리
- 구버전 참고 파일 정리 (data-analysis, refactoring-decisions)
## 리포지토리 문서
- docs/RELEASE-NOTES.md: Unreleased 섹션에 prediction e2e 수정, System Flow 포커스 모드,
hourly API, V014~V016, mock 정리, KST 통일, DemoQuickLogin hostname 등 추가
- CLAUDE.md: database/ 설명 V001~V016, 48 테이블로 갱신
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 07:10:22 +09:00
8ccae2fee5
Merge pull request 'release: DemoQuickLogin hostname 대응' ( #15 ) from develop into main
Build and Deploy KCG AI Monitoring (Frontend) / build-and-deploy (push) Successful in 16s
2026-04-08 06:59:04 +09:00
930fbfc841
Merge pull request 'fix: DemoQuickLogin hostname 기반 노출' ( #14 ) from feature/demo-login-hostname into develop
2026-04-08 06:59:02 +09:00
666d6e88c8
fix: DemoQuickLogin 노출 조건에 hostname 기반 판정 추가
...
Gitea CI 빌드에 .env 파일이 포함되지 않아 VITE_SHOW_DEMO_LOGIN이
주입되지 않는 문제 대응. 허용된 호스트에서는 환경변수 없이도 데모 퀵로그인 표시.
허용 호스트:
- localhost / 127.0.0.1 (로컬 개발)
- kcg-ai-monitoring.gc-si.dev (현재 데모 운영)
실운영 호스트로 전환 시 DEMO_ALLOWED_HOSTS에서 제거 필요.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 06:58:39 +09:00
24f3473daa
Merge pull request 'release: prediction e2e 수정' ( #13 ) from develop into main
2026-04-08 06:48:20 +09:00
1ff8a6ac7f
Merge pull request 'fix: prediction e2e — Decimal/violation/KPI/stats/parent workflow 5건 수정' ( #12 ) from feature/prediction-e2e-fixes into develop
2026-04-08 06:48:19 +09:00
da37a00b8e
fix: prediction 5가지 이슈 수정 — 모든 파이프라인 정상 동작
...
## 이슈 1: gear_correlation Decimal → float TypeError
- prediction/algorithms/gear_correlation.py:785
- _load_all_scores()가 NUMERIC 컬럼을 Decimal로 읽어 float 상수와 연산 시 실패
- float() 명시 변환으로 수정
- 효과: gear correlation 24,474 raw metrics + 3,966 scores 정상 기록
## 이슈 2: violation_classifier classified=0 문제
- prediction/output/violation_classifier.py
- result.get('id')는 AnalysisResult에 없어 항상 None → 모든 UPDATE 건너뜀
- 존재하지 않는 permit_status/gear_judgment 필드에 의존
- (mmsi, analyzed_at) 기준 UPDATE로 변경
- 중국 선박(412/413*) + EEZ 진입은 permit 없어도 EEZ_VIOLATION 판정
- 효과: classified=0 → classified=4~6/cycle
## 이슈 3: kpi_writer 모두 0 (tracking_active 외)
- prediction/output/kpi_writer.py:27
- date.today() + timezone.utc 혼용 → 현재 시각이 UTC로는 아직 '어제'라 '오늘 >= today_start' 쿼리가 0 반환
- KST 기준으로 today_start 계산
- 효과: realtime_detection 0 → 7,107, illegal_transship 0 → 5,033
## 이슈 4: stats_daily 오늘 0건
- prediction/output/stats_aggregator.py:96, 194
- aggregate_daily/monthly가 UTC 경계 사용
- KST 기준 자정으로 수정
- 효과: 2026-04-08 detections 0 → 543,656, events 0 → 5,253
## 이슈 5: parent workflow 테이블 누락 컬럼 (V005 ↔ prediction 불일치)
V016 마이그레이션으로 일괄 추가:
- gear_parent_label_sessions: label_parent_name, normalized_parent_name,
duration_days, actor, comment, metadata, updated_at 등 8개 컬럼
- gear_group_parent_resolution: parent_name, normalized_parent_name,
selected_parent_name, confidence, decision_source, top_score, second_score,
score_margin, stable_cycles, evidence_summary, episode_id, continuity_*,
prior_bonus_total, last_evaluated_at, last_promoted_at 등 17개 컬럼
- gear_parent_candidate_exclusions: normalized_parent_name, reason_type,
duration_days, metadata, updated_at, active_from, active_until +
candidate_mmsi GENERATED ALWAYS AS (excluded_mmsi) 별칭
- gear_group_parent_candidate_snapshots: parent_name
효과: gear parent inference: 925 groups, 301 direct-match, 1329 candidates,
188 review-required, 925 episode-snapshots 기록 — 전체 모선 워크플로우 정상
## 검증 결과 (e2e)
- analysis cycle: 6,824 vessels, 112초/cycle 정상
- vessel_analysis_results: 10분 13,650건, 총 125만건
- prediction_events: 1시간 138건, 총 12,258건
- prediction_alerts: 1시간 183건
- gear_correlation_scores: 3,966건
- gear_group_parent_resolution: 926건
- stats_hourly: 17행, stats_daily: 오늘 543,656건
- 백엔드 Flyway V016 정상 적용
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 06:47:53 +09:00
4f1572cd4e
Merge pull request 'release: System Flow 포커스 모드' ( #11 ) from develop into main
Build and Deploy KCG AI Monitoring (Frontend) / build-and-deploy (push) Successful in 16s
2026-04-08 05:48:30 +09:00
99764e7c99
Merge pull request 'feat: System Flow 뷰어 포커스 모드 + 엣지 겹침 완화' ( #10 ) from feature/system-flow-focus into develop
2026-04-08 05:48:29 +09:00
17215be29c
feat: System Flow 뷰어 — 포커스 모드 + 엣지 겹침 완화
...
## 포커스 모드
- 노드 선택 시 해당 노드 + 1-hop 연결된 노드만 활성
- 나머지 노드는 opacity 0.18 + grayscale, 엣지는 0.08로 dim 처리
- 상단 중앙 배지로 포커스 상태 표시 + "전체 보기 ✕" 해제 버튼
- 캔버스 빈 공간(pane) 클릭 시 포커스 해제
- 선택 노드는 스케일 1.02 + glow 효과로 강조
## 엣지 겹침 완화
- COL_WIDTH 360 → 440, ROW_HEIGHT 130 → 170 (간격 확대)
- smoothstep pathOptions.offset을 source별로 20→34→48... 분산
- 같은 노드에서 나가는 N번째 엣지는 서로 다른 경로로 라우팅
- 선택/포커스된 엣지는 zIndex 1000으로 최상단 표시
## 시각 보강
- 포커스된 엣지는 stroke #f8fafc + strokeWidth 2.8 + animated
- 비활성 엣지 라벨은 opacity 0.3, 텍스트 #475569로 어둡게
- 선택 노드 body: box-shadow + glow + scale 1.02
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 05:47:51 +09:00
1a6604d3b9
Merge pull request 'release: System Flow 뷰어 추가' ( #9 ) from develop into main
Build and Deploy KCG AI Monitoring (Frontend) / build-and-deploy (push) Successful in 16s
2026-04-07 17:11:46 +09:00
d55b177dec
Merge pull request 'feat: System Flow 뷰어 — 시스템 전체 데이터 흐름 시각화 (102 노드)' ( #8 ) from feature/system-flow-viewer into develop
2026-04-07 17:11:13 +09:00
5d0bca73e1
docs: 릴리즈 노트에 System Flow 뷰어 항목 추가
...
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:10:46 +09:00
a6f6003c5f
feat: System Flow 뷰어 추가 (system-flow.html) — 102 노드, 133 엣지
...
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>
2026-04-07 17:10:22 +09:00
1c69e2cdb8
Merge pull request 'release: 2026-04-07.2 (prediction e2e + 프론트 mock 정리)' ( #7 ) from develop into main
Build and Deploy KCG AI Monitoring (Frontend) / build-and-deploy (push) Successful in 16s
2026-04-07 15:37:25 +09:00
8dd86b692e
Merge pull request 'fix: prediction e2e + 프론트 mock 전수 정리 + KST 통일' ( #6 ) from feature/prediction-e2e-backend-fix into develop
2026-04-07 15:37:07 +09:00
19b1613157
feat: 프론트 전수 mock 정리 + UTC→KST 통일 + i18n 수정 + stats hourly API
...
## 시간 표시 KST 통일
- shared/utils/dateFormat.ts 공통 유틸 신규 (formatDateTime/formatDate/formatTime/toDateParam)
- 14개 파일에서 인라인 toLocaleString → 공통 유틸 교체
## i18n 'group.parentInference' 사이드바 미번역 수정
- ko/en common.json의 'group' 키 중복 정의를 병합
(95행 두번째 group 객체가 35행을 덮어써서 parentInference 누락)
## Dashboard/MonitoringDashboard/Statistics 더미→실 API
- 백엔드 GET /api/stats/hourly 신규 (PredictionStatsHourly 엔티티/리포지토리)
- Dashboard: HOURLY_DETECTION/VESSEL_TYPE/AREA_RISK 하드코딩 제거 →
getHourlyStats(24) + getDailyStats(today) 결과로 useMemo 변환
- MonitoringDashboard: TREND Math.random() 제거 → getHourlyStats 기반
위험도 가중평균 + 경보 카운트
- Statistics: KPI_DATA 하드코딩 제거 → getKpiMetrics() 결과를 표 행으로
## Store mock 의존성 제거
- eventStore.alerts/MOCK_ALERTS 제거 (MobileService는 events에서 직접 추출)
- enforcementStore.plans 제거 (EnforcementPlan은 이미 직접 API 호출)
- transferStore + MOCK_TRANSFERS 완전 제거
(ChinaFishing/TransferDetection은 RealTransshipSuspects 컴포넌트 사용)
- mock/events.ts, mock/enforcement.ts, mock/transfers.ts 파일 삭제
## RiskMap 랜덤 격자 제거
- generateGrid() Math.random() 제거 → 빈 배열 + 'AI 분석 데이터 수집 중' 안내
- MTIS 외부 통계 5개 탭에 [MTIS 외부 통계] 배지 추가
## 12개 mock 화면에 '데모 데이터' 노란색 배지 추가
- patrol/PatrolRoute, FleetOptimization
- admin/AdminPanel, DataHub, NoticeManagement, SystemConfig
- ai-operations/AIModelManagement, MLOpsPage
- field-ops/ShipAgent
- statistics/ReportManagement, ExternalService
- surveillance/MapControl
## 백엔드 NUMERIC precision 동기화
- PredictionKpi.deltaPct: 5,2 → 12,2
- PredictionStatsDaily/Monthly.aiAccuracyPct: 5,2 → 12,2
- (V015 마이그레이션과 동기화)
44 files changed, +346 / -787
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:36:38 +09:00
e12d1c33e2
fix: prediction e2e — 누락 테이블 12개 + 컬럼 매핑 + NUMERIC precision 통합 수정
...
- V014: fleet_vessels, fleet_tracking_snapshot, gear_identity_log,
gear_correlation_scores/raw_metrics, correlation_param_models,
group_polygon_snapshots, gear_group_episodes/episode_snapshots,
gear_group_parent_candidate_snapshots, gear_parent_label_tracking_cycles,
system_config 테이블 추가
- V015: 점수/비율 NUMERIC precision 일괄 확대 (score→7,4 / pct→12,2) +
vessel_analysis_results UNIQUE(mmsi, analyzed_at) 인덱스 추가
- prediction kcgdb.py: timestamp→analyzed_at, zone→zone_code,
is_leader→fleet_is_leader, is_transship_suspect→transship_suspect 매핑
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:00:29 +09:00
7f11a400ca
Merge pull request 'release: 2026-04-07 (26건 커밋)' ( #5 ) from develop into main
Build and Deploy KCG AI Monitoring (Frontend) / build-and-deploy (push) Successful in 16s
2026-04-07 13:59:55 +09:00
4db7874082
Merge pull request 'docs: 릴리즈 노트 정리 (2026-04-07)' ( #4 ) from release/2026-04-07 into develop
2026-04-07 13:58:53 +09:00
49140cc8fc
docs: 릴리즈 노트 정리 (2026-04-07)
...
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:58:28 +09:00
a01cd926a7
Merge pull request 'feat: 모노레포 전환 + 백엔드 RBAC + prediction 이식 + 15화면 실데이터 연동' ( #3 ) from feature/monorepo-backend-rbac into develop
2026-04-07 13:57:27 +09:00