목차
1. Context란
2. Context 사용 방법
3. 사용시 주의 사항
4. Context 사용이 적합한 경우
5. Context 사용 방법(번외)
Context란
컴포넌트간의 데이터를 전달하는 방법으로, 전역적인 값 관리가 가능한 방법입니다.
중간 컴포넌트를 거쳐서 하위 컴포넌트에 props를 전달하지 않고 필요한 컴포넌트에게 전달할 수 있는 방법이라 props 전달 방식의 단점인 props drilling을 해결할 수 있습니다.
props drilling
상위 컴포넌트에서 하위 컴포넌트로 props를 전달하려고 할때 props가 필요없는 중간 컴포넌트를 통해 데이터를 연달아 전달해야하는 현상.
또한 Context는 일종의 데이터 보관소 역할을 합니다.

Context 사용 방법
(1) Context 생성
import {createContext} from "react";
const UserContext = creatContext(null);
데이터를 하위 컴포넌트에 전달하는 것이 주 목적이기 때문에 컴포넌트 바깥에 생성합니다.
=> 렌더링 될 때마다 다시 생성될 필요 없음.
(2) Provider로 값 공급
function App() {
const user = {name = "Faker", age : 28};
return (
<UserContext.Provider value={user}>
<Champions/>
</UserContext.Provider>
)
}
contextProvider가 감싸는 모든 하위 컴포넌트는 props를 사용하지 않아도 value 속성으로 값을 전달할 수 있습니다.
(3) useContext로 값 읽기
function Champions() {
const user = useContext(UserContext);
return <div>{user.name}</div>
}
useContext(Context.Provider에서 내려온 값을 읽는 훅)은 읽기 전용이기 때문에 값을 변경하려면 Provider쪽의 state를 관리해야합니다.
Provider가 상위에 없는 경우 createContext의 기본값을 반환합니다. (1번에서 정의한 null)
추가 사용 예시
//App.jsx (최상위 컴포넌트)
import { useState, useRef, useReducer, useCallback, createContext } from "react";
...
export const TodoContext = createContext();
function App() {
...
return (
<>
<div className="App">
<Header />
<TodoContext.Provider
value={{//전달할 값
todos, onCreate, onUpdate, onDelete,
}}
>
<Editor />
<List />
</TodoContext.Provider>
</div>
</>
);
}
export default App;
//하위 컴포넌트 - Editor.jsx
import { useState, useRef, useContext } from "react";
import { TodoContext } from "../App";
//상위 컴포넌트에서 만든 TodoContext import
const Editor = () => {
const { onCreate } = useContext(TodoContext);
//onCreate만 사용함 구조분해할당
...
return (
...
);
};
export default Editor;
//하위 컴포넌트 - List.jsx
import { useState, useMemo, useContext } from "react";
import { TodoContext } from "../App";
const List = () => {
const { todos } = useContext(TodoContext);
...
return (
<div className="List">
...
<div className="todos_wrapper">
{filteredTodos.map((todo) => {
return <TodoItem key={todo.id} {...todo} />;
//props로 넘겨주던 것들 삭제
})}
</div>
</div>
);
};
export default List;
//하위 컴포넌트 - TodoItem.jsx
import { memo, useContext } from "react";
import { TodoContext } from "../App";
const TodoItem = ({ id, isDone, content, date }) => {
const { onUpdate, onDelete } = useContext(TodoContext);
...
return (
...
);
};
export default memo(TodoItem);

