지식 정리 📝

React Conext 톺아보기

엄성준 2024. 11. 10. 13:09

오늘 React Context를 톺아보려는 이유는 많은 기업에서 React를 사용하면서 Props 전달이 필요한 상황에서 Context를 적극 활용하고 있다는 생각이 들어서입니다.

이 글에서는 공식 문서(React v18.3.1)를 참고해 Context의 개념과 사용법을 정리해 보려고 합니다.

https://ko.react.dev/learn/passing-data-deeply-with-context

 

Context를 사용해 데이터를 깊게 전달하기 – React

The library for web and native user interfaces

ko.react.dev

 

React Context는 왜 등장했을까요?

React를 사용해 본 사람이라면 부모 컴포넌트에서 자식 컴포넌트로 Props를 전달하는 과정을 경험해 보셨을 겁니다.

부모와 자식 컴포넌트 간에 직접 Props를 전달하는 경우에는 큰 문제가 없지만, 중간에 여러 자식 컴포넌트를 거쳐 Props를 계속 전달해야 한다면 과정이 점점 번거로워집니다.

특히 TypeScript를 사용하고 있다면, 각 자식 컴포넌트에서 Props의 타입까지 매번 선언해줘야 해 더욱 귀찮아질 수 있습니다.

이런 문제를 해결하기 위해, React는 Props를 일일이 전달하는 대신 원하는 컴포넌트에 "순간이동" 시키듯 값을 제공할 수 있는 Context를 도입했습니다

 

Prop drilling

출처: React 공식 문서

 

codesandbox 링크로 접속하시면 지금은 각각의 <Heading> 컴포넌트level prop을 전달하고 있고 다음과 같이 코드를 수정하려고 합니다.

각각의  <Heading> 컴포넌트 에  level  prop을 전달 하는 이미지
import Heading from './Heading.js';
import Section from './Section.js';

export default function Page() {
  return (
    <Section level={1}>
      <Heading>Title</Heading>
      <Section level={2}>
        <Heading>Heading</Heading>
        <Heading>Heading</Heading>
        <Heading>Heading</Heading>
        <Section level={3}>
          <Heading>Sub-heading</Heading>
          <Heading>Sub-heading</Heading>
          <Heading>Sub-heading</Heading>
          <Section level={4}>
            <Heading>Sub-sub-heading</Heading>
            <Heading>Sub-sub-heading</Heading>
            <Heading>Sub-sub-heading</Heading>
          </Section>
        </Section>
      </Section>
    </Section>
  );
}

 

1단계: Context 생성하기 

먼저 context를 만들어야 합니다. 컴포넌트에서 사용할 수 있도록 파일에서 내보내야 합니다.

import { createContext } from 'react';

export const LevelContext = createContext(1);

 

 

2단계: Context 사용하기

React에서 useContext Hook과 생성한 Context를 가져옵니다.

levelprop을 제거하고 대신 위에서 가져온 context인 LevelContext에서 값을 읽도록 합니다.

import { useContext } from 'react';
import { LevelContext } from './LevelContext.js';

export default function Heading({ children }) {
  const level = useContext(LevelContext);
  // ...
}

 

3단계: Context 제공하기

LevelContext를 자식들에게 제공하기 위해 context provider로 감싸줍니다.

import { LevelContext } from './LevelContext.js';

export default function Section({ level, children }) {
  return (
    <section className="section">
      <LevelContext.Provider value={level}>
        {children}
      </LevelContext.Provider>
    </section>
  );
}

 

다시 한번 정리해 보면 아래의 단계를 거쳤습니다.

  1. LevelContext라는 이름으로 createContext 훅을 활용해 기본값을 1로 설정하여 Context를 생성합니다.
  2. Section 컴포넌트에서 LevelContext.Provider로 하위 컴포넌트를 감싸고, value에 level 값을 전달합니다.
  3. Heading 컴포넌트에서는 기존에 Props로 전달받던 level을 제거하고, 대신 useContext(LevelContext) 훅을 사용해 level 값을 받아와 필요한 분기 처리를 수행하도록 변경합니다.

 

구현 코드입니다.

https://codesandbox.io/p/sandbox/hl9ysq

 

https://codesandbox.io/p/sandbox/hl9ysq

 

codesandbox.io

 

나의 생각

오늘은 Props를 ‘순간이동’할 수 있는 React의 Context에 대해 살펴보았습니다. 개인적인 컨벤션으로는 컴포넌트 깊이가 3단계를 초과하지 않는 한 Props를 직접 전달하는 방식을 선호하고 있으며, 3단계를 넘어가면 주로 Redux Toolkit이나 Zustand와 같은 전역 상태 관리 라이브러리를 사용해 문제를 해결해 왔습니다.

현재 사내에서는 Context 사용 빈도가 매우 낮지만, 다른 기업에서도 각 사의 컨벤션에 맞추는 것이 중요하다고 생각합니다. 만약 기존 코드에서 Context로 Props를 전달하고 있다면 그 방식을 따르는 것이 맞고, 전역 상태 관리 라이브러리를 사용하고 있다면 이에 맞추어야 한다고 생각합니다. 이처럼 저는 상황에 맞게 적응하며 사용하는 것이 중요하다고 느끼며, 어떤 환경에서도 쉽게 적응할 수 있도록 Context를 포함한 다양한 방식을 공부하고 있습니다.