리액트

[React] React Context API를 활용한 전역 상태 관리

코딩하는둥이 2025. 4. 14. 12:11

context

단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있습니다.

전역에서 사용할 수 있는 함수를 만들어 줍니다. 

 

Context API란?

React의 Context API는 컴포넌트 트리에서 데이터를 전역적으로 공유할 수 있도록 지원합니다. 이를 사용하면 props 드릴링(부모에서 자식으로 데이터를 전달하는 과정)을 제거하고, 애플리케이션의 상태를 효율적으로 관리할 수 있습니다.

 

React.createContext

const MyContext = React.createContext(defaultValue);
//defaultValue: Context를 구독하는 컴포넌트가 트리 상에서 적절한 Provider를 찾지 못했을 때 사용되는 기본값입니다.

 

createContext는 React에서 Context 객체를 생성하는 함수입니다. 이 객체는 컴포넌트 트리에서 데이터를 전역적으로 관리하고 공유할 수 있게 합니다.


Context.Provider

<MyContext.Provider value={/* 하위 컴포넌트로 전달할 데이터입니다. */}>

 

Context의 값을 하위 컴포넌트들에게 전달하고 하위 컴포넌트들은 이 값을 구독하여 사용할 수 있습니다

 * context를 구족하는 모든 컴포넌트는 Provider의 value prop가 바뀔 때마다 다시 랜더링됩니다.

 

 

사용자 정보를 전역적으로 관리하는 코드를 구현하겠습니다.

 

UserStore 컴포넌트 생성
UserStore는 사용자 정보를 전역적으로 관리하며, 모든 자식 컴포넌트에서 접근 가능한 컨텍스트를 제공합니다.

import React,{createContext, useState} from "react"; 

export const UserContext = createContext();

export default function UserStore(props) {
  const [job, setJob] = useState("FE-developer")

  const user = {
    name:"seojiho",
    job:"FE-developer",
    changeJob:(updateJob) => setJob(updateJob),

  };

  return <UserContext.Provider value={user}>{props.children}</UserContext.Provider>
}

 

App 컴포넌트에서 Provider 사용

UserStore를 최상위 컴포넌트로 감싸서 전역적으로 Context를 사용할 수 있게 합니다

import { BrowserRouter, Routes, Route } from "react-router-dom";
import MainPage from "./components/MainPage";
import TechPage from "./components/TechPage";
import BlogPage from "./components/BlogPage";
import JavascriptPage from "./components/JavascriptPage";
import ReactPage from "./components/ReactPage";
import ReactDocPage from "./components/ReactDocPage";
import UserStore from "../../store/user";

function App() {
  return (
    <UserStore>
      <BrowserRouter>
        <Routes>
          <Route path={"/"} element={<MainPage />} />
          <Route path={"tech"} element={<TechPage />}>
            <Route path="javascript" element={<JavascriptPage />} />
            <Route path="react" element={<ReactPage />} />
            <Route path="react/:docId" element={<ReactDocPage />} />
          </Route>
          <Route path={"blog"} element={<BlogPage />} />
        </Routes>
      </BrowserRouter>
    </UserStore>
  );
}

export default App;

 

Consumer에서 데이터 사용

useContext 훅을 사용하여 Context 데이터를 간편하게 가져옵니다

import React,{useContext} from "react";
import { UserContext } from "../../../store/user";

export default function BlogPage() {
  const value = useContext(UserContext);

  return (
    <div>
      <h1>{value}</h1>
    </div>
  );
}

 

장점

 Props 드릴링 제거로 코드 간결화됩니다.

 전역 상태 관리가 쉬워집니다.

 React 내장 기능으로 추가 라이브러리 불필요합니다.

 

주의사항

 값 변경 시 하위 컴포넌트가 불필요하게 리렌더링될 수 있습니다.

 복잡한 애플리케이션에서는 Redux와 같은 상태 관리 라이브러리가 더 적합할 수 있습니다.

 이와 같이 Context API를 활용하면 사용자 정보를 포함한 다양한 데이터를 효율적으로 관리할 수 있습니다.

 

 

useReducer와 Context API로 상태 관리하기

React에서 상태 관리를 할 때 가장 많이 사용하는 훅은 useState입니다. 하지만 컴포넌트의 상태 관리가 복잡해지거나 여러 컴포넌트에서 동일한 상태를 공유해야 하는 경우, useReducer와 Context API를 함께 사용하는 것이 더 적합할 수 있습니다

 

 

useReducer란?

 React에서 제공하는 훅으로, useState의 대체재로 사용됩니다. 상태와 이를 업데이트하는 로직을 컴포넌트 외부로 분리하여 더 깔끔하고 유지보수하기 쉬운 코드를 작성할 수 있습니다.

const [state, dispatch] = useReducer(reducer, initialState);

reducer: (state, action) => newState 형태의 함수로, 현재 상태와 액션을 받아서 새로운 상태를 반환합니다. 

initialState: 초기 상태 값입니다. 

dispatch: 액션을 발생시키는 함수입니다.

 

 

1) Context 생성 및 Provider 구현

전역 상태를 관리할 Context를 생성하고, 이를 제공하는 Provider 컴포넌트를 구현합니다.

import React, { createContext, useReducer } from "react"; 

// 1. Context 생성
export const UserContext = createContext();

// 2. 초기 상태 정의
const initialUser = {
    name: "seojiho",
    job: "FE-developer",
};

// 3. Reducer 함수 정의
const userReducer = (state, action) => {
    switch (action.type) {
        case "CHANGE_JOB":
            return { ...state, job: action.payload };
        default:
            return state;
    }
};

// 4. Provider 컴포넌트 구현
export default function UserStore(props) {
    const [user, dispatch] = useReducer(userReducer, initialUser);

    return (
        <UserContext.Provider value={{ user, dispatch }}>
            {props.children}
        </UserContext.Provider>
    );
}

 

 

2) Context 소비하기 (Consumer)

이제 Context를 사용하는 컴포넌트를 만들어봅니다. 이 컴포넌트에서는 useContext 훅을 사용하여 전역 상태와 dispatch를 가져옵니다.

import React, { useContext } from "react";
import { UserContext } from "../../../store/user";

export default function BlogPage() {
    // Context에서 user와 dispatch 가져오기
    const { user, dispatch } = useContext(UserContext);

    return (
        <div>
            <h1>현재 직업: {user.job}</h1>
            <button 
                onClick={() => dispatch({ type: "CHANGE_JOB", payload: "BE-developer" })}
            >
                직업 변경
            </button>
        </div>
    );
}

 

=> 초기화면에는 현재 직업: FE-developer가 표시되고 버튼을 클릭하면 BE-developer로 변경되며 변경된 직업 정보가 화면에 반영합니다.