React에서 여러 컴포넌트가 동일한 데이터를 공유하고 조작해야 할 경우, props를 깊게 전달하는 방식은 유지보수가 어렵고 구조가 복잡해지기 쉽다. 이럴 때 useContext를 사용하면, 전역적으로 데이터를 관리할 수 있어 코드가 훨씬 깔끔해진다. 아래에서는 useContext 적용 전후의 차이점을 코드와 함께 비교해 보자.
<List todos={todos} onUpdate={onUpdate} onDelete={onDelete} />
<Editor onCreate={onCreate} />
TodoItem에서도 마찬가지로 onUpdate, onDelete를 계속 전달받는다.
<TodoItem {...todo} onUpdate={onUpdate} onDelete={onDelete} />
<TodoStateContext.Provider value={todos}>
<TodoDispatchContext.Provider value={memoizedDispatch}>
<Editor />
<List />
</TodoDispatchContext.Provider>
</TodoStateContext.Provider>
const todos = useContext(TodoStateContext);
const { onUpdate, onDelete } = useContext(TodoDispatchContext);
const TodoItem = ({ id, isDone, content, date, onUpdate, onDelete }) => {
const onChangeCheckbox = () => onUpdate(id);
const onClickDeleteButton = () => onDelete(id);
return (...);
};
const { onUpdate, onDelete } = useContext(TodoDispatchContext);
const TodoItem = ({ id, isDone, content, date }) => {
const onChangeCheckbox = () => onUpdate(id);
const onClickDeleteButton = () => onDelete(id);
return (...);
};
❗ 단, 모든 상태에 무작정 useContext를 적용하는 것은 오히려 성능 저하나 예측 가능성 저하를 불러올 수 있음. 상태가 자주 바뀌고, 컴포넌트 간 결합이 강한 경우는 오히려 props나 Redux, Zustand 같은 별도 상태관리 툴이 더 적합할 수 있다.
// context.js
export const UserContext = createContext(null);
// App.jsx
<UserContext.Provider value={{ name: "Han" }}>
<Profile />
</UserContext.Provider>
// Profile.jsx
const user = useContext(UserContext);
return <p>환영합니다, {user.name}님</p>;
useContext는 props 전달의 번거로움을 줄이고, 전역 데이터를 효율적으로 관리할 수 있게 해준다. 구조가 단순해지고 가독성이 좋아지며, 특히 상태 변경 로직까지 함께 전달하면 비즈니스 로직이 컴포넌트로부터 분리되어 테스트와 유지보수가 쉬워진다.
적절한 시점에 useContext를 도입하면, React 앱의 구조를 한층 더 깔끔하게 개선할 수 있다.
React - useCallback을 활용한 함수 최적화 전략 (0) | 2025.06.07 |
---|---|
React - useMemo를 사용한 코드 vs 사용하지 않은 코드 비교 (0) | 2025.06.07 |
React - useState를 useReducer로 대체하는 간단 예제 (0) | 2025.06.05 |
React - props 전달 방식의 차이: `{...todo}` vs `todo={todo}` (0) | 2025.06.05 |
React - useEffect를 이용한 컴포넌트 라이프사이클 제어 정리 (1) | 2025.06.05 |