1. State와 Dispatch


Context는 역할에 따라 크게 두 가지로 구분할 수 있습니다.

<aside>

  1. state: 애플리케이션에서 관리되는 데이터나 UI의 상태
  2. dispatch: 상태를 변경하거나 특정 동작을 수행하는 함수 </aside>

어떤 컨텍스트의 Provider로 제공된 값 중 하나가 변경될 경우, 해당 컨텍스트를 구독한 모든 컴포넌트에서 리렌더링이 발생합니다. 위에서 state는 상태를 담당해 자주 리렌더링이 발생하는 반면, dispatch는 함수 참조값으로써 리렌더링이 거의 발생하지 않습니다. 하지만 statedispatch를 하나의 Provider로 제공할 경우, state가 변경되었을 때 dispatch만 사용하는 모든 컴포넌트에서도 리렌더링이 발생합니다. 따라서 statedispatch를 서로 다른 Provider로 제공해 구독을 분리하면 불필요한 리렌더링을 방지할 수 있습니다.

2. 컨텍스트 기본 구조


위 설명에 따라 statedispatch를 분리해 제공합니다.

type StateType: { state: string };
type UpdateType: (newState: StateType) => void;

type StateContextType = StateType | null;
type DispatchContextType = { update: UpdateType; };

// Context
const StateContext = createContext<StateContextType>(null);
const DispatchContext = createContext<DispatchContextType>({ update: () => {} });

// Provider
function ContextProvider({ children }: { children: ReactNode }) {
  const [state, setState] = useState<StateContextType>(null);

  const update: UpdateType = (newState) => {
    setState(newState);
  };

  const dispatch: DispatchContextType = { update };

  return (
    <StateContext.Provider value={state}>
      <DispatchContext.Provider value={dispatch}>
	      {children}
      </DispatchContext.Provider>
    </StateContext.Provider>
  );
}

이처럼 statedispatch를 분리하면 다음과 같은 장점이 있습니다.

<aside>

  1. 리렌더링 최소화
  2. 관심사 분리
  3. 유지보수 및 테스트 용이성 </aside>

필요에 따라 추가적으로 구독을 분리할 수 있습니다. 하지만 너무 세세하게 분리할 경우 코드 복잡성과 초기 설정 비용이 발생할 수 있으므로 적절한 수준에서 분리하는 것이 중요합니다.