ContextAPI는 React 웹 애플리케이션 개발 시 컴포넌트 트리 내부에서 데이터들을 전역적으로 공유할 수 있는 방법을 제공하는 방법입니다.
props를 단계별로 전달하는 Props Drilling을 해결하기 위해 사용됩니다.Context를 통해, 중간에 있는 여러 컴포넌트를 거치지 않고도, 컴포넌트 트리 깊은 곳에 있는 컴포넌트에 데이터를 전달할 수 있게 됩니다.전역 상태관리 라이브러리 Redux,Zustand등과 같이 store 내부에 상태나 데이터를 정의하고, Props Drilling 없이 전역적으로 상태를 참조하고, 사용할 수 있다는 관점에선 동일한 역할을 지닙니다.
Context API를 사용할때, 해당 컨텍스트를 구독하는 모든 컴포넌트들은 상태변화와 상관없이 모두 리렌더링이 발생합니다.
이를 증명하기 위해 Context API로 간단한 유저상태를 구현하겠습니다.
먼저 UserContext라는 파일을 생성한후, 해당 Context를 전역적으로 공급하기 위한 간단한 코드를 작성했습니다.
users의 초기상태를 나타내는 initalUsersProfile와, users의 상태를 변경하는 함수인 setUser를 내보냈습니다.
/* 📑 UserContext.jsx */
import {createContext, useState} from "react";
/* Context 기본값 설정 */
const initalUsersProfile = {
name: "Seju",
posts: [
"Context API가 상태관리 라이브러리의 대안이 될 수 없는 이유",
"Babel 왜쓰고 왜 사용할까?",
],
};
export const UserContext = createContext({
user: initalUsersProfile,
setUser: () => {},
});
/* Provider로 전역적으로 상태를 공급. */
const UserProvider = ({children}) => {
const [user, setUser] = useState(initalUsersProfile);
return (
<UserContext.Provider value={{user, setUser}}>
{children}
</UserContext.Provider>
);
};
export default UserProvider;
Main.jsx에서 구성한 UseProvider 함수를 공급합니다.context를 사용하는 <UserProfile>컴포넌트와 context와는 연관이 없는, 정적인 JSX를 가지고 있는 <UserPosts> 컴포넌트를 생성했습니다.
main.jsx
Context를 사용하는 UserProfile 컴포넌트
/* 📑 UserProfile.jsx */
import {useContext} from "react";
import {UserContext} from "../context/UserContext";
function UserProfile() {
const {user} = useContext(UserContext);
console.log("UserProfile 컴포넌트 리렌더링 발생");
return (
<>
<div>{user.name}</div>
</>
);
}
export default UserProfile;
Context와 연관이 없는 UserPost 컴포넌트
/* 📑 UserPosts.jsx */
function UserPosts() {
console.log("UserPost 컴포넌트 리렌더링 발생");
return (
<>
<div>Some Static Content</div>
</>
);
}
export default UserPosts;
해당 컴포넌트 두개를 전부 렌더링하고 있는 App.jsx
App.jsx에서 유저상태를 변경하는 setUser 함수를 가져오고,/* 📑 App.jsx */
function App() {
const {setUser} = useContext(UserContext);
const handleChangeUserName = () => {
setUser((prevUser) => ({
...prevUser,
name: "suwan",
}));
};
return (
<>
<UserProfile />
<UserPosts />
<button onClick={handleChangeUserName}>이름변경</button>
</>
);
}
export default App;
이제 버튼 클릭시 어떤 user의 상태가 변경되어 리렌더링이 발생하게 됩니다. 어떤 컴포넌트들이 리렌더링이 발생할까요?

Context와는 전혀 상관없는 정적인 컴포넌트인 UserPosts 컴포넌트에서도 리렌더링이 발생하고 있습니다.Context를 구독여부에 상관없이 Provider로 래핑된 컴포넌트는 상태가 변화될 때 모두 리렌더링이 발생함을 의미합니다.이는 1번째 문제와 연관이 있습니다.
이에 반해 전역상태관리 라이브러리는?
store에 저장하고, 컴포넌트는 스토어의 특정부분을 구독할 수 있도록 설계되었습니다.
https://github.com/facebook/react/issues/14110 에서 리액트 팀원이였던 Sebastian Markbåge가 작성한 댓글을 발췌 했습니다.
해당 댓글은 React의 Context API에 대한 사용 사례와 한계를 설명하고 있습니다. 해당 내용에 핵심부분을 번역하면,
Context API는 변경사항이 드물게 발생하는 경우에 적합하다고 언급하고 있습니다.결론을 요약하자면 Context API는 특정 유형(값이 자주바뀌지 않는 정적인 유형)의 상태관리에서는 선택적으로 사용될 수 있지만, 복잡한 상태관리 요구사항을 가진 애플리케이션은 다른 상태관리 솔루션을 고려해야한다는 점을 설명하고 있습니다.