Skip to content

fix: 컴포넌트 binding audit + 14건 수정 + props 11개 추가#157

Open
zeakd wants to merge 6 commits intomainfrom
feat/examples
Open

fix: 컴포넌트 binding audit + 14건 수정 + props 11개 추가#157
zeakd wants to merge 6 commits intomainfrom
feat/examples

Conversation

@zeakd
Copy link
Copy Markdown
Owner

@zeakd zeakd commented May 2, 2026

Summary

전체 컴포넌트의 props ↔ SDK 결합 audit + 2회 코드 리뷰 후속 + 외부 패턴 리서치까지 반영한 종합 라운드.

SDK 옵션 저장 패턴(A: _mapOptions 분리 / B: setX 부수효과 / C: _<key>_changed / D: 일방향·static) 정립.

3 commits: 2480ec0 (1차) → f470669 (1차 리뷰 후속 A-D) → 7348f88 (2차 리뷰 후속).

라이브러리 코어

  • useControlledKVO: setter 우선순위 setX > setOptions > set. Map은 옵션을 별도 _mapOptions KVO에 저장하므로 직접 target.set()으론 SDK가 무시. setMapTypeId처럼 부수효과 있는 setX는 우선 사용.
  • useKVO: Map의 옵션 키 구독을 _mapOptions로 라우팅. useKVO(map, 'draggable') 등 정상 발화 수신.
  • kvoEquals: 양쪽 모두 시도 (prev=literal, new=instance 비대칭 해소)

컴포넌트 버그 수정

컴포넌트 변경
NaverMap minZoom/maxZoom static → controlled
NaverMap onInit/onIdle/onTilesloaded useEffectuseLayoutEffect (init 박빙 방지)
NaverMap logoControl 일방향 controlled 분류 정밀화 + dev warn (한 번만, ref 가드)
TrafficLayer autoRefresh undefined 시 endAutoRefresh 호출 안 함
InfoWindow setOptions(obj) 일괄 → per-key useControlledKVO
InfoWindow onOpen/onClose listener를 useLayoutEffect로 (방어적, fix-16)
GroundOverlay SDK 미발화 이벤트(dblclick/mouseover/out/move) 타입 축소
CustomOverlay pane static 명시 + position/anchor kvoEquals 비교

신규 controlled props (11개)

  • NaverMap: cursor, tilt (+onTiltChanged), rotation (+onRotationChanged), tileDuration
  • NaverMap static: repeatX, gl, customStyleId, useStyleMap
  • GroundOverlay: crossOrigin
  • Polygon/Polyline: simplifyLevel

개발자 경험

  • 신규 internal hook useStaticProp: dev/prod 함수 선택 패턴으로 production DCE 시도. undefined grace period로 비동기 prop 패턴({config?.gl}) false positive 방지.
  • DCE 실측 통과: Astro/Vite production 빌드에서 'static prop', 'useStaticPropDev', 한국어 dev warn 모두 0건 ✓
  • 메시지 영문 + 한국어 병기: 외부 라이브러리(downshift/react-aria 등)는 영문만 — 1.0에서 영문 통일 검토

이벤트 등록 시점 정책 (fixes/16)

  • SDK 동기 발화 (init/idle/open/close/tilesloaded): useLayoutEffect로 등록
  • 사용자 인터랙션 (click/drag 등): useEffect 등록 OK
  • audit 결과: 우리 노출 props 모두 적정 처리 (research/bindings/sync-fired-events-audit.md)

회귀 테스트

121 → 160 tests 통과 (25 files, +39 신규).

신규 회귀 테스트:

  • naver-map-controlled.spec.tsx — fix 01/02/05/13/15
  • info-window.spec.tsx 보강 — fix 08, fix-16 timing
  • traffic-layer.spec.tsx 보강 — fix 07
  • event-types.spec.ts 강화 — fix 09 (toEqualTypeOf)
  • custom-overlay.spec.tsx 보강 — fix 10
  • hooks/__tests__/use-kvo.spec.tsx — fix 06
  • hooks/__tests__/use-static-prop.spec.tsx — fix 14 + grace period
  • __tests__/strict-mode.spec.tsx 신규 — StrictMode 더블 마운트 7건
  • __tests__/kvo-equals.spec.ts — 양쪽 비교

외부 패턴 리서치 (related-patterns-research.md)

4개 라이브러리 비교 (@react-google-maps/api, react-map-gl, react-leaflet, @react-three/fiber):

  • react-map-gl과 가장 정렬useIsomorphicLayoutEffect + per-prop diff
  • downshift의 initial-/default- prefix가 가장 깔끔 — 0.3에서 하이브리드 도입 검토
  • useSyncExternalStore caveat 확인: 매 프레임 mutate 시 blocking으로 떨어짐 → 우리 useControlledKVO 재설계(dirty diff) 결정 정당화
  • 0.3 후보: initial- prefix, useKVOFrame (RAF throttle), DCE 가드 표준화
  • 1.0 후보: 영문 통일, Activity 호환성 명시, 번들 검사 CI

Breaking 가능성 (사실상 없음)

