본문 바로가기
Frontend/React

[React] Context API

by 디스코비스킷 2025. 4. 21.
반응형

Context API란?

1. Context API란?

Context API는 리액트에서 컴포넌트 트리 전체에 데이터를 전달할 수 있도록 해주는 기능이다. 주로 부모 컴포넌트에서 하위 컴포넌트로 데이터를 전달하는 props의 대안으로 사용된다. Context API를 사용하면 중간에 있는 컴포넌트들을 거치지 않고도 상위에서 하위로 데이터를 전달할 수 있어, 깊은 컴포넌트 트리 구조에서 유용하다.

 

Context API의 주요 구성 요소

  • Context: 데이터를 공유하는 공간을 생성한다.
  • Provider: Context의 데이터를 제공하는 컴포넌트로, 하위 컴포넌트들이 Context에 접근할 수 있게 만든다.
  • Consumer: Context에 제공된 데이터를 사용하는 컴포넌트이다. (React 16.8부터는 useContext 훅으로 대체 가능하다.)

2. 언제 Context API를 사용하나요?

Context API는 주로 다음과 같은 상황에서 사용된다.

  1. 전역 상태 관리
    • 애플리케이션 내에서 여러 컴포넌트가 동일한 데이터를 필요로 할 때, 예를 들어, 사용자의 로그인 상태나 테마(어두운 모드/밝은 모드) 등의 상태를 여러 컴포넌트에서 공유해야 할 때 유용하다.
  2. 컴포넌트 간 데이터 전달이 복잡할 때
    • 여러 중간 컴포넌트를 거쳐서 데이터를 전달해야 하는 경우가 있다. 이때, props drilling(컴포넌트를 거쳐서 props를 전달하는 방식)이 불편하고 코드가 복잡해지기 때문에, Context API를 사용하여 데이터를 한 번에 전달할 수 있다.
  3. 상태가 자주 변경되거나 여러 곳에서 사용되는 경우
    • 앱 전체에서 여러 컴포넌트들이 동일한 상태에 의존하고 그 상태가 자주 바뀐다면, 상태를 Context API로 관리하면 더 효율적이다.
    • 예를 들어, 사용자 언어 설정, 테마 설정, 인증 상태 등.

Context API 사용을 피해야 할 경우

  • 많은 데이터를 다루지 않거나 간단한 상태 관리일 경우: 상태가 한정적이고 변경이 적은 경우, 굳이 Context API를 사용할 필요는 없다. useStateprops만으로도 충분할 수 있다.
  • 성능 이슈: Context는 값이 변경될 때마다 해당 값을 사용하는 모든 컴포넌트를 리렌더링하기 때문에, 성능 최적화가 필요할 수 있다. 이를 해결하기 위해 React.memo, useMemo 등을 사용할 수 있다.

Context API 사용 방법

Context API를 사용하기 위한 단계는 크게 세 가지로 나눌 수 있다.

  1. createContext로 전역 상태 만들기
  2. Provider로 전역 상태 연결
  3. useContext로 전역 상태 가져오기

1. createContext로 전역 상태 만들기

createContext를 사용하여 데이터를 공유할 Context를 생성한다. 이를 통해 여러 컴포넌트 간에 상태를 공유할 수 있게 된다.

import React, { createContext } from 'react';

// Context 생성: 이 Context는 전역 상태를 저장하는 역할을 한다.
const ThemeContext = createContext();

2. Provider로 전역 상태 연결

Provider는 Context에 데이터를 공급하는 역할을 한다. Provider는 그 내부에서 값을 설정하고, 하위 컴포넌트들에 그 값을 전달할 수 있게 해준다.

themeContext.jsx

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

