Skip to content

Commit ee01e59

Browse files
zeakdclaude
andcommitted
docs: KVO 훅 read/write 비대칭 전제 주석 + changeset 정정 + gitignore
- use-controlled-kvo / use-kvo: 읽기 경로와 쓰기/구독 경로의 대상 선택 조건이 서로 달라 'SDK가 동일 슬롯에 라우팅한다'는 전제에 의존함을 주석화. (동작 변경 아님 — 미래 SDK 변경 시 주의점 명시) - changeset: dblclick 유지/tileDuration static/테스트 카운트 정정 - gitignore: __screenshots__ (vitest 산출물), examples/ (작업 중 — stash 보관, 별도 브랜치로 분리 예정. lint 오염 방지) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 96af489 commit ee01e59

4 files changed

Lines changed: 22 additions & 5 deletions

File tree

.changeset/bindings-audit-0-2-1.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313
- NaverMap: `onInit/onIdle/onTilesloaded` 등록을 `useEffect``useLayoutEffect`로 이동. SDK 동기 발화 케이스에서 init 누락 방지.
1414
- TrafficLayer: `autoRefresh` 미지정 시 `endAutoRefresh` 호출하지 않음 (이전엔 강제 비활성화).
1515
- InfoWindow: `setOptions(obj)` 일괄 호출을 per-key `useControlledKVO`로 전환. 인라인 객체 props 시 폭주 방지.
16-
- GroundOverlay: SDK가 발화하지 않는 dblclick/mouseover/mouseout/mousemove 이벤트 prop 제거 (타입 축소).
16+
- GroundOverlay: SDK가 발화하지 않는 mouseover/mouseout/mousemove 이벤트 prop 제거 (타입 축소). `dblclick`은 click 리스너가 연속 클릭을 합성 발화하므로 유지.
1717
- CustomOverlay: `pane` static 명시. position/anchor를 `kvoEquals` 비교 후 호출.
1818
- NaverMap: `logoControl` 분류 정밀화 — SDK가 `false`를 거부하는 일방향 controlled. `false` 시도 시 dev 안내.
1919

2020
### 신규 controlled props
21-
- NaverMap: `cursor`, `tilt` (+`onTiltChanged`), `rotation` (+`onRotationChanged`), `tileDuration`
22-
- NaverMap static: `repeatX`, `gl`, `customStyleId`, `useStyleMap`
21+
- NaverMap: `cursor` (드래그 중 SDK 자체 토글과 충돌 가능 — JSDoc 주의 명시), `tilt` (+`onTiltChanged`), `rotation` (+`onRotationChanged`)
22+
- NaverMap static: `repeatX`, `gl`, `customStyleId`, `useStyleMap`, `tileDuration` (SDK에 setter/`_changed` 없이 타일 생성 시에만 읽힘)
2323
- GroundOverlay: `crossOrigin`
2424
- Polygon/Polyline: `simplifyLevel`
2525

@@ -32,8 +32,8 @@
3232
- `examples/map-geolocation`: 공식 tutorial 동작과 정렬 (`open` prop 명시 + 콘텐츠 스타일).
3333

3434
### 회귀 테스트
35-
- 121개 → **147개** 통과. 모든 fix 시나리오 커버.
35+
- 121개 → **174개** 통과. 모든 fix 시나리오 커버. `event-types.spec.ts`는 vitest `typecheck`로 실제 평가(이전엔 런타임 no-op).
3636

3737
### Breaking 가능성 (사실상 없음)
38-
- GroundOverlay 이벤트 타입 축소: 기존 코드에서 `onMouseover` 등을 사용했더라도 SDK가 발화하지 않았으므로 실제 동작 변화 없음.
38+
- GroundOverlay 이벤트 타입 축소: 기존 코드에서 `onMouseover`/`onMouseout`/`onMousemove`사용했더라도 SDK가 발화하지 않았으므로 실제 동작 변화 없음. (`onDblclick`은 유지)
3939
- CustomOverlay `pane` 변경: 이전에도 무시되던 동작이 이제 dev 경고로 명시.

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,9 @@ research/
8787
test-results/
8888
__tile_cache__/
8989
screenshots/CLAUDE.md
90+
91+
# Vitest browser mode 산출물
92+
__screenshots__/
93+
94+
# 통합 예제 (작업 중 — 별도 브랜치/PR로 분리 예정. stash 보관)
95+
examples/

packages/react-naver-maps/src/hooks/use-controlled-kvo.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ export function useControlledKVO(
109109
const hasOptions =
110110
typeof t.setOptions === 'function' && typeof t.getOptions === 'function';
111111

112+
// 주의: 읽기(getter/getOptions/get)와 쓰기(setter/setOptions/set) 경로를 독립적으로
113+
// 선택한다. "전용 getter는 없지만 전용 setter는 있는" prop(예: Marker position —
114+
// setPosition은 있고 getPosition은 없음)에서는 읽기는 getOptions/get, 쓰기는 setPosition을
115+
// 탄다. 현재 SDK에서는 이들이 동일 KVO 슬롯을 보므로 결과가 일관되지만, 이는 SDK 구현이
116+
// setX와 setOptions/set을 같은 슬롯에 라우팅한다는 전제에 의존한 정합성이다.
112117
let current: unknown;
113118
if (hasGetter) {
114119
current = (t[getterName] as () => unknown)();

packages/react-naver-maps/src/hooks/use-kvo.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ export function useKVO<T>(target: naver.maps.KVO, property: string): T {
3333
_mapOptions?: naver.maps.KVO;
3434
};
3535
// Map은 옵션을 _mapOptions에 저장. 거기에 구독해야 발화 받음.
36+
//
37+
// 주의: 구독 대상 선택(_mapOptions ?? target)과 읽기 대상 선택(getOptions ?? get)의
38+
// 조건이 서로 다르다. "getOptions는 있지만 _mapOptions는 없는" 대상(Shape/Marker)에서는
39+
// 구독은 본체 KVO(target)에, 읽기는 getOptions(→get)에 간다. 현재 SDK에서는 둘이 동일
40+
// 슬롯을 보므로 정합하지만, Map은 getOptions('minZoom')이 클램프된 userMinZoom을 반환하는 등
41+
// _mapOptions.get과 의미가 다른 키가 있어, 채널 일치를 깨는 SDK 변경이 있으면 주의가 필요하다.
3642
const t = target as WithOptions;
3743
const optionsTarget = t._mapOptions ?? null;
3844

0 commit comments

Comments
 (0)