From ff5f52a1506f4fd9c04b7fac067594d96b48ce46 Mon Sep 17 00:00:00 2001 From: Macbook Date: Thu, 11 Jun 2026 00:57:13 +0900 Subject: [PATCH] =?UTF-8?q?=EC=84=9C=EB=B2=84=20=EC=95=8C=EB=A6=BC?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EB=A1=9C=EB=94=A9=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../useTradeNotificationSignalSnapshot.ts | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/frontend/src/hooks/useTradeNotificationSignalSnapshot.ts b/frontend/src/hooks/useTradeNotificationSignalSnapshot.ts index 2b06974..ef77448 100644 --- a/frontend/src/hooks/useTradeNotificationSignalSnapshot.ts +++ b/frontend/src/hooks/useTradeNotificationSignalSnapshot.ts @@ -16,7 +16,10 @@ import { type VirtualIndicatorSnapshot, } from './useVirtualIndicatorSnapshots'; -const MAX_EMPTY_RETRIES = 15; +/** 전략을 찾았지만 백엔드가 아직 조건을 평가하지 않은 경우 — warm-up 대기 (10분) */ +const MAX_EMPTY_RETRIES_WARM = 200; +/** 전략 자체를 찾지 못한 경우 — 빠르게 "데이터 없음" 표시 */ +const MAX_EMPTY_RETRIES_NO_STRATEGY = 3; function staticFallback( market: string, @@ -48,6 +51,7 @@ export function useTradeNotificationSignalSnapshot( const [snapshot, setSnapshot] = useState(); const [loading, setLoading] = useState(false); const emptyRetryRef = useRef(0); + const strategyResolvedRef = useRef(false); const genRef = useRef(0); const refreshInFlightRef = useRef(false); const resolvedStrategyRef = useRef(); @@ -93,6 +97,7 @@ export function useTradeNotificationSignalSnapshot( if (resolved.strategy) { effectiveStrategy = resolved.strategy; resolvedStrategyRef.current = resolved.strategy; + strategyResolvedRef.current = true; } if (resolved.strategyId != null) { effectiveId = resolved.strategyId; @@ -100,6 +105,9 @@ export function useTradeNotificationSignalSnapshot( } } + // 전략을 prop 또는 resolution으로 확보했으면 resolved 표시 + if (effectiveStrategy) strategyResolvedRef.current = true; + const pinFirst = emptyRetryRef.current === 0; let snap = await fetchLiveSnapshot( normalizedMarket, @@ -122,9 +130,13 @@ export function useTradeNotificationSignalSnapshot( if (gen === genRef.current) { setSnapshot(snap ?? undefined); - const stillCollecting = (!snap || snap.rows.length === 0) - && emptyRetryRef.current < MAX_EMPTY_RETRIES; - setLoading(stillCollecting); + const isEmpty = !snap || snap.rows.length === 0; + // 전략이 확인된 경우: 백엔드 warm-up을 충분히 기다림 (10분) + // 전략 자체를 찾지 못한 경우: 빠르게 "데이터 없음" 표시 + const maxRetries = strategyResolvedRef.current + ? MAX_EMPTY_RETRIES_WARM + : MAX_EMPTY_RETRIES_NO_STRATEGY; + setLoading(isEmpty && emptyRetryRef.current < maxRetries); } } finally { refreshInFlightRef.current = false; @@ -145,11 +157,13 @@ export function useTradeNotificationSignalSnapshot( setSnapshot(undefined); setLoading(false); emptyRetryRef.current = 0; + strategyResolvedRef.current = false; resolvedStrategyRef.current = undefined; effectiveStrategyIdRef.current = null; return; } emptyRetryRef.current = 0; + strategyResolvedRef.current = strategy != null; resolvedStrategyRef.current = strategy ? hydrateStrategyDto(strategy) : undefined; effectiveStrategyIdRef.current = strategy?.id ?? rawId; setLoading(true);