글을 불러오는 중…
글을 불러오는 중…
React에서 Zustand Store와 Context Provider 함께 사용할 때 발생하는 불필요한 리렌더링 문제 해결하기 문제 상황 호텔 검색 기능을 구현하면서 다음과 같은 문제가 발생했습니다: 이 코드에서 발생한 문제: 1. Provider가 리렌더링될 때마다 새로운 stor…
호텔 검색 기능을 구현하면서 다음과 같은 문제가 발생했습니다:
// SearchProvider.tsx
export function SearchProvider({ children }: { children: ReactNode }) {
const store = createSearchStore(); // 매 리렌더링마다 새로운 store 생성
const searchParams = useSearchParams();
const { isLoggedIn } = useAuthStore();
const fetcher = useCallback(() => {
store.getState().fetchResults({ ...searchParams, isLoggedIn });
}, [searchParams, isLoggedIn, store]);
useEffect(() => {
if (searchParams) {
fetcher();
}
}, [searchParams, fetcher]);
return (
<SearchContext.Provider value={store}>
{children}
</SearchContext.Provider>
);
}
이 코드에서 발생한 문제:
Provider가 리렌더링될 때마다 새로운 store 인스턴스가 생성됨
store가 의존성 배열에 포함되어 있어 불필요한 fetcher 호출 발생
결과적으로 초기 렌더링 시 3번의 API 호출이 발생
Store 생성 위치의 문제
컴포넌트 내부에서 store를 생성하면 리렌더링마다 새로운 인스턴스가 생성됨
이는 Zustand store의 싱글톤 특성을 해치는 패턴
의존성 배열의 문제
store가 의존성 배열에 포함되어 있어 store 참조가 변경될 때마다 useEffect가 실행됨
이는 불필요한 API 호출을 유발
// searchStore.ts
export const createSearchStore = () => {
return createStore<SearchStore>()(
immer((set, get) => ({
// store 구현
}))
);
};
// SearchProvider.tsx
const store = createSearchStore(); // 모듈 레벨에서 한 번만 생성
export function SearchProvider({ children }: { children: ReactNode }) {
const searchParams = useSearchParams();
const { isLoggedIn } = useAuthStore();
const fetcher = useCallback(() => {
store.getState().fetchResults({ ...searchParams, isLoggedIn });
}, [searchParams, isLoggedIn]); // store 의존성 제거
useEffect(() => {
if (searchParams) {
fetcher();
}
}, [searchParams, fetcher]);
return (
<SearchContext.Provider value={store}>
{children}
</SearchContext.Provider>
);
}
store를 의존성 배열에서 제거
실제로 필요한 의존성만 포함 (searchParams, isLoggedIn)
성능 향상
불필요한 store 재생성 방지
불필요한 API 호출 감소
코드 품질 향상
Zustand store의 싱글톤 특성 유지
더 예측 가능한 렌더링 동작
메모리 사용 최적화
Provider의 생명주기
Provider는 일반적으로 애플리케이션의 최상위 레벨에서 한 번만 마운트됨
하지만 React Strict Mode나 개발 환경에서는 컴포넌트가 두 번 마운트될 수 있음
Store 초기화 시점
모듈 레벨에서 store를 생성하면 애플리케이션 시작 시 한 번만 초기화됨
이는 대부분의 경우 바람직한 동작이지만, 특정 상황에서는 동적 초기화가 필요할 수 있음
Zustand store와 Context Provider를 함께 사용할 때는 store를 컴포넌트 외부에서 생성하고, 의존성 배열을 최적화하는 것이 중요합니다. 이는 불필요한 리렌더링을 방지하고 애플리케이션의 성능을 향상시키는 데 도움이 됩니다.