kcg-monitoring/frontend/src/services/chnPrmShip.ts
htlee feabf16114 feat: 중국어선 분석 인프라 — 허가어선 API 연동 + vessel-analysis 백엔드 + 결과 포맷 확정
- Frontend: ChnPrmShipInfo 타입 + chnPrmShip.ts 서비스 (signal-batch 허가어선 API)
- Frontend: FieldAnalysisModal fetchVesselPermit → lookupPermittedShip 교체
- Frontend: 더미 라벨 정리 (LightGBM → 규칙기반, BD-09/레이더 → STANDBY/미연동)
- Frontend: VesselAnalysisResult 인터페이스 정의 (Python 분석 결과 수신용)
- Backend: vessel-analysis REST API (Entity/Repository/Service/Controller)
- Backend: DB 마이그레이션 005 (kcg.vessel_analysis_results 테이블)
- Backend: AuthFilter 인증 예외 + CacheConfig 캐시 등록

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 11:00:16 +09:00

55 lines
1.5 KiB
TypeScript

import type { ChnPrmShipInfo } from '../types';
const SIGNAL_BATCH_BASE = '/signal-batch';
const CACHE_TTL_MS = 5 * 60_000; // 5분
let cachedList: ChnPrmShipInfo[] = [];
let cacheTime = 0;
let fetchPromise: Promise<ChnPrmShipInfo[]> | null = null;
async function fetchList(): Promise<ChnPrmShipInfo[]> {
const now = Date.now();
if (cachedList.length > 0 && now - cacheTime < CACHE_TTL_MS) {
return cachedList;
}
if (fetchPromise) return fetchPromise;
fetchPromise = (async () => {
try {
const res = await fetch(
`${SIGNAL_BATCH_BASE}/api/v2/vessels/chnprmship/recent-positions?minutes=60`,
{ headers: { accept: 'application/json' } },
);
if (!res.ok) return cachedList;
const json: unknown = await res.json();
cachedList = Array.isArray(json) ? (json as ChnPrmShipInfo[]) : [];
cacheTime = Date.now();
return cachedList;
} catch {
return cachedList;
} finally {
fetchPromise = null;
}
})();
return fetchPromise;
}
/** mmsi로 허가어선 정보 조회 — 목록을 캐시하고 lookup */
export async function lookupPermittedShip(mmsi: string): Promise<ChnPrmShipInfo | null> {
const list = await fetchList();
return list.find((s) => s.mmsi === mmsi) ?? null;
}
/** 허가어선 mmsi Set (빠른 조회용) */
export async function getPermittedMmsiSet(): Promise<Set<string>> {
const list = await fetchList();
return new Set(list.map((s) => s.mmsi));
}
/** 캐시 강제 갱신 */
export function invalidateCache(): void {
cacheTime = 0;
}