import { useState, useEffect, useRef, useCallback } from 'react'; import type { OilDetectionResult, OilDetectionConfig } from '../utils/oilDetection'; import { detectOilSpillAPI, DEFAULT_OIL_DETECTION_CONFIG } from '../utils/oilDetection'; interface UseOilDetectionOptions { videoRef: React.RefObject; enabled: boolean; config?: Partial; } interface UseOilDetectionReturn { result: OilDetectionResult | null; isAnalyzing: boolean; error: string | null; } export function useOilDetection(options: UseOilDetectionOptions): UseOilDetectionReturn { const { videoRef, enabled, config } = options; const [result, setResult] = useState(null); const [isAnalyzing, setIsAnalyzing] = useState(false); const [error, setError] = useState(null); const configRef = useRef({ ...DEFAULT_OIL_DETECTION_CONFIG, ...config, }); const isBusyRef = useRef(false); useEffect(() => { configRef.current = { ...DEFAULT_OIL_DETECTION_CONFIG, ...config, }; }, [config]); const analyze = useCallback(async () => { if (isBusyRef.current) return; // 이전 호출이 진행 중이면 스킵 const video = videoRef.current; if (!video || video.readyState < 2) return; isBusyRef.current = true; setIsAnalyzing(true); try { const detection = await detectOilSpillAPI(video, configRef.current); setResult(detection); setError(null); } catch (err) { // API 실패 시 이전 결과 유지, 에러 메시지만 갱신 const message = err instanceof Error ? err.message : '추론 서버 연결 불가'; setError(message); console.warn('[OilDetection] API 호출 실패:', message); } finally { isBusyRef.current = false; setIsAnalyzing(false); } }, [videoRef]); useEffect(() => { if (!enabled) { setResult(null); setIsAnalyzing(false); setError(null); isBusyRef.current = false; return; } setIsAnalyzing(true); // 첫 분석: 2초 후 (영상 로딩 대기) const firstTimeout = setTimeout(analyze, 2000); // 반복 분석 const intervalId = setInterval(analyze, configRef.current.captureIntervalMs); return () => { clearTimeout(firstTimeout); clearInterval(intervalId); }; }, [enabled, analyze]); return { result, isAnalyzing, error }; }