변경 영향
GroundOverlay 이벤트 타입 축소 SDK 미발화 이벤트라 실제 영향 0
CustomOverlay pane 변경 무시 명시 이전에도 무시됨

Changeset

patch bump (0.2.0 → 0.2.1).

보류 결정 (decisions/)

  • CompassControl: SDK 번들에 클래스 정의 없음 (legacy stub) — 미노출

🤖 Generated with Claude Code

전체 컴포넌트의 props ↔ SDK 결합 audit 결과를 반영. SDK 옵션 저장 패턴(A: _mapOptions 분리, B: setX 부수효과, C: _<key>_changed, D: 일방향/static)을 정밀화하고, 발견된 버그를 수정하며, 누락 옵션을 노출.

핵심:
- useControlledKVO/useKVO가 Map의 _mapOptions로 정확히 라우팅
- setter 우선순위 setX > setOptions > set (mapTypeId registry 전환 등)
- onInit/onIdle/onTilesloaded을 useLayoutEffect로 이동 (init 발화 누락 방지)
- InfoWindow를 per-key useControlledKVO로 전환 (인라인 객체 폭주 방지)
- TrafficLayer autoRefresh undefined 가드
- GroundOverlay 미발화 이벤트 타입 축소
- CustomOverlay equality + pane static 명시
- logoControl 일방향 controlled 분류 정밀화
- 신규 props: cursor/tilt/rotation/tileDuration/repeatX/gl/customStyleId/useStyleMap/crossOrigin/simplifyLevel
- 신규 internal hook useStaticProp (dev mode warn)

회귀 테스트 121 -> 147개. CompassControl은 SDK 클래스 정의 부재로 보류 결정.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zeakd zeakd changed the base branch from dev to main May 2, 2026 14:46
zeakd and others added 5 commits May 3, 2026 00:09
리뷰에서 도출된 6개 Major + 8개 Minor 항목 처리.

Group A (안전한 즉시 수정):
- useStaticProp: dev/prod 함수 선택 패턴으로 production DCE 가능 (effect 슬롯 0)
- kvoEquals: 양쪽 어느 쪽이든 equals 있으면 시도 (literal vs instance 비대칭 해소)
- logoControl false warn: ref 가드로 한 번만 출력 + 회귀 테스트 3건

Group B (측정으로 검증):
- NaverMap 38개 useControlledKVO: 단일 토글 36 get + 8 set, 16ms 내. 이론적 우려 대비 실측 OK
- InfoWindow per-key 동등성: bulk vs per-key 모두 1 draw + 1 resize. SDK _drawRequired 플래그가 중복 draw 방지

Group C (이벤트 등록 시점 정책):
- InfoWindow onOpen/onClose를 useLayoutEffect로 이동. open() 호출 직후 동기 발화하는
  'open' 이벤트를 listener 미등록으로 놓치는 timing bug 해소 (fix-13과 동일 원리)
- 정책 명문화: SDK 동기 발화 = useLayoutEffect, 사용자 인터랙션 = useEffect

Group D (Minor 정리):
- console.warn 메시지 영문 우선 + 한국어 보조 (한영 병기)
- StrictMode 더블 마운트 회귀 테스트 7건 추가
- *Options 런타임 audit (zoomControlOptions 등 5개) — 모두 controlled 동작 확정
- useNaverMapStatic vs satisfies 패턴 정책 명시 (3+ 호출 wrapper, 1-2 satisfies)

테스트: 147 -> 160 (+13). 빌드 통과.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2차 리뷰 결과 처리:

1. fix-16 회귀 테스트 catch 능력 보강 — 분석 결과 솔직히 인정
   - test-utils의 mock InfoWindow.open()이 'open' 이벤트 동기 발화하도록 수정
   - 테스트가 onOpen 호출을 직접 검증
   - 결론: 같은 컴포넌트 내 hook 등록 순서가 React에서 보장되므로 useLayoutEffect/useEffect
     차이가 사실상 없음. fix-16은 방어적 보수책. fixes/16에 한계 + 의도 명시

2. vitest.config.ts headless 잠금
   - PWDEBUG/HEADED 환경변수 명시 차단
   - browser.headless: true + launch.headless: true 이중 명시
   - launch.devtools: false

3. SDK 동기 발화 이벤트 audit (미커밋, research/bindings/sync-fired-events-audit.md)
   - OverlayView의 added/removed/draw 이벤트는 우리 prop으로 미노출 → 영향 없음
   - 모든 노출 props가 적정 timing으로 처리됨 확인

테스트: 25 files, 160 tests 통과.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR #152(commit 4a12e35)에서 astro-component-docs의 test 스크립트가 'bun test src/'로
변경되었으나 ci.yml에 bun 설치 단계가 누락되어 CI가 지속적으로 실패. setup-bun@v2 추가.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vitest browser mode가 Playwright Chromium 헤드리스 브라우저를 launch하므로,
'pnpm exec playwright install --with-deps chromium' 단계 추가. 이전엔 호스트 환경에
설치되어 있어서 우회됐을 가능성.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant