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);