실시간 차트 갱신문제 수정

This commit is contained in:
Macbook
2026-05-25 04:09:58 +09:00
parent 67a6aa0dee
commit ac2e6a1dae
4 changed files with 80 additions and 12 deletions
+23 -2
View File
@@ -614,6 +614,8 @@ function App() {
const managerRef = useRef<ChartManager | null>(null);
/** 차트 매니저 준비 전 도착한 STOMP 틱 (준비 후 1회 적용) */
const pendingRealtimeBarRef = useRef<OHLCVBar | null>(null);
/** reloadAll setData 완료 전 — 이전 종목 rawBars에 실시간 틱 혼입 방지 */
const chartLiveReadyRef = useRef(false);
const useUpbit = isUpbitMarket(symbol);
// ── 백테스팅 ───────────────────────────────────────────────────────────────
@@ -940,6 +942,10 @@ function App() {
// 틱 수신: 동일 캔들 업데이트 → React state 변경 없이 차트만 직접 갱신
const handleTickUpdate = useCallback((bar: OHLCVBar) => {
if (barsMarketRef.current !== chartContextRef.current.symbol) return;
if (!chartLiveReadyRef.current) {
pendingRealtimeBarRef.current = bar;
return;
}
if (!managerRef.current) {
pendingRealtimeBarRef.current = bar;
flashWsDot();
@@ -952,6 +958,10 @@ function App() {
// 새 캔들: bars state를 변경하지 않고 차트에 바만 추가 + 인디케이터 last point 갱신
const handleNewCandle = useCallback((newBar: OHLCVBar) => {
if (barsMarketRef.current !== chartContextRef.current.symbol) return;
if (!chartLiveReadyRef.current) {
pendingRealtimeBarRef.current = newBar;
return;
}
if (!managerRef.current) {
pendingRealtimeBarRef.current = newBar;
flashWsDot();
@@ -961,6 +971,15 @@ function App() {
flashWsDot();
}, []);
const handleCandlesReady = useCallback(() => {
chartLiveReadyRef.current = true;
const pending = pendingRealtimeBarRef.current;
const mgr = managerRef.current;
if (!pending || !mgr || barsMarketRef.current !== chartContextRef.current.symbol) return;
pendingRealtimeBarRef.current = null;
mgr.updateBar(pending);
}, []);
const chartRealtimeSource = appDefaults.chartRealtimeSource ?? 'BACKEND_STOMP';
const { bars: upbitBars, barsMarket: upbitBarsMarket, latestBar, wsStatus, isLoading, error } = useChartRealtimeData(
symbol,
@@ -978,8 +997,9 @@ function App() {
const barsMarket = useUpbit ? upbitBarsMarket : symbol;
barsMarketRef.current = barsMarket;
/** 종목·타임프레임 전환 시 이전 틱 버퍼 폐기 (paint 전에 실행) */
/** 종목·타임프레임 전환 시 이전 틱 버퍼·실시간 허용 플래그 초기화 (paint 전에 실행) */
useLayoutEffect(() => {
chartLiveReadyRef.current = false;
pendingRealtimeBarRef.current = null;
}, [symbol, timeframe]);
@@ -1970,10 +1990,11 @@ function App() {
onCrosshair={setLegend}
onTradeOrderRequest={applyTradeFill}
onDataLoaded={() => syncBacktestMarkersRef.current()}
onCandlesReady={handleCandlesReady}
onManagerReady={mgr => {
managerRef.current = mgr;
const pending = pendingRealtimeBarRef.current;
if (pending && barsMarketRef.current === symbol && bars.length > 0) {
if (pending && chartLiveReadyRef.current && barsMarketRef.current === symbol && bars.length > 0) {
pendingRealtimeBarRef.current = null;
const last = bars[bars.length - 1];
if (last && pending.time === last.time) mgr.updateBar(pending);