Next.js
React 상태를 전역으로 올리면 생기는 문제
Context나 Zustand 같은 전역 상태를 남발하면 컴포넌트 결합도가 높아지고 불필요한 리렌더링이 쌓인다.
React로 개발하다 보면 상태를 어디에 둘지 고민하게 된다. 처음엔 props drilling이 귀찮아서 전부 전역으로 올리게 되는데, 이게 나중에 꽤 골치 아파진다.
전역 상태가 많아지면 생기는 문제
가장 눈에 띄는 건 리렌더링이다. Context를 쓸 경우, Provider가 갖고 있는 값 중 하나라도 바뀌면 그 Context를 구독하는 컴포넌트가 전부 다시 렌더링된다. 관련 없는 데이터를 한 Context에 몰아넣으면 성능 문제가 생긴다.
예를 들어 유저 정보, 알림 목록, UI 테마를 하나의 Context에 넣으면:
// 이렇게 하면 알림 목록이 바뀔 때마다
// 유저 정보만 쓰는 컴포넌트도 리렌더링된다
const AppContext = createContext({
user: null,
notifications: [],
theme: 'light',
})
관심사별로 Context를 나누거나, Zustand처럼 selector를 지원하는 도구를 쓰면 해결된다.
// Zustand: 필요한 슬라이스만 구독
const user = useUserStore((s) => s.user)
전역이 필요한 상태 vs 필요 없는 상태
실제로 전역이 필요한 경우는 생각보다 적다.
- 전역이 맞는 것: 로그인한 유저 정보, 인증 토큰, 앱 전체 테마
- 로컬 상태가 맞는 것: 모달 열림/닫힘, 폼 입력값, 드롭다운 선택
"다른 컴포넌트에서도 이 값이 필요할 것 같은데?"라는 이유로 전역으로 올리면, 실제로 필요해지지 않는 경우가 대부분이다. 나중에 필요해지면 그때 올려도 늦지 않는다.
전역 상태가 많아지면 디버깅도 어렵다
어떤 컴포넌트가 상태를 바꿨는지 추적하기 어려워진다. 로컬 상태는 해당 컴포넌트 안에서만 변경되니까 범위가 명확한데, 전역 상태는 어디서든 바꿀 수 있어서 버그를 찾기가 더 힘들다.
Zustand나 Redux DevTools를 쓰면 어느 정도 추적이 되지만, 근본적으로는 상태를 가능한 한 아래에 두는 게 낫다.
결국 규칙은 단순하다
상태를 쓰는 컴포넌트 중 가장 가까운 공통 조상에 두는 게 기본 원칙이다. 그 공통 조상이 앱 루트가 돼버릴 때만 전역으로 올린다. 이 원칙을 지키는 것만으로도 불필요한 전역 상태 대부분을 막을 수 있다.