사용시 주의 사항
- context 사용시 컴포넌트의 재사용이 어려울 수 있습니다.
- 단순히 props drilling을 피하기 위함이라면 Component Composition(컴포넌트 합성)을 권장합니다.
- context의 value가 변경되면 contextProvider 하위 모든 컴포넌트가 리렌더링 됩니다.
- Provider가 중첩된다면 추적이 어려워집니다.
- 필터링 상태, 검색어, input값 등과 같이 자주 바뀌는 값은 context 사용을 지양합니다.
주의 사항 중 context 사용시 컴포넌트의 재사용이 어려울 수 있다는 부분이 바로 이해가 되지 않아서 약간의 예시를 들어보겠습니다.
UserProfile이라는 컴포넌트는 useHeader라는 context에 있는 로그아웃 처리를 사용한다고 가정하겠습니다.
// UserProfile.jsx
import React from 'react';
import { useHeader } from '@/utils/headerUtils'; // Context에 종속됨
function UserProfile() {
const { setHeader } = useHeader();
useEffect(() => {
// 이 컴포넌트가 마운트될 때, 헤더 설정을 Context에 의존하여 변경합니다.
setHeader({
title: "내 프로필",
isLogoutBtn: true,
onLogout: () => { console.log("로그아웃 처리..."); }
});
return () => {
// 언마운트 시 헤더를 기본 상태로 되돌립니다.
setHeader({});
};
}, [setHeader]);
return <div>사용자 프로필 상세 정보</div>;
}
export default UserProfile;
문제점
- UserProfile 컴포넌트는 useHeader라는 context에 종속 되어있기 때문에 해당 context를 제공하지 않는 레벨에서는 사용할 수 없습니다.
- 이는 특정 context에 종속되어 context가 제공되지 않는 곳에서는 컴포넌트를 재사용할 수 없다는 문제점을 있습니다.
해결방법
- 재사용이 중요한 범용적인 UI컴포넌트 (버튼, 입력 필드 등)에는 context를 피하고 props를 사용하는 것이 좋습니다.
- 단순 props drilling을 피하기 위함이라면 Component Composition을 권장합니다.
Context 사용이 적합한 경우
context는 애플리케이션의 핵심 데이터, 테마 같이 전역적으로 필수적인, 자주 변하지 않는 전역값에 적합합니다.
- 로그인한 사용자 정보
- 테마 정보(light / dark)
- 언어 설정
- 글로벌 config (전역 환경 설정)
- 인증 토큰
Context 사용 방법(번외)
import { ModalProvider } from "@/utils/modalUtils";
import { HeaderProvider } from "@/utils/headerUtils";
export default function CommonProvider({children}) {
return (
<ModalProvider>
<HeaderProvider>{children}</HeaderProvider>
</ModalProvider>
)
}
import React, { createContext, useState, useContext, useEffect } from "react";
const HeaderContext = createContext();
export const HeaderProvider({children}) => {
const [headerState, setHeaderState] = useState({
title: "",
onLogout = () => {},
isLogoutBtn: false,
onSearch = () => {},
isSearchBtn: false,
isSettingBtn: false,
onSetting = () => {}
})
const setHeader = ({
title = "",
onLogoutBtn = () => {},
isLogoutBtn = false,
onSearch = () => {},
isSearchBtn = false,
onSetting = () => {},
isSettingBtn = false
}) => {
setHeaderState({
title,
onLogoutBtn,
isLogoutBtn,
onSearch,
isSearchBtn,
onSetting,
isSettingBtn
})
}
const value = { headerState, setHeader };
return <HeaderContext.Provider value={value}>{children}</HeaderContext.Provider>;
}
import CommonProvider from "@/utils/CommonProvider";
function App() {
return (
<>
<CommonProvider>
<Router>
<RootRoutes/>
</Router>
<ModalAlert/>
</CommonProvider>
</>
)
}
function MainComponent() {
const {setHeader} = useHeader(); //context에 정의된 header정보 관리 함수 호출
useEffect(() => {
setHeader({
isLogoutBtn: true,
onLogout: () => {
openAlert({
messag: "로그아웃 하시겠습니까?",
isCancelBtn: true,
onConfirm: () => {
logout();
}
})
}
})
},[])
}
사용법 요약
- Context의 데이터를 전달해주는 Provider를 컴포넌트화 해서 App.js에서 간략하게 표현할 수 있습니다.
- HeaderProvider 컴포넌트가 받는 {children}은 HeaderProvider가 받는 하위 컴포넌트를 의미합니다.
- CommonProvider에 HeaderContext를 전달하는 HeaderProvider를 하위에 정의했기 때문에, App.js에서 CommonProvider 하위의 모든 컴포넌트는 HeaderProvider에서 제공하는 header 정보를 사용할 수 있습니다.
- 하위 컴포넌트인 MainComponent는 context에 저장된 header정보를 제어할 수 있게 됩니다.
참고
https://ko.legacy.reactjs.org/docs/context.html
Context – React
A JavaScript library for building user interfaces
ko.legacy.reactjs.org
'cs > react' 카테고리의 다른 글
| [React] Custom Hook (0) | 2025.12.02 |
|---|---|
| [React] Redux Toolkit (0) | 2025.12.01 |
| [React] 컴포넌트 생명주기 (0) | 2025.11.28 |
| [React] 리액트 훅 (0) | 2025.11.27 |
| [React] 가상 DOM과 재조정 (0) | 2025.11.24 |