느릿늘있

[React Hooks] useContext 이해하기 본문

개발공부

[React Hooks] useContext 이해하기

JHKim93 2024. 10. 13. 20:23

  React에서는 다양한 Hooks를 사용해서 컴포넌트의 상태를 관리하는 패러다임을 제시합니다. 그 중 하나로 useContext라는 훅이 있는데요. 실무에서 자주 써본 것이 아니라면 그냥 전역 상태 관리를 할 수 있게 해주는 훅이다 정도로 알고 있을 겁니다. 저 또한 그랬기에 이번 기회에 useContext에 대해 공식 문서를 보면서 꼼꼼하게 정리해보려고 합니다!

https://ko.react.dev/reference/react/useContext

 

useContext – React

The library for web and native user interfaces

ko.react.dev

  React의 공식 문서에는 useContext를 컴포넌트에서 Context를 읽고 구독할 수 있는 React Hook이라고 설명하고 있습니다. 이 말을 이해하려면 우선 Context(문맥, 맥락)가 뭔지를 알아야 하는데요. React에서 Context는 그냥 말하자면 전역 상태를 의미합니다. 하지만 Context라는 단어를 놓고 생각하자면 글(코드, 컴포넌트)을 둘러싼(감싸고 있는) 문맥(전역 상태)이다라고 이해할 수 있을 것 같습니다. 즉 이 프로그램이 전체적으로 어떤 맥락에서 실행되고 있는가를 설정하고 보여주는 역할을 하는 것이 바로 컨텍스트입니다. 실제로 내부 컴포넌트에서 그 맥락 속에서 필요한 정보(상태)들을 쏙쏙 뽑아서 사용하고 있는 것이지요.

  React에서 Context는 생성(Create) - 제공(Provide) - 사용(Consume)이 라는 아주 명료한 과정으로 구성됩니다. 그리고 이 과정을 선언적으로 사용할 수 있게 도와주는 도구가 바로 Context API인 것이죠.

https://dmitripavlutin.com/react-context-and-usecontext/

1. 생성 (Create)

  Context를 생성하는 Context API는 createContext(defaultValue)입니다. createContext는 context 객체를 반환하는데요. 공식 문서에도 나와 있듯이 context 객체는 별로 대단한 게 없는 그냥 createContext할 때 인자로 전달한 defaultValue 객체입니다. 다만 여기에 Provider, Consumer, DisplayName을 기본 속성으로 갖고 있다는 점이 유일한 특징입니다.

const contextObject = createcreateContext({
	myData1: "기본값1",
	myData2: "기본값2"
})

// 여기서 contextObject는 단지 Provider, Consumer, Display를 갖게 될 뿐이고 이를 단순하게 표현하면 아래와 같다.
contextObject = {
	Provider,
	Consumer,
	DisplayName: "Context", 
	myData1: "기본값1",
	myData2: "기본값2"
}

2. 제공 (Provide)

  위에서 생성한 Context를 제공하는 방법은 단순하게 해당 Context를 주입할 컴포넌트들을 모두 감싸고 value로 값을 전달하면 됩니다.

import { ContextObject } from '00000.js'

export default function ComponentA() {
    ...
    const myData1 = "문맥값1";
    const myData2 = "문맥값2";

    // 생성한 Context의 Provider로 감싸고 value로 전역 상태값을 주입한다.
    return (<ContextObject.Provider value={
        myData1: myData1,
        myData2: myData2,
    }>
      <Page />
    </ContextObject.Provider>)
}

3. 사용 (Consume)

  이 글의 제목인 useContext가 바로 이 사용 단계에서 쓰이는 훅입니다. useContext 훅이 생기기 전 사용 단계의 코드는 어떻게 생겼었는 지부터 알아보시죠.

// Page.jsx
import { ContextObject } from '00000.js'

export default function ComponentA() {
    ...
    return (<ContextObject.Consumer>
        {({ myData2 }) => (<div>{myData2}</div>)}
    </ContextObject.Consumer>)
}

  위 코드처럼 Provider 내부의 컴포넌트에서 또 한번 Consumer로 내부 요소들을 감싸서 그 안에서 Provider에서 주입한 데이터를 불러와서 사용하고 있습니다. 어려운 내용은 아니지만 설명하는 말부터도 복잡하게 느껴집니다. 이런 방식은 상당히 React스럽지 못하다라고 할 수 있습니다. 보다 React스러운 오늘의 주제, useContext가 어떻게 Context를 사용(Consume)하는 지 알아보시죠.

// Page.jsx
import { ContextObject } from '00000.js'
import { useContext } from 'react';

export default function ComponentA() {
    ...
    const { myData2 } = useContext(ContextObject);

    return <div>{myData2}</div>;
}

  JSX 내부에 거추장스럽게 존재하던 Consumer 요소가 사라지고 컴포넌트 함수 내에서 이를 사용할 수 있게 되었습니다. 예시만 보면 생각보다 줄어드는 코드의 양이 많지 않다고 느낄 수도 있을 것 같은데요. 그것과는 별개로 상당히 React스러운 코드가 되었다는 사실에는 이견이 없을 것 같습니다.

  Context 객체의 3가지 기본 속성 중 DisplayName은 Context의 동작과는 크게 상관이 없습니다. 다만 React DevTools에서 해당 컨텍스트를 디버깅할 때 표출할 이름을 정해준다라고만 아시면 될 것 같습니다. 

  useContext를 사용할 때는 아래 3가지 주의사항을 꼭 기억해주세요!

  1. 컨텍스트 값이 변경되면 해당 컨텍스트를 사용하는 모든 컴포넌트가 리렌더링됩니다.
  2. 성능 최적화를 위해 필요한 경우 컨텍스트를 분리하거나 메모이제이션을 사용할 수 있습니다.
  3. 컨텍스트는 자주 변경되는 값보다는 테마, 인증 정보 등 비교적 안정적인 값에 적합합니다.

  끝으로 Context API를 프로젝트에 도입할 지 고민 중이시거나 더 잘 써보고 싶으시다면 아래 블로그 글을 추천드립니다!

https://velog.io/@velopert/react-context-tutorial

 

다른 사람들이 안 알려주는 리액트에서 Context API 잘 쓰는 방법

여러분, 리액트로 웹 애플리케이션 개발 하면서 Context API를 어떻게 사용하고 계신가요? 과거에도 관련 포스트를 작성한적이 있긴 하지만, 지난 몇 년간 Context를 사용하면서 습득하게된 팁들을

velog.io