[React] 33. Context 분리

서회정's avatar
Mar 09, 2026
[React] 33. Context 분리

 
이번 단계에서는 context를 추가하여 상태 관리를 했을 때
최적화가 풀리는 문제 해결해보자.
 

⚠️ 최적화가 풀리는 원인

 
프로바이더 컴포넌트도 엄연히 리액트 컴포넌트이다.
 
그래서 todos 값이 변경되면 해당하는 컴포넌트도
리렌더링되는데, 그 과정에서 프로바이더에게 전달하는
value 안의 객체가 다시 만들어지기 때문이다.
 
notion image
 
notion image
 
그렇다면 이 문제는 어떻게 해결할 수 있을까?
 
TodoContext를 두 개로 분리하여 해결 할 수 있다.
 
notion image
 
state로 값이 변경되는 요소와 호출만 되어
따로 값이 변경되지 않는 함수는 분리해주는 것이다.
 
notion image
 

1. 분리된 Context 만들기

 
기존에 만들어 둔 컨텍스트를 삭제하고
값이 변하는 컨텍스트와 변하지 않는 컨텍스트 두 개로 나누어
각각의 컨텍스트를 새로 만들어주자.
 
// export const TodoContext = createContext(); export const TodoStateContext = createContext(); export const TodoDispatchContext = createContext();
 
그리고 상위에 TodoStateContext.Provider컴포넌트로 감싸고
전달해줄 데이터인 todosvalue값으로 넣어주자.
 
하나의 값만 존재하기 때문에 객체가 아닌 일반변수로 넣어주자.
 
그리고 TodoDispatchContext.Provider에는 value값으로
아까와 같은 객체 형태에서 todos만 뺀 나머지 값들을
넣을 수 있다.
 
<div className="App"> <Header /> <TodoStateContext.Provider value={todos}> <TodoDispatchContext.Provider value={{onCreate, onUpdate, onDelete}}> <Editor /> <List /> </TodoDispatchContext.Provider> </TodoStateContext.Provider> </div>;
 
하지만 이렇게만 하면 상위에 있는 todos 값이 변경되며
어짜피 {onCreate, onUpdate, onDelete} 이 객체 자체가
다시 만들어지는 문제는 해결되지 않는다.
 

2. 변경되지 않는 함수 메모이제이션하기

 
따라서 우리는 이 객체를 메모이제이션 기법으로 재생성되지
않게 변경해줄 것이다.
 
useMemo훅을 추가하고 memoizedDispatchuseMemo
호출하여 첫 번째 인수로 콜백 함수 내에 재생성되지 않고자 하는
객체를 그대로 반환하게 넣어주자.
 
그리고 두 번째 인수인 deps자리에 빈 배열을 두어 이 객체가
마운트 될 때만 렌더링 되도록 만들어주자.
 
const memoizedDispatch = useMemo(() => { return { onCreate, onUpdate, onDelete }; }, []);
 
다음으로 메모이제이션된 이 객체를 그대로
프로바이더 컴포넌트의 value에 넣어주자.
 
<TodoDispatchContext.Provider value={memoizedDispatch}> <Editor /> <List /> </TodoDispatchContext.Provider>;
 

3. 변경된 프로바이더 이름으로 공급받기

 
이제는 각각의 컴포넌트에서 변경된 이름의 컨텍스트로
필요한 값을 꺼내주도록 하자.
 
먼저 Editor컴포넌트에서는 다음과 같이 이름이 변경될 것이다.
 
const { onCreate } = useContext(TodoDispatchContext);
 
마찬가지로 TodoITem컴포넌트에서도 변경된 컨텍스트의
이름으로 값을 공급받자.
 
const { onUpdate, onDelete } = useContext(TodoDispatchContext);
 
List컴포넌트에서는 객체 형태로 넘기지 않았기 때문에
더 이상 구조분해할당으로 값을 받지 않고 일반 변수인
todos로 값을 받아주자.
 
const todos = useContext(TodoStateContext);
 
 
Share article

clubnerdy