React Hook - useContext

김소희·2025년 11월 1일

useContext

리액트 앱은 여러 컴포넌트가 트리 계층 구조로 이루어져 있으며
부모 컴포넌트가 자식 컴포넌트에게 데이터를 전달할 때는 props를 사용한다.

하지만 컴포넌트가 많아지고 계층이 깊어지면
최상위 state 1개를 최하위까지 전해주기 위해
사용하지도 않는 중간 컴포넌트들까지 props를 계속 만들어서 전달해야 한다.

이런 상황이 Prop Drilling(프롭 드릴링) 문제다.


Context API

Context API를 사용하면
전역적으로 다뤄야 하는 데이터를 여러 컴포넌트끼리 쉽게 공유할 수 있다.

최상위 App 컴포넌트가
“이 데이터 필요하면 가져가~” 하고 방송하면
필요한 컴포넌트가 바로 가져다 쓸 수 있다.

대표적인 전역 데이터 예시는 아래와 같다.

  • 앱 언어 (한국어/영어)
  • 전체 테마 (Dark / Light)
  • 로그인 정보

그럼 props는 필요 없어질까?
정답은 아니다.

React 공식문서에서는
단순히 Prop Drilling만 피하려는 목적이라면
Component Composition(컴포넌트 합성) 을 먼저 고려하라고 한다.
Context 사용이 많아지면 재사용성이 떨어질 수 있기 때문이다.

Component Composition 이란?
부모가 자식에게 특정 모양/구성을 미리 조립해서 넘겨주는 방식.
즉, “설계로 문제를 해결”하려는 접근이다.
context는 마지막 선택지에 가깝다.


Prop Drilling 예제

App.jsx

import { useState } from 'react';
import './App.css';
import Page from './components/Page';

function App() {
  const [isDark, setIsDark] = useState(false);

  return <Page isDark={isDark} setIsDark={setIsDark} />;
}

export default App;

Page.jsx

import React from 'react';
import Content from './Content';
import Footer from './Footer';
import Header from './Header';

const Page = ({ isDark, setIsDark }) => {
  return (
    <div className="page">
      <Header isDark={isDark} />
      <Content isDark={isDark} />
      <Footer isDark={isDark} setIsDark={setIsDark} />
    </div>
  );
};

export default Page;

Header.jsx

import React from 'react';

const Header = ({ isDark }) => {
  return (
    <header
      className="header"
      style={{
        backgroundColor: isDark ? 'black' : 'lightgray',
        color: isDark ? 'white' : 'black',
      }}
    >
      <h1>Welcome 홍길동!</h1>
    </header>
  );
};

export default Header;

Content.jsx

import React from 'react';

const Content = ({ isDark }) => {
  return (
    <div
      className="content"
      style={{
        backgroundColor: isDark ? 'black' : 'white',
        color: isDark ? 'white' : 'black',
      }}
    >
      <p>홍길동님, 좋은 하루 되세요!</p>
    </div>
  );
};

export default Content;

Footer.jsx

import React from 'react';

const Footer = ({ isDark, setIsDark }) => {
  const toggleTheme = () => {
    setIsDark(!isDark);
  };

  return (
    <footer
      className="footer"
      style={{
        backgroundColor: isDark ? 'black' : 'lightgray',
      }}
    >
      <button className="button" onClick={toggleTheme}>
        Dark Mode
      </button>
    </footer>
  );
};

export default Footer;

useContext 적용 리팩터링

ThemeContext.js

import { createContext } from 'react';

export const ThemeContext = createContext(null);

기본값이 null인데,
만약 value가 없다면 이 초기값이 들어간다.


App.jsx

import { useState } from 'react';
import './App.css';
import Page from './components/Page';
import { ThemeContext } from './ThemeContext';

function App() {
  const [isDark, setIsDark] = useState(false);

  return (
    <ThemeContext.Provider value={{ isDark, setIsDark }}>
      <Page />
    </ThemeContext.Provider>
  );
}

export default App;

App이 ThemeContext.Provider로 감싸면서
하위 컴포넌트는 props를 거치지 않아도
isDark / setIsDark 에 접근할 수 있게 되었다.


Page.jsx

import React from 'react';
import Content from './Content';
import Footer from './Footer';
import Header from './Header';

const Page = () => {
  return (
    <div className="page">
      <Header />  // 더 이상 props 전달이 필요 없음
      <Content />
      <Footer />
    </div>
  );
};

export default Page;

Header.jsx

import React, { useContext } from 'react';
import { ThemeContext } from '../ThemeContext';

const Header = () => {
  const { isDark } = useContext(ThemeContext);

  return (
    <header
      className="header"
      style={{
        backgroundColor: isDark ? 'black' : 'lightgray',
        color: isDark ? 'white' : 'black',
      }}
    >
      <h1>Welcome 홍길동!</h1>
    </header>
  );
};

export default Header;

Content.jsx / Footer.jsx 도 같은 방식으로 useContext를 적용한다.


결론

  • Prop drilling 문제는 context를 사용하면 해결할 수 있다.
  • 중간 컴포넌트가 “단순 전달자 역할”을 하지 않아도 된다.
  • 하지만 Context가 많아지면 컴포넌트 재사용성이 떨어질 수 있다.

Context는 global state store 전용 도구는 아니다.
그래서 Redux / Recoil / Zustand 같은 상태관리 라이브러리가 존재한다.


참고자료

별코딩 - 유튜브 강의
용뇽 개발 노트 - 가상돔
공식문서
벨로퍼트 - 모던 리액트

profile
개발자 소희의 노트

0개의 댓글