perf(map): 해저케이블 렌더링 최적화

- GeoJSON source tolerance:1, buffer:64 (저줌 vertex 단순화)
- hitarea/casing/glow 레이어 minzoom:3 (저줌 렌더 제외)
- ensureGeoJsonSource에 source options 파라미터 추가
- NativeSourceConfig에 options 필드 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
htlee 2026-02-16 05:28:44 +09:00
부모 a16ccc9a01
커밋 f5ef24c02f
3개의 변경된 파일10개의 추가작업 그리고 3개의 파일을 삭제

파일 보기

@ -14,7 +14,7 @@
* useEffect에서 . * useEffect에서 .
*/ */
import { useEffect, useRef, type MutableRefObject } from 'react'; import { useEffect, useRef, type MutableRefObject } from 'react';
import maplibregl, { type LayerSpecification } from 'maplibre-gl'; import maplibregl, { type GeoJSONSourceSpecification, type LayerSpecification } from 'maplibre-gl';
import { ensureGeoJsonSource, ensureLayer, setLayerVisibility, cleanupLayers } from '../lib/layerHelpers'; import { ensureGeoJsonSource, ensureLayer, setLayerVisibility, cleanupLayers } from '../lib/layerHelpers';
import { kickRepaint, onMapStyleReady } from '../lib/mapCore'; import { kickRepaint, onMapStyleReady } from '../lib/mapCore';
@ -23,6 +23,8 @@ import { kickRepaint, onMapStyleReady } from '../lib/mapCore';
export interface NativeSourceConfig { export interface NativeSourceConfig {
id: string; id: string;
data: GeoJSON.GeoJSON | null; data: GeoJSON.GeoJSON | null;
/** GeoJSON source 옵션 (tolerance, buffer 등) */
options?: Partial<Omit<GeoJSONSourceSpecification, 'type' | 'data'>>;
} }
export interface NativeLayerSpec { export interface NativeLayerSpec {
@ -101,7 +103,7 @@ export function useNativeMapLayers(
// 3. Source 생성/업데이트 // 3. Source 생성/업데이트
for (const src of cfg.sources) { for (const src of cfg.sources) {
if (src.data) { if (src.data) {
ensureGeoJsonSource(map, src.id, src.data); ensureGeoJsonSource(map, src.id, src.data, src.options);
} }
} }

파일 보기

@ -33,6 +33,7 @@ const LAYER_SPECS: NativeLayerSpec[] = [
sourceId: SRC_ID, sourceId: SRC_ID,
paint: { 'line-color': 'rgba(0,0,0,0)', 'line-width': 14, 'line-opacity': 0 }, paint: { 'line-color': 'rgba(0,0,0,0)', 'line-width': 14, 'line-opacity': 0 },
layout: { 'line-cap': 'round', 'line-join': 'round' }, layout: { 'line-cap': 'round', 'line-join': 'round' },
minzoom: 3,
}, },
{ {
id: CASING_ID, id: CASING_ID,
@ -44,6 +45,7 @@ const LAYER_SPECS: NativeLayerSpec[] = [
'line-opacity': CASING_OPACITY_DEFAULT, 'line-opacity': CASING_OPACITY_DEFAULT,
}, },
layout: { 'line-cap': 'round', 'line-join': 'round' }, layout: { 'line-cap': 'round', 'line-join': 'round' },
minzoom: 3,
}, },
{ {
id: LINE_ID, id: LINE_ID,
@ -68,6 +70,7 @@ const LAYER_SPECS: NativeLayerSpec[] = [
}, },
filter: ['==', ['get', 'id'], ''], filter: ['==', ['get', 'id'], ''],
layout: { 'line-cap': 'round', 'line-join': 'round' }, layout: { 'line-cap': 'round', 'line-join': 'round' },
minzoom: 3,
}, },
{ {
id: POINTS_ID, id: POINTS_ID,
@ -156,7 +159,7 @@ export function useSubcablesLayer(
reorderGlobeFeatureLayers, reorderGlobeFeatureLayers,
{ {
sources: [ sources: [
{ id: SRC_ID, data: subcableGeo }, { id: SRC_ID, data: subcableGeo, options: { tolerance: 1, buffer: 64 } },
{ id: POINTS_SRC_ID, data: pointsGeoJson }, { id: POINTS_SRC_ID, data: pointsGeoJson },
], ],
layers: LAYER_SPECS, layers: LAYER_SPECS,

파일 보기

@ -71,6 +71,7 @@ export function ensureGeoJsonSource(
map: maplibregl.Map, map: maplibregl.Map,
sourceId: string, sourceId: string,
data: GeoJSON.GeoJSON, data: GeoJSON.GeoJSON,
options?: Partial<Omit<GeoJSONSourceSpecification, 'type' | 'data'>>,
) { ) {
const existing = map.getSource(sourceId); const existing = map.getSource(sourceId);
if (existing) { if (existing) {
@ -79,6 +80,7 @@ export function ensureGeoJsonSource(
map.addSource(sourceId, { map.addSource(sourceId, {
type: 'geojson', type: 'geojson',
data, data,
...options,
} satisfies GeoJSONSourceSpecification); } satisfies GeoJSONSourceSpecification);
} }
} }