React Context API 개념

hoo00nn·2020년 12월 18일
0
post-thumbnail

Context API란?

Context는 모든 레벨의 컴포넌트 트리에 props를 통하지 않아도 데이터를 전달할 수 있는 방법을 제공해줍니다.

작은 프로젝트의 수준을 넘어서 꽤 규모가 있는 프로젝트를 만들고 싶거나 반복적으로 만들던 컴포넌트를 재사용 가능한 컴포넌트로 만들어 보고 싶다면 Context API가 필요한 순간이 올 것입니다.

기본적으로 리액트에서 다른 컴포넌트로부터 데이터를 전달 받을 때 props 라는 것을 사용합니다.

하지만 props는 한계가 있습니다. 자신의 바로 위에 있는 컴포넌트로부터 직접 전달 받아야 한다는 점입니다.

부모 컴포넌트가 있고 자식 컴포넌트가 밑에 있을 때 props로 넘겨줘야 합니다. 만약 이 depth가 한 번이라면 괜찮겠지만 depth가 깊다고 가정한다면 한참 위에 있는 부모 컴포넌트로부터 값을 전달 받아야 사용해야 합니다. 그러면 중간에 있는 컴포넌트들은 이 값을 별로 사용하고 싶지 않아도 자식 컴포넌트로 props를 넘겨주는 일을 해야 합니다.

이해하기 어려울 수 있어 그림으로 간단하게 설명해드리겠습니다.

그림과 같이 B,C에선 사용하지 않지만 D에서 상태를 사용해야 한다면 A → B → C → D 순으로 props를 넘겨줘야 합니다.

이것보다 depth가 더 길어지게 된다면 코드도 복잡해질 뿐만 아니라 유지보수에도 어려워지게 됩니다.

또 다른 예시를 하나 들어보겠습니다. 리액트는 SPA(Single Page Aplication)이기 때문에 항상 최상위 컴포넌트가 있습니다. 그리고 라우터 처리를 해서 페이지가 나눠지는 것처럼 만들 수 있습니다.

B라는 페이지 역할을 하는 컴포넌트와 C라는 페이지 역할을 하는 컴포넌트가 있다고 가정을 하겠습니다.

만약 D와 F 컴포넌트에서 필요한 데이터가 같다면 어떻게 해야할까요?

A라는 컴포넌트에 상태를 만들고 B와 C 각각에 props로 전달하고 쭉 타고 내려가 D와 F까지 상태를 전달해야할 것입니다.

이렇게 페이지가 많아지는 등 프로젝트 규모가 커진다면 props만으로 데이터를 전달하기 힘든 상황이 올 것입니다.

이럴 경우에 사용하면 좋은 것이 Context API입니다.

Context API를 사용했을 경우 도식화

context API를 사용하면 context를 만들고 특정 컴포넌트에 context를 감싸준다면 감싼 컴포넌트의 하위에 있는 모든 컴포넌트들은 해당 context에 직접적으로 접근하여 상태를 사용할 수 있게 됩니다.

아래의 사진과 같이 D와 F에서 모두 사용할 수 있도록 하려면 A라는 컴포넌트를 context로 감싸줘야겠죠?

Context API 사용법

코드로 예를 들어보겠습니다.

아래의 코드처럼 Title 컴포넌트와 User컴포넌트에 라우팅을 적용했습니다.

import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Title from "./pages/title";
import User from "./pages/user";

export default function App() {
  return (
    <Router>
      <Switch>
        <Route path="/title" component={Title} />
        <Route path="/user" component={User} />
      </Switch>
    </Router>
  );
}

만약 Title컴포넌트와 User컴포넌트에서 같은 상태를 가지고 싶다면 Context API로 어떻게 할 수 있을까요?

아래의 코드와 같이 createContext 함수를 통해 비어있는 context를 만들고 context의 Provider를 통해 상태를 넣을 수 있습니다. 아래의 코드에서는 간단한 유저 정보를 넣었습니다.

그리고 가운데 있는 props.children은 하위 컴포넌트가 들어갈 자리인데요. children에 들어가는 컴포넌트들은 UserContext로 감싸져있기 때문에 언제든지 context에 있는 상태에 접근할 수 있게 됩니다.

import React, { createContext } from "react";

export const UserContext = createContext();

const Store = (props) => {
  const users = {
    name: "jihoon",
    age: 25
  };

  return (
    <UserContext.Provider value={users}>{props.children}</UserContext.Provider>
  );
};

export default Store;

그럼 방금 만든 Store를 App.js에 들어가 최상단에 감싸보겠습니다.

export default function App() {
  return (
    <Store>
      <Router>
        <Switch>
          <Route path="/title" component={Title} />
          <Route path="/user" component={User} />
        </Switch>
      </Router>
    </Store>
  );
}

그럼 하위 컴포넌트에서 context에 있는 상태를 가져다 쓰려면 어떻게 해야할까요?

아까 만들었던 UserContext와 react에서 제공하는 useContext 훅을 사용하면 됩니다.

아래와 같이 useContext의 인자로 사용할 context를 넣어주게 되면 아까 context를 만들 때 Provider에 넣어줬던 값을 반환하므로 비구조화 할당을 통해 원하는 값만 가져올 수 있습니다.

import React, { useContext } from "react";
import { UserContext } from "../store/user";

const Title = () => {
  const { name } = useContext(UserContext);
  return (
    <>
      <h1>hello {name}</h1>
    </>
  );
};

export default Title;

사진과 같이 이름을 잘 불러온 것을 볼 수 있습니다.

Context API를 사용하기 전 주의할 점

Context는 꼭 용도에 맞는 상황에서만 사용해야 합니다. 즉, 전역 데이터를 한 곳에서 저장하고 여러 컴포넌트에서 접근하고 싶은 경우가 아니라면 사용을 안하는게 좋습니다. 문서에 따르면 Context 를 사용하게 되면 해당 컴포넌트는 해당 Context가 없이는 재사용이 어려워지므로 꼭 필요 할때만 사용해야합니다.

이번 포스팅에선 Context API에 대해서 알아보았습니다. 다음엔 Redux에 대해서 알아보겠습니다.

profile
😀 신기술에 관심이 많고, 함께 성장하고 함께 개발하고 싶은 개발자가 되고 싶습니다. 😀

0개의 댓글