import { useEffect, useMemo } from "react"; import { type KisRuntimeCredentials } from "@/features/settings/store/use-kis-runtime-store"; import type { DashboardRealtimeTradeTick, DashboardStockOrderBookResponse, } from "@/features/trade/types/trade.types"; import { resolveTradeTrIds } from "@/features/trade/utils/kisRealtimeUtils"; import { useKisWebSocketStore } from "@/features/kis-realtime/stores/kisWebSocketStore"; import { useDomesticSession } from "@/features/trade/hooks/useDomesticSession"; import { useTradeTickSubscription } from "@/features/trade/hooks/useTradeTickSubscription"; import { useOrderbookSubscription } from "@/features/trade/hooks/useOrderbookSubscription"; /** * @description KIS 실시간 매매/호가 데이터를 통합 구독하는 커스텀 훅입니다. * @summary * - `useDomesticSession`: 장 운영 시간(정규장, 시간외 등) 세션 관리 * - `useTradeTickSubscription`: 실시간 체결가(Tick) 데이터 구독 및 상태 관리 * - `useOrderbookSubscription`: 실시간 호가(Orderbook) 데이터 구독 * - `useKisWebSocketStore`: 전역 웹소켓 연결 상태 및 에러 관리 * * 위 훅들을 조합(Composition)하여 트레이딩 화면에 필요한 모든 실시간 데이터를 제공합니다. */ export function useKisTradeWebSocket( symbol: string | undefined, credentials: KisRuntimeCredentials | null, isVerified: boolean, onTick?: (tick: DashboardRealtimeTradeTick) => void, options?: { orderBookSymbol?: string; orderBookMarket?: "KOSPI" | "KOSDAQ"; onOrderBookMessage?: (data: DashboardStockOrderBookResponse) => void; }, ) { const marketSession = useDomesticSession(); const { isConnected, error } = useKisWebSocketStore(); const { latestTick, recentTradeTicks, lastTickAt } = useTradeTickSubscription( { symbol, isVerified, credentials, marketSession, onTick, }, ); useOrderbookSubscription({ symbol: options?.orderBookSymbol, market: options?.orderBookMarket, isVerified, credentials, marketSession, onOrderBookMessage: options?.onOrderBookMessage, }); // Connection/Data warning useEffect(() => { if (!isConnected || lastTickAt || !symbol) return; const timer = window.setTimeout(() => { // Just a warning, not blocking }, 8000); return () => window.clearTimeout(timer); }, [isConnected, lastTickAt, symbol]); const realtimeTrId = useMemo(() => { if (!credentials) return "H0STCNT0"; const ids = resolveTradeTrIds(credentials.tradingEnv, marketSession); return ids[0] ?? "H0STCNT0"; }, [credentials, marketSession]); return { latestTick, recentTradeTicks, isConnected, error, lastTickAt, realtimeTrId, }; }