From 2a2e4e3590baafb9375d56afcf4f0934ef0b200d Mon Sep 17 00:00:00 2001 From: htlee Date: Mon, 23 Mar 2026 12:37:58 +0900 Subject: [PATCH] =?UTF-8?q?perf:=20LIVE=20=EB=AA=A8=EB=93=9C=20=EB=A7=A4?= =?UTF-8?q?=EC=B4=88=20=EC=84=A0=EB=B0=95=20=EC=9E=AC=EA=B3=84=EC=82=B0=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20=E2=80=94=20=EB=8F=99=EC=9D=BC=20=EC=B0=B8?= =?UTF-8?q?=EC=A1=B0=20=EB=B0=98=ED=99=98=EC=9C=BC=EB=A1=9C=20=ED=95=98?= =?UTF-8?q?=EC=9C=84=20useMemo=20=EC=97=B0=EC=87=84=20=EC=B0=A8=EB=8B=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - LIVE 모드: enrichedShipsRef 동일 참조 반환 → currentTime 매초 변경 시에도 visibleShips/filteredShips/shipGeoJson 재실행 안 함 - mtCategory/natGroup: baseShipsKorea 변경 시 1회 새 배열 생성 (useState 불변성 준수) - REPLAY 모드: propagateShips로 위치 보간 유지 (mtCategory는 spread로 상속) Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/hooks/useKoreaData.ts | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/frontend/src/hooks/useKoreaData.ts b/frontend/src/hooks/useKoreaData.ts index 95b3e1a..cec7547 100644 --- a/frontend/src/hooks/useKoreaData.ts +++ b/frontend/src/hooks/useKoreaData.ts @@ -145,15 +145,24 @@ export function useKoreaData({ // Propagate Korea aircraft (live only — no waypoint propagation needed) const aircraft = useMemo(() => propagateAircraft(baseAircraftKorea, currentTime), [baseAircraftKorea, currentTime]); - // Korea region ships — pre-compute mtCategory/natGroup for O(1) filter lookups - const ships = useMemo(() => { - const propagated = propagateShips(baseShipsKorea, currentTime, isLive); - for (const s of propagated) { - s.mtCategory = getMarineTrafficCategory(s.typecode, s.category); - s.natGroup = getNationalityGroup(s.flag); - } - return propagated; - }, [baseShipsKorea, currentTime, isLive]); + // Pre-compute mtCategory/natGroup on base data change (5-min polling) + // useState 값 직접 변경 불가 → 새 배열을 ref에 저장 + const enrichedShipsRef = useRef([]); + useMemo(() => { + enrichedShipsRef.current = baseShipsKorea.map(s => ({ + ...s, + mtCategory: getMarineTrafficCategory(s.typecode, s.category), + natGroup: getNationalityGroup(s.flag), + })); + }, [baseShipsKorea]); + + // Korea region ships + // LIVE: enrichedShipsRef 동일 참조 반환 → 하위 useMemo 재실행 방지 (매초 currentTime 변경 무시) + // REPLAY: propagateShips로 위치 보간 → 새 배열 반환 (mtCategory는 spread로 상속) + const ships = useMemo( + () => isLive ? enrichedShipsRef.current : propagateShips(enrichedShipsRef.current, currentTime, false), + [baseShipsKorea, currentTime, isLive], + ); // Category-filtered data for map rendering (Set.has = O(1) per ship) const visibleAircraft = useMemo(