import { useRef, useEffect } from "react"; import type { KisRuntimeCredentials } from "@/features/settings/store/use-kis-runtime-store"; import type { DashboardStockOrderBookResponse } from "@/features/trade/types/trade.types"; import { useKisWebSocketStore } from "@/features/kis-realtime/stores/kisWebSocketStore"; import { parseKisRealtimeOrderbook, resolveOrderBookTrIds, } from "@/features/trade/utils/kisRealtimeUtils"; import type { DomesticKisSession } from "@/lib/kis/domestic-market-session"; interface UseOrderbookSubscriptionParams { symbol: string | undefined; // orderBookSymbol isVerified: boolean; credentials: KisRuntimeCredentials | null; marketSession: DomesticKisSession; onOrderBookMessage?: (data: DashboardStockOrderBookResponse) => void; } /** * @description 실시간 호가(Orderbook) 구독 로직을 담당하는 훅입니다. * - 호가 데이터는 빈도가 매우 높으므로 별도의 상태(state)에 저장하지 않고, * - 콜백 함수(onOrderBookMessage)를 통해 상위 컴포넌트로 데이터를 직접 전달합니다. * - 이를 통해 불필요한 리렌더링을 방지합니다. */ export function useOrderbookSubscription({ symbol, isVerified, credentials, marketSession, onOrderBookMessage, }: UseOrderbookSubscriptionParams) { const { subscribe, connect } = useKisWebSocketStore(); const onOrderBookMessageRef = useRef(onOrderBookMessage); useEffect(() => { onOrderBookMessageRef.current = onOrderBookMessage; }, [onOrderBookMessage]); useEffect(() => { if (!symbol || !isVerified || !credentials) return; connect(); const trIds = resolveOrderBookTrIds(credentials.tradingEnv, marketSession); const unsubscribers: Array<() => void> = []; const handleOrderBookMessage = (data: string) => { const ob = parseKisRealtimeOrderbook(data, symbol); if (ob) { ob.tradingEnv = credentials.tradingEnv; onOrderBookMessageRef.current?.(ob); } }; for (const trId of trIds) { unsubscribers.push(subscribe(trId, symbol, handleOrderBookMessage)); } return () => { unsubscribers.forEach((unsub) => unsub()); }; }, [symbol, isVerified, credentials, marketSession, connect, subscribe]); }