React Hooks :: useContext에 대해 알아보기 (Feat. Context API)

Hayoung·2021년 4월 30일
1

React

목록 보기
1/2
post-custom-banner

React의 Hook이란 무엇일까?🤔

  • Hook은 React 버전 16.8부터 React 요소로 새로 추가되었습니다. Hook을 이용하여 기존 Class 바탕의 코드를 작성할 필요 없이 상태 값과 여러 React의 기능을 사용할 수 있습니다.
  • 출처: Hook의 개요 - React 공식 문서

Hook은, 아주아주아주x100 짧게 말하자면 Class를 사용하지 않고도 State, 생명주기 메서드(LifeCycle Method)와 같은 React 기능을 함수형 컴포넌트에서도 사용할 수 있도록 해준다.

React에는 기본적으로 제공하는 내장 훅(Built-in Hooks)이 있는데,
이번 글에서는 React 내장 훅 중 하나인 useContext에 대해 공부하고자 한다🤓


useContext의 'Context'란 무엇일까?🤔

  • context를 이용하면 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있습니다.
  • context는 React 컴포넌트 트리 안에서 전역적(global)이라고 볼 수 있는 데이터를 공유할 수 있도록 고안된 방법입니다.
  • context의 주된 용도는 다양한 레벨에 네스팅된 많은 컴포넌트에게 데이터를 전달하는 것입니다.
  • 출처: Context - React 공식 문서

React로 개발을 하다보면, 상위 컴포넌트로부터 하위 컴포넌트에게 데이터를 전달해야하거나,
컴포넌트 트리 내에서 데이터를 전역적(global)으로 관리를 할 상황이 자주 일어난다.
이때 컴포넌트 트리 구조가 복잡하거나 거대한 경우에는,
단순히 데이터를 넘겨주기 위한 용도의 컴포넌트가 생성되기도 한다.
예를 들면, X라는 데이터를 D 컴포넌트에서 사용한다고 가정하자.
A→B→C→D
X가 엄청난 환승을 거쳐야한다. 아주 힘든 여정이다.

데이터만 잘 넘겨졌으면 된거 아니야?🤨라고 생각할 수 있는데,
우리의 환승을 생각해보자.
저 멀리 목적지에 가기 위해 버스 탔다가 지하철로 환승. 지하철에서 또 버스로 환승...
굉장히 귀찮고 피곤하지 않은가😖
그리고 장기적으로 봤을 때 컴포넌트 트리 구조가 굉장히 복잡해지기 때문에
컴포넌트를 관리하는 것이 어려워지게 된다.

이 쯤에서 다시 한 번 「useContext의 'Context'란 무엇일까?🤔」 소제목 밑의
React 공식 문서페이지로부터 인용된 설명을 보자.

context를 이용하면, 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에서 데이터를 사용할 수 있습니다🤭

느낌이 오는가?

나는 Context를 보물 상자💎📦 라고 이해했다. (혹시 비유가 잘못됐다면 지적해주세요!)
소중한 녀석들을 한 곳에 모아두고 저장하는 보물 상자.
Context는 우리의 소중한 데이터를 담아두고 저장하는 보물 상자💎📦 인 것이다.

소중한 데이터를 저장해두는 보물 상자💎📦 = Context를 마련해둠으로써,
상위 컴포넌트에서 하위 컴포넌트로 하나하나 데이터를 건네주지 않아도
소중한 데이터를 언제든지 꺼내볼 수 있도록 했기 때문에,
언제 어디서든 보물 상자 a.k.a. Context에 접근해서 필요한 데이터를 꺼내볼 수 있다.

↑ Context와 기존의 props를 넘겨주는 방식을 그림으로 표현하자면 요런 느낌.
Context에 데이터를 담아두었기 때문에 원하는 계층에서 바로 그 데이터를 가져와서 사용할 수 있다.
즉, 컴포넌트 트리 전체에서 언제 어디서나 전역적(global)으로 데이터를 사용할 수 있게 해주는 것이 Context이다.

이렇게 유용한 Context로부터 데이터를 가져와서 사용하기 위하여
React 내장 훅으로 구현된 것이 바로바로 오늘의 주인공인 useContext이다🥰


useContext 경험해보기👊

유저 이름을 표시하는 아주아주아주x100 간단한 웹 페이지를 만들어 보자.
아래의 결과 화면에서 JohnContext에 저장된 값을 불러온 것이다.

1️⃣ 먼저, 데이터 저장소인 Context를 생성하자

Context를 생성할 때에는 createContext라는 함수를 사용한다.
createContext의 파라미터에는 해당 Context에 기본값으로 설정할 값을 입력한다.
기본값을 따로 지정하지 않을 경우에는 파라미터를 비워두거나 null을 입력.

// context.js

import React from "react";
export const UserNameContext = React.createContext(null);

또는

// context.js

