[React] Context API : High Frequency updates

two-threeMin·2022년 7월 12일
0

High Frequency updates

Context API보다 Redux의 어떤 장점 때문에 많이 사용하는 걸까 라는 생각이 들어서 "Context API의 한계"에 대해서 찾아보던 중

React Context is Not optimized for high frequency updates.

이유가 무엇일까 생각해보니, React 공식문서에서 Context는

Provider 하위에서 context를 구독하는 모든 컴포넌트는 Provider의 value prop가 바뀔 때마다 다시 렌더링 됩니다.

// store/rundata-context.js 
export const RunDataContext = React.createContext({
  runData: [],
  appendRunIten: () => {},
});

export const RunDataContextProvider = ({ ...props }) => {
  const [runData, setRunData] = useState();

   const appendRunItem = (newRunData) => {
    setRunData([newRunData, ...runData]);
  };

  return (
    <RunDataContext.Provider
      value={{ appendRunItem, runData }}
    >
      {props.children}
    </RunDataContext.Provider>
  );
// component/RunHome.js
import { RunDataContextProvider } from 'store/rundata-context';

export const RunHome = () => {
  initLocalData();

  return (
    // RunDataContextProvider의 value prop이 바뀔때마다
    // AddRunItem, RunItemList는 re-rendering 된다.
    <RunDataContextProvider>
      <AddRunItem />
      <RunItemList />
    </RunDataContextProvider>
  );
};

예시와 함께 보자면, RunDataContextProvider value prop이 바뀌면 해당되는 Context에 속하는(Context Provider Component 자식인) AddRunItem, RunItemList Component도 re-rendering 됩니다.

이러한 이유로 빈번한 상태 변화가 있을 경우에는 설계에 따라 크게 자원이 소모될 수 있기 때문에 "빈번한 변화에 최적화되어 있지 않다." 라고 쓰여있던 것이라고 생각합니다.

  • React Context is Not optimized for high frequency updates.

eslint : react/jsx-no-constructed-context-values

프로젝트에 Context API만을 적용하면 eslint에서 다음과 관련된 에러가 발생합니다.

위 링크에서도

이것은 컨텍스트 공급자와 소비자가 하위 트리의 모든 요소를 다시 렌더링하게 할 뿐만 아니라 공급자를 렌더링하고 소비자를 찾기 위해 트리 스캔 반응에 대한 처리도 낭비되기 때문에 성능이 상당히 저하될 수 있습니다.

여기서 다시 드는 생각이 그러면 React.Memo로 부모 컴포넌트의 변화에 대응하고, 위 eslint에서 언급한 것처럼 useMemo, useCallback을 사용하면 되는거 아닌가? 하는 의문이 들 때쯤에 이 질문을 던졌던 톡방에 선생님이 답변을 주셨는데 감사합니다..

답변(위 내용의 요약)

복잡한 전역 상태 관리를 해야 할 때 ContextAPI는 Context가 공급하는 value가 변경되면 해당 Context에 속하는(ContextProvider 컴포넌트의 자식인) 컴포넌트들이 모두 리렌더 됩니다.
반면 Redux는 스토어의 특정 값이 변화하였을 때 해당 값을 구독하고 있는 컴포넌트만 리렌더가 발생합니다.
물론 Context를 사용할 때에도 Context 분리, useCallback, useMemo, React.memo으로도 Redux와 동일한 급의 최적화가 가능하지만 그 정도로 최적화가 필요하고 복잡한 상태관리가 필요하다면 Redux가 현명한 대안이 될 수 있습니다.

결론

현재 프로젝트처럼 규모가 작은 프로젝트에서는 Context API와 메모이제이션을 통한 최적화, 규모가 큰(복잡한 상태관리 및 구조) 경우에는 Redux 적용

하지만 Redux 공부를 해야하기 때문에 다음 토이프로젝트에 Redux 적용해보는 걸로..

0개의 댓글