// ThemeProvider 컴포넌트: ThemeContext.Provider로 앱의 전역 상태를 관리한다.
const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light'); // 기본 테마는 light

  const toggleTheme = () => {
    setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light'));
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

export default ThemeProvider;

위 코드에서 ThemeContext.ProviderthemetoggleTheme 함수를 전역 상태로 제공하며, 이를 value로 설정한다. childrenProvider 안에 감싸진 컴포넌트들이며, 이들 컴포넌트는 모두 ThemeContext를 통해 전역 상태에 접근할 수 있다.

App.js

import React from 'react';
import { ThemeProvider } from './ThemeContext'; // ThemeProvider import
import ThemeToggler from './ThemeToggler'; // ThemeToggler import

const App = () => {
  return (
    <ThemeProvider>
      <ThemeToggler />
    </ThemeProvider>
  );
};

export default App;

AppThemeProvider로 감싸서 ThemeContext에서 제공한 데이터를 사용할 수 있다.

3. useContext로 전역 상태 가져오기

useContext 훅을 사용하여 Context에 제공된 데이터를 컴포넌트에서 쉽게 가져올 수 있다.

ThemeToggler.jsx

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

// 테마를 변경하는 버튼을 가진 컴포넌트
const ThemeToggler = () => {
  const { theme, toggleTheme } = useContext(ThemeContext); // useContext로 전역 상태 가져오기

  return (
    <div>
      <h1>현재 테마: {theme}</h1>
      <button onClick={toggleTheme}>테마 변경</button>
    </div>
  );
};

export default ThemeToggler;

위 코드에서는 useContext(ThemeContext)를 통해 themetoggleTheme을 가져온다. 이 컴포넌트는 현재 테마를 표시하고, 버튼 클릭 시 테마를 전환하는 기능을 수행한다.

 

작동 원리

  1. ThemeProvider는 전역 상태인 themetoggleTheme를 제공한다.
  2. ThemeToggleruseContext 훅을 사용하여 이 상태를 가져와서 테마를 화면에 표시하고, 버튼 클릭 시 테마를 변경한다.
  3. AppThemeProvider로 감싸져 있어, ThemeTogglerThemeContext에서 제공한 데이터를 사용할 수 있다.

 

Context를 사용하기 전에 고려할 것

Context는 남용하기 쉽기 때문에 신중하게 사용해야 한다. 여러 레벨 깊이로 props를 전달해야 한다고 해서 무작정 정보를 context에 넣는 것이 좋은 선택이 아닐 수 있다.

  1. 먼저 Props 전달하기
    컴포넌트들 간에 여러 개의 props를 전달하는 것이 불편할 수 있지만, 이는 데이터를 사용하는 컴포넌트가 어떤 데이터를 사용하는지 명확히 해주는 좋은 방법이다. 이를 통해 데이터 흐름이 props를 통해 분명해지며, 코드의 유지보수와 관리가 용이해진다. 
  2. 컴포넌트 추출 후 JSX를 children으로 전달하기
    데이터를 사용하지 않는 중간 컴포넌트 층을 지나야 하는 경우, 데이터가 전달되는 중간 컴포넌트들에 대해 고민할 수 있다. 이때 데이터를 사용하지 않는 컴포넌트를 추출하고, children prop으로 전달하는 방법이 유효하다. 이렇게 하면 데이터가 필요한 컴포넌트와 데이터를 전달하는 컴포넌트 사이의 중간층을 줄여 더욱 간결한 구조로 만들 수 있다.
  3. Context 사용 여부 결정하기
    만약 위의 방법들이 잘 맞지 않거나, 중간에 지나치게 많은 props 전달이 필요하거나 복잡한 구조가 된다면, 그때 context를 고려해볼 수 있다. 단, context는 자주 변경되는 값이나, 여러 컴포넌트 간에 공유되어야 하는 값들을 다룰 때 유용하다.

Context 사용예시

  1. 테마 지정하기
    다크 모드와 같은 시각적 요소를 사용자에게 제공하는 애플리케이션에서는, context provider를 앱의 최상단에 두고 필요한 컴포넌트에서 해당 값을 가져와 사용할 수 있다. 이를 통해 테마 설정을 앱 전체에서 손쉽게 관리할 수 있다.
  2. 현재 계정 관리
    로그인한 사용자의 정보는 많은 컴포넌트에서 필요할 수 있다. 이때, context에 현재 계정을 저장해두면, 컴포넌트 트리 어디에서나 해당 정보를 쉽게 가져올 수 있다. 예를 들어, 댓글 작성 시 다른 사용자로 댓글을 달고 싶을 때, 각 컴포넌트가 같은 사용자 정보를 가져올 수 있게 된다. 이와 같은 상황에서는 여러 계정을 관리할 수 있는 구조가 유용하다.
  3. 라우팅 관리
    대부분의 라우팅 솔루션은 내부적으로 현재 경로를 추적하기 위해 context를 사용한다. 이 방식을 사용하면 애플리케이션 내의 링크나 버튼들이 현재 경로에 따라 활성화 여부를 판단할 수 있다. 
  4. 상태 관리
    애플리케이션이 커지면서 여러 컴포넌트가 동일한 상태를 필요로 할 때, 상태 관리가 복잡해질 수 있다. 이때, 상태를 context와 함께 관리하면, 멀리 떨어져 있는 컴포넌트들 간에 상태를 손쉽게 공유하고 변경할 수 있다. 예를 들어, reducer와 context를 결합하여 복잡한 상태를 효율적으로 관리할 수 있다.
반응형

최근댓글

최근글

© Copyright 2024 ttutta