개발 블로그

React - Context API 설명과 예시 코드, 그림 설명 본문

React

React - Context API 설명과 예시 코드, 그림 설명

daehwan2 2024. 1. 15. 00:08

벌써 프론트엔드 개발 2년차인데 이 회사를 들어오고 나서 단 한번도 Context API 를 사용한 적이 없다. 기존 프로젝트가 redux 로 상태관리를 하였었고, 이후에 react-query 와 jotai 라이브러리로 상태 데이터를 관리하는 것으로 리팩토링을 진행하였기 때문이다.

 

 이러던 중 문득, 다른 많은 UI 라이브러리들이 Context API 로 구성되어 있는 것을 발견하였고 Context API 공부의 필요성을 느껴 따로 공부하여 정리하여 본다.

 

Context API 란?

Context API 란 React 에서 제공하는 상태 관리 API 이다.

 

먼저 기존 리액트의 구조를 살펴보겠다.

리액트의 트리구조와 Props Drilling

리액트는 컴포넌트가 다음과 같이 트리구조로 구성되어 있다.

때문에, 컴포넌트 간의 데이터를 교환 할때는 props 를 이용하여서 데이터를 교환하게 된다. props 는 연결되어 있는 부모 컴포넌트에서 자식 컴포넌트로 데이터를 주는 것을 말한다.

위 그림에서 App 컴포넌트에서 맨 아래 Child 컴포넌트로 데이터를 주기 위해서는 필수적으로 Parent 컴포넌트를 한번 통해야만 한다.

그렇게 되면 Parent 컴포넌트에서 쓰이지 않는 데이터임에도 불구하고 불필요하게 데이터를 이동시키는 상황이 발생하게 된다. 그리고 트리의 깊이가 깊어지게 되면 props 의 이동이 어마어마하게 많이 생기게 된다. 이것을 props drilling 이라고 부른다

 

props drilling 을 해결할 수 있는 리액트에서 제공하는 상태 관리 API 가 Context API 이다.

 

 

적용하는 과정을 보면 다음과 같다.

 

1. Context 를 생성한다.

2. Context.Provider 컴포넌트로 데이터를 사용할 컴포넌트를 감싸준다. ( 이 때 사용할 데이터를 value 속성으로 넘겨준다. )

3. 이렇게 해주면 데이터가 감싸진 컴포넌트에서는 Context 안에 들어있는 data 에 한번에 접근할 수 있게 된다.

즉 컴포넌트간 공통적으로 사용할 데이터를 꼭 props 로 이동안시켜도 된다는 것이다.

 

이렇게 글만 봐서는 당연히 이해가 어렵다.

 

간단한 예시 코드와 트리 구조에서 어떻게 Context API 가 동작하는지 아래에서 보겠다.

import React, { createContext, useContext, useState } from "react";
import "./App.css";

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

const MyProvider = ({ children }) => {
  const [count, setCount] = useState(0);

  const increase = () => {
    setCount((prev) => prev + 1);
  };

  const decrease = () => {
    setCount((prev) => prev - 1);
  };

  // 2. Context.Provider 로 감싸기 ( 이때 value props 로 사용할 데이터 넘기기 )
  return (
    <MyContext.Provider value={{ count, increase, decrease }}>
      {children}
    </MyContext.Provider>
  );
};

const MyComponent = ({ children }) => {
  // 3. Context.Provider 의 value 로 넘긴 데이터를 useContext 훅을 사용하여 바로 꺼내기
  const { count, increase, decrease } = useContext(MyContext);

  return (
    <>
      <div>
        <p>COUNT: {count}</p>
        <button onClick={increase}>+</button>
        <button onClick={decrease}>-</button>
      </div>
      {children}
    </>
  );
};

const App = () => {
  return (
    <div style={{ padding: "20px" }}>
      <div className="context-provider">
        <MyProvider>
          <MyComponent>
            <MyComponent>
              <MyComponent />
            </MyComponent>
          </MyComponent>
        </MyProvider>
      </div>

      <div className="context-provider">
        <MyProvider>
          <MyComponent />
          <MyComponent />
        </MyProvider>
      </div>
    </div>
  );
};

export default App;

 

 여기서 { count, increase, decrease } 데이터는 각각의 MyProvider 컴포넌트에서 생성된 것이고,  MyContext.Provider 의 value 값으로 넘겨진 것을 볼 수 있다. 그리고 MyComponent 는 MyContext.Provider 컴포넌트에 감싸져 있기 때문에 MyComponent 에서 useContext 훅을 통해 Provider 의 value 데이터인 { count, increase, decrease } 에 접근할 수 있게 된다.

즉 상위 컴포넌트인 MyProvider 에서 생성된 데이터인 {count, increase, decrease} 를

하위 컴포넌트인 MyComponent 에서 props 전달없이 한번에 사용하고 있는 것을 볼 수 있다.

 

결과화면은 다음과 같다.

예시 코드 결과화면

첫번째 섹션과 두번째 섹션의 Context.Provider가 따로 생성이 되어서 데이터가 서로 다르게 동작하는 것을 볼 수 있다..!

 

끝..

 


 

이게 정말 글로 설명하려니까 난해하고 어렵게 쓰게 된 것 같다. 익숙치 않은 API 라서 그런가..

음 추후 오픈 소스를 뜯어보면서 Context API 에 대해서 더 알아본 후 다시 포스팅을 쓰도록 해봐야겠다.

반응형
Comments