부적합: 자주 변하는 list, 입력 값, 폼 state. → Zustand / Redux / Jotai.
변화 빈도와 소비자 수가 동시에 크면 split.
💻 코드 패턴
Split by frequency
constStaticContext=createContext({apiClient,theme});// 거의 안 바뀜
constPresenceContext=createContext({onlineUsers});// 자주 바뀜
<StaticContext.Providervalue={static}><PresenceContext.Providervalue={presence}>{children}</PresenceContext.Provider></StaticContext.Provider>
Selector hook
functionuseUserName() {const{user}=useContext(AuthContext);returnuser.name;// 그래도 user 객체가 바뀌면 모든 소비자 재렌더
}// 진짜 selector 가 필요하면 zustand 또는 use-context-selector 라이브러리.
Provider value 안정화
functionAuthProvider({children}){const[user,setUser]=useState(null);constvalue=useMemo(()=>({user,setUser}),[user]);// 매 렌더 새 객체 방지
return<AuthContext.Providervalue={value}>{children}</AuthContext.Provider>;}
🤔 의사결정 기준
데이터 성격
Context
외부 store
정적 설정 (theme, locale)
✅
❌
인증 user
✅
OK either
실시간 presence / cursor
❌
✅
Form state
❌
react-hook-form
캐시된 서버 데이터
❌
React Query / SWR
UI 상태 (modal open, selection)
✅ (좁은 영역)
✅
❌ 안티패턴
value 가 매 렌더 새 객체: 모든 소비자 재렌더. useMemo / useState 결과 그대로.
한 Context 에 모든 글로벌 상태: GodContext. split 또는 store.
deeply nested Provider hell (10단계+): 드릴링이 더 나을 수도. 또는 store 통합.
Context 안의 Date/Map/Set 직접 mutate: 소비자에게 변경 안 알림. 새 인스턴스 반환.
default value 에 throw 안 던지기: Provider 잊으면 silent default. 안전하게:
constctx=useContext(MyContext);if(!ctx)thrownewError('useMyContext must be used within MyProvider');
🤖 LLM 활용 힌트
상태 라이브러리 선택지 명시: "이 데이터는 Context vs Zustand vs React Query 중 어디?"