Skip to content

refactor: deepCompare → shallow 비교로 전환 (zustand 방식, breaking change) - #5

Merged
ayden94 merged 3 commits into
mainfrom
refactor/shallow-compare
Jul 19, 2026
Merged

refactor: deepCompare → shallow 비교로 전환 (zustand 방식, breaking change)#5
ayden94 merged 3 commits into
mainfrom
refactor/shallow-compare

Conversation

@ayden94

@ayden94 ayden94 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #3deepCompareshallow 비교로 전환 (zustand 방식).

Breaking Change

React 어댑터의 selector 비교 방식을 deep compare에서 shallow compare로 변경. shallow가 항상 적용됨 (옵션 아님).

Changes

New: src/core/shared/shallow.ts

zustand의 shallow 구현을 참고하여 작성:

  • Object.is → 1단계 비교
  • Map: entries() 비교
  • Set: iterator 비교
  • 배열: iterator 비교
  • 일반 객체: Object.entries() 비교
  • Date: 프로토타입 비교 (같으면 같음 — selector에서 getTime() 권장)
  • 순환 참조 안전 (1단계만 비교하므로)

src/core/React/createUseState.ts

  • deepCompare 제거
  • shallowuseStoreState에 내장 — 항상 shallow 적용
  • useSyncExternalStore에 직접 selector 전달 방식으로 단순화
  • 메모이제이션 로직을 shallow 기반으로 재작성

Deleted: src/core/shared/deepCompare.ts

Tests: test/shallow.test.ts — 21개

  • 원시값, 객체, 배열, Map, Set, Date, 순환 참조 안전성

Docs

  • README.md / README.ko.md: 마이그레이션 가이드 추가

Performance

Before (deep) After (shallow)
매 렌더링 비교 비용 전체 state 재귀 순회 1단계 비교만
Map/Set/Date 잘못된 비교 올바른 shallow 비교
순환 참조 스택 오버플로우 안전

Verification

pnpm run build     → BUILD_OK
pnpm run typecheck → TYPECHECK_OK
pnpm test          → 136 pass, 0 fail (762 expect calls)

기존 115개 테스트 전부 통과 (회귀 없음) + 21개 shallow 테스트 추가.

Closes #3

ayden94 added 3 commits July 19, 2026 18:39
Breaking change: React 어댑터의 selector 비교 방식을 deep compare에서
shallow compare로 변경.

## 변경 사항

- src/core/shared/shallow.ts: shallow 함수 구현 (zustand 참고)
  - Object.is → 1단계 비교
  - Map: entries() 비교
  - Set: iterator 비교
  - 배열: iterator 비교
  - 일반 객체: Object.entries() 비교
  - Date: 프로토타입 비교 (같으면 같음 — selector에서 getTime() 권장)
  - 순환 참조 안전 (1단계만 비교)

- src/core/React/createUseState.ts:
  - deepCompare 제거, shallow를 useStoreState에 내장 (항상 shallow 적용)
  - useSyncExternalStore에 직접 selector 전달 방식으로 단순화
  - 메모이제이션 로직을 shallow 기반으로 재작성

- src/core/shared/deepCompare.ts: 삭제

- test/shallow.test.ts: 21개 단위 테스트
  - 원시값, 객체, 배열, Map, Set, Date, 순환 참조 안전성

- README.md / README.ko.md: 마이그레이션 가이드 추가
  - deep → shallow 변경 이유와 영향
  - 깊은 비교가 필요한 경우 useMemo 권장

## 성능 개선

- 매 렌더마다 전체 state를 재귀 순회 → 1단계 비교만
- Map/Set/Date 올바른 비교 (기존 deepCompare 버그 수정)
- 순환 참조 스택 오버플로우 해결

## 기존 테스트 회귀

115개 기존 테스트 전부 통과 (변경 없음)
+ 21개 shallow 테스트 = 136개 전부 통과

Closes #3
High: shallowSelector 클로저가 store 변경에 안전하지 않은 문제 수정
- getSnapshot과 getServerSnapshot이 별도의 createShallowSelector
  인스턴스를 생성하도록 분리
- store 의존성이 두 useMemo에 모두 포함되어 store 변경 시
  클로저가 재생성됨
- 서버/클라이언트 hydration 불일치 및 stale 참조 문제 해결

Medium: Date 비교를 getTime() 기반으로 개선
- shallow 함수에 Date instanceof 체크 추가
- 다른 시각의 Date가 같다고 판단되는 문제 해결
- 테스트 및 README 마이그레이션 가이드 업데이트

Low: shallow.ts 끝 개행 추가
- .changeset/shallow-selector-breaking.md: major changeset documenting
  the deepCompare -> shallow breaking change with migration notes
- README.md / README.ko.md: bump migration heading to v2.0.0 (was v1.1.0),
  mark as breaking change, add 'Keep selector identity stable' section
  explaining how inline selectors reset createShallowSelector's cache and
  recommending module-scope selectors or useCallback
@ayden94
ayden94 force-pushed the refactor/shallow-compare branch from 9933448 to 4e99628 Compare July 19, 2026 09:42
@ayden94
ayden94 merged commit 77d382f into main Jul 19, 2026
1 check failed
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.

fix: deepCompare가 Map, Set, Date를 올바르게 비교하지 못함

1 participant