import React, { createContext } from "react";
export const UserNameContext = createContext(null);

위 두가지 방법 모두 Context를 생성한다는 결과는 같다.
createContext를 언제 불러오느냐의 차이.

2️⃣ Context의 값을 설정하기 (Context에 값을 저장하기)

아래의 캡쳐와 같이 1️⃣ 에서 생성했던 UserNameContextconsole.log해보면,
Context 내부에는 Provider라는 컴포넌트가 있다는 것을 알 수 있다.

Provider란 무엇일까?

  • Provider 컴포넌트는 value prop을 받아서 이 값을 하위에 있는 컴포넌트에게 전달합니다.
  • 출처: Context - React 공식 문서
// App.js

import React from "react";
import Screen from "./Screen";
import { UserNameContext } from "./context";

export default function App() {
  return (
    <UserNameContext.Provider value="John">
      <Screen />
    </UserNameContext.Provider>
  );
}

Context의 값은 Provider 컴포넌트를 통해 설정할 수 있다.
위의 공식 문서의 설명과 같이, Provider 컴포넌트는 value라는 prop을 받게 되는데,
Context의 값을 설정할 때는 이 Provider 컴포넌트의 value prop에 값을 설정해준다.

value prop에 설정하는 값은 바로, 실제로 하위 컴포넌트에 전달하려는 값이다.
앞서 「useContext의 'Context'란 무엇일까?🤔」 파트에서 예시로 설명했던 아래의 내용에서,

예를 들면, X라는 데이터를 D 컴포넌트에서 사용한다고 가정하자.
A→B→C→D
X가 엄청난 환승을 거쳐야한다. 아주 힘든 여정이다.

여기서 X라는 데이터가 Provider 컴포넌트의 value prop의 값이 된다.

Provider 컴포넌트로 감싸진 모든 컴포넌트는 Context에 대한 접근권한이 생기게 되는데,
Provider 컴포넌트로 감싸진 컴포넌트 내에서는 어디서든지 Context의 값을 조회해서 사용할 수 있게 된다.

위의 예시 코드에서 Screen 컴포넌트는 Provider 컴포넌트로 감싸져 있기 때문에, Context의 값을 조회해서 사용할 수 있게 된다.

3️⃣ Context에 저장된 값을 사용하기, 불러오기 (useContext 등장!)

2️⃣ 의 예시 코드에서 등장한 Screen 컴포넌트는
Provider 컴포넌트로 감싸져 있기 때문에 Context에 접근을 할 수 있게 됐다.
자, 그럼 Screen 컴포넌트에서 Context에 저장된 값을 사용하기 위해서는 어떻게 해야 할까?

그렇다! 여기서 바로 우리의 주인공인 useContext가 등장하게 된다!!👏
useContext를 사용함으로써 Context의 값=Provider 컴포넌트에서 지정했었던 value값을 사용할 수 있게 된다!

// Screen.js

import React, { useContext } from "react";
import { UserNameContext } from "./context";

export default function Screen() {
  const userName = useContext(UserNameContext);
  return <p>My name is {userName}</p>;
}
  • 1행: useContext를 사용하기 위해, React로부터 useContext라는 Hook을 import한다. (앞서 언급했듯이 useContext는 React의 내장 Hook임. 그렇기 때문에 React로부터 import가 가능함)
  • 2행: context.js에서 생성했던 UserNameContext라는 이름의 Contextimport한다.
  • 5행: UserNameContext라는 Context에 담긴 값을 사용하고 불러오기 위해 useContext를 사용. useContext의 인자에는 2행에서 불러온 ContextUserNameContext를 지정한다. userName이라는 정수를 만들어서 그 안에 UserNameContext의 값을 넣는다.
  • 6행: 5행에서 만들었던 userName을 사용한다.

4️⃣ 출력 결과

이렇게 Context에 저장된 값인 John을 불러와서 출력하는 것에 성공👏


전체 코드 보기, Demo 🔍


마치며

ContextuseContext를 통해 같은 데이터를 여러 컴포넌트가 공유할 때 발생하는 문제와
데이터를 하위 컴포넌트로 전달할 때 발생되는 문제를 해결함으로써,
컴포넌트 트리를 복잡한 컴포넌트 구성에서 벗어날 수 있다는 것을 알았다.

아주아주아주x100000 간단한 예시여서 useContext의 진가를 보여주지 못했지만...
useContextuseState와 같은 또다른 Hook들과 조합해서 쓰는 등
얼마든지 응용을 한다면 좀 더 유용하게 사용할 수 있을거라는 생각이 든다.

혹여나 이 페이지에 틀린 정보가 있다면 마구마구 지적해주시면 감사하겠습니다!🙇‍♀️

profile
Frontend Developer. 블로그 이사했어요 🚚 → https://iamhayoung.dev
post-custom-banner

0개의 댓글