귀여운 눈높이에서 작성된, 🐰

하루 한 걸음씩, 성장 하는 중 입니다 🫶🏻

Studying/React

리액트 공부하기 - 전역 상태 관리 context API

creamymood 2025. 4. 24. 18:30

후.. 여행 후, 현생 복귀란 쉽지 않네요

하지만,, 다시 제 자리에서 집중 ! 


상태관리에서 createContext, Provider, useContext 이런 것들은 React에서 컴포넌트끼리 데이터를 공유하기 위해 사용하는 도구

🐰 먼저 큰 그림 (상위 개념)

상태 관리(State Management)란?

  • 컴포넌트들이 "공통된 정보"를 공유할 때 그 정보를 어디에 저장하고, 어떻게 전달하냐는 문제야.
  • 예: 로그인된 유저 정보, 언어 설정, 테마 같은 것들

상태 관리의 종류

  1. 로컬 상태 (useState) → 한 컴포넌트 안에서만 사용
  2. 전역 상태 → 여러 컴포넌트에서 공유해야 할 때 필요
    이 전역 상태를 도와주는 게 Context API야.

📦 Context API란?

전역 상태를 쉽게 관리할 수 있게 도와주는 도구 세트!

핵심 3개만 기억하면 돼:

  • createContext
  • Provider
  • useContext

🛠️ 각각 역할과 흐름

1. createContext

  • 일종의 박스 만들기야.
  • 이 박스에 데이터를 넣어두고, 어디서든 꺼내 쓸 수 있게 하려는 거야.
import { createContext } from 'react';

export const MyContext = createContext(); // 박스 하나 만든 거야

2. Provider

  • 만든 박스를 감싸는 포장지 같은 거야.
  • 자식 컴포넌트들한테 "이 박스 안에 든 걸 줄게!" 라는 역할.
<MyContext.Provider value={내가공유할값}>
  <App />   // 이 App과 그 자식들은 이제 그 "값"을 꺼내 쓸 수 있어
</MyContext.Provider>

3. useContext

  • 자식 컴포넌트에서 박스 안 데이터를 꺼내 쓰는 도구야.
import { useContext } from 'react';
import { MyContext } from './MyContextFile';

const Child = () => {
  const value = useContext(MyContext);  // 박스에서 값 꺼냄
  return <div>{value}</div>;
};

💡 실제 흐름 요약 (예시)

  1. MyContext라는 박스 만들고
  2. MyContext.Provider로 App 또는 공유가 필요한 컴포넌트들을 감싸고
  3. 그 내부의 자식 컴포넌트에서 useContext(MyContext)로 꺼내 씀

🧪 예제 코드로 한 눈에 보기

// context/UserContext.js
import { createContext } from 'react';

export const UserContext = createContext();
// App.jsx
import { UserContext } from './context/UserContext';
import Child from './Child';

function App() {
  const user = 'Jane';

  return (
    <UserContext.Provider value={user}>
      <Child />
    </UserContext.Provider>
  );
}
// Child.jsx
import { useContext } from 'react';
import { UserContext } from './context/UserContext';

const Child = () => {
  const user = useContext(UserContext);
  return <p>Hello, {user}!</p>;
};

🔁 한 줄 정리

createContext로 박스를 만들고
Provider로 감싸서 값을 나눠주고
useContext로 그 값을 자식이 꺼내서 씀!


필요하면 코드 따라 하면서 실습해보는 것도 추천해!
어떤 부분이 제일 헷갈렸는지도 알려줘~ 더 쉽게 풀어줄게!


오~ 이해 잘했네 Jane! 질문도 아주 좋아.
자, 그럼 대답해볼게:


🎯 꼭 Provider가 필요할까?

응, 거의 무조건 필요해!
왜냐면 createContext()로 박스만 만든 상태아무 정보도 들어 있지 않은 빈 박스야.
Provider는 그 박스에 실제 값을 넣는 역할을 해.


📦 박스만 만들면 생기는 일

const MyContext = createContext();

이렇게만 하면 MyContext는 **"기본값(undefined)"**만 가지고 있어.

const value = useContext(MyContext);
console.log(value); // undefined

그래서 Provider 없이 쓰면 실제로 아무런 값도 못 받아와.
React는 "어? 이 박스 안에 뭐 없는데?" 하면서 undefined만 줘.


✅ Provider는 "박스 안에 값 넣는 사람"

<MyContext.Provider value={"Jane"}>
  <Child />
</MyContext.Provider>

이렇게 해줘야 useContext(MyContext)가 "아~ Jane이란 값을 받았구나!" 하게 돼.


🥚 비유로 정리해보자

  • createContext() → 빈 도시락통만 만든 거야
  • Provider → 그 도시락에 밥이나 반찬 넣는 역할
  • useContext() → 그 도시락 꺼내 먹는 역할

💡 밥 안 넣고 도시락통만 들고 다녀봐야... 배고프지 ㅋㅋ


결론!

createContext만으론 아무 기능도 안 해!
Provider가 있어야 값이 들어가고,
자식 컴포넌트가 그 값을 쓸 수 있어.




Provider로 값을 넣을 때는 정말 거의 뭐든지 넣을 수 있어.
단! value={} 이 안에 들어가는 건 단 하나의 값만 가능해.
그게 객체든 문자열이든 함수든 배열이든 다 돼!


✅ 어떤 걸 넣을 수 있냐면:

1. 문자열

<UserContext.Provider value="Jane">

2. 숫자

<CountContext.Provider value={42}>

3. 객체 (가장 많이 씀!!)

<UserContext.Provider value={{ name: "Jane", age: 28 }}>

4. 배열

<ThemeContext.Provider value={["dark", "light"]}>

5. 함수 (상태 변경 함수 등!)

<MyContext.Provider value={() => alert("Hi!")}>

6. 복합 형태 (객체 안에 상태랑 함수 둘 다 넣기)

<MyContext.Provider value={{
  user: "Jane",
  setUser: setUser, // 상태 변경 함수
}}>

이 구조가 진짜 많이 쓰여.
예: 로그인한 유저 정보랑 로그아웃 함수 같이 전달할 때


🔄 왜 객체로 많이 쓰냐면?

여러 값을 한 번에 보내고 싶을 때 편하거든!

const value = {
  theme: "dark",
  toggleTheme: () => setTheme(prev => prev === "dark" ? "light" : "dark")
};

<ThemeContext.Provider value={value}>

그럼 자식 컴포넌트에선:

const { theme, toggleTheme } = useContext(ThemeContext);

이렇게 편하게 구조분해 해서 꺼낼 수 있어!


🚨 잠깐! 주의할 점

  • value={}에는 하나의 값만 들어간다.
  • 여러 값을 보내고 싶으면 객체로 묶어서 보내야 돼.
  • 상태(useState)랑 같이 쓰면 진짜 강력해져.