초기로딩 부하문제 수정

This commit is contained in:
Macbook
2026-05-31 22:26:54 +09:00
parent 4f2d98d4ba
commit 32d735c172
8 changed files with 554 additions and 387 deletions
+25 -43
View File
@@ -2,11 +2,12 @@
* 업비트 최근 체결 (호가창 좌측 체결 목록용)
*/
import { useState, useEffect, useRef, useCallback } from 'react';
import { subscribeUpbitWs } from '../utils/upbitWsBroker';
export interface RecentTrade {
price: number;
volume: number;
side: 'ask' | 'bid'; // ask=매도체결, bid=매수체결
side: 'ask' | 'bid';
time: number;
}
@@ -29,12 +30,13 @@ interface UpbitTradeWs {
timestamp: number;
}
export function useUpbitRecentTrades(market: string) {
export function useUpbitRecentTrades(market: string, enabled = true) {
const [trades, setTrades] = useState<RecentTrade[]>([]);
const [strength, setStrength] = useState<number | null>(null);
const wsRef = useRef<WebSocket | null>(null);
const mountedRef = useRef(true);
const marketRef = useRef(market);
marketRef.current = market;
const pushTrade = useCallback((t: RecentTrade) => {
setTrades(prev => {
@@ -49,7 +51,7 @@ export function useUpbitRecentTrades(market: string) {
const fetchSnapshot = useCallback(async () => {
try {
const res = await fetch(`/upbit-api/v1/trades/ticks?market=${market}&count=${MAX_TRADES}`);
const res = await fetch(`/upbit-api/v1/trades/ticks?market=${marketRef.current}&count=${MAX_TRADES}`);
if (!res.ok) return;
const data: UpbitTradeRaw[] = await res.json();
const list: RecentTrade[] = data.map(d => ({
@@ -63,57 +65,37 @@ export function useUpbitRecentTrades(market: string) {
const sellVol = list.filter(x => x.side === 'ask').reduce((s, x) => s + x.volume, 0);
if (sellVol > 0) setStrength((buyVol / sellVol) * 100);
} catch { /* ignore */ }
}, [market]);
}, []);
useEffect(() => {
mountedRef.current = true;
setTrades([]);
setStrength(null);
if (!enabled) {
return () => { mountedRef.current = false; };
}
fetchSnapshot();
const proto = window.location.protocol === 'https:' ? 'wss' : 'ws';
const ws = new WebSocket(`${proto}://${window.location.host}/upbit-ws`);
ws.binaryType = 'arraybuffer';
wsRef.current = ws;
ws.onopen = () => {
ws.send(JSON.stringify([
{ ticket: `tr-${market}-${Date.now()}` },
{ type: 'trade', codes: [market] },
]));
};
ws.onmessage = async (e: MessageEvent) => {
const unsub = subscribeUpbitWs('trade', [market], raw => {
if (!mountedRef.current) return;
try {
let text: string;
if (typeof e.data === 'string') text = e.data;
else if (e.data instanceof ArrayBuffer) text = new TextDecoder().decode(e.data);
else if (e.data instanceof Blob) text = await e.data.text();
else return;
const msg: UpbitTradeWs = JSON.parse(text);
if (msg.type === 'trade' && msg.code === market) {
pushTrade({
price: msg.trade_price,
volume: msg.trade_volume,
side: msg.ask_bid === 'ASK' ? 'ask' : 'bid',
time: msg.timestamp,
});
}
} catch { /* ignore */ }
};
const msg = raw as unknown as UpbitTradeWs;
if (msg.type === 'trade' && msg.code === marketRef.current) {
pushTrade({
price: msg.trade_price,
volume: msg.trade_volume,
side: msg.ask_bid === 'ASK' ? 'ask' : 'bid',
time: msg.timestamp,
});
}
});
return () => {
mountedRef.current = false;
if (wsRef.current) {
wsRef.current.onopen = null;
wsRef.current.onmessage = null;
wsRef.current.onclose = null;
wsRef.current.close();
wsRef.current = null;
}
unsub();
};
}, [market, fetchSnapshot, pushTrade]);
}, [market, enabled, fetchSnapshot, pushTrade]);
return { trades, strength };
}