전역 상태관리와 Props.children 그리고 Context API

응애 나 프론트애긔👶·2022년 8월 14일
0
post-thumbnail

전역 상태관리 🙆



전역이라는 단어을 우리는 자바스크립트에서도 본 적이 있다.

전역 객체, 전역 변수...

전역이란 군복무를 마친.... 🤜🤕

전역이란 전체영역 정도로 이해하면 좋을거 같다.

전역 상태관리는 그 이름 그대로 전역에서 상태를 관리한다는 뜻이다.

그렇다면 React에서는 전역 상태관리를 어떻게 관리를 하는가 ?

가장 쉬운 방법은 상위 컴포넌트에서 하위 컴포넌트로 prop을 전달해주면 된다.



코드로 표현해보자 !


// 막내에게 소세지를 주자 !
function App() {
  return (
    <div>
      <FirstComponent sausage="소세지" />
    </div>
  );
}

function FirstComponent({ sausage }) {
  return (
    <div>
      <h3>난 첫째 ! 둘째야 받아 !</h3>
      <SecondComponent sausage={sausage} />
    </div>
  );
}

function SecondComponent({ sausage }) {
  return (
    <div>
      <h3>난 둘째 ! 막내야 받아 !</h3>
      <ThirdComponent sausage={sausage} />
    </div>
  );
}

function ThirdComponent({ sausage }) {
  return (
    <div>
      <h3>막내 {sausage} 잘 받았습니다 !</h3>
    </div>
  );
}

export default App;

위 코드를 보면 FirstComponent에서 sausageThirdComponent로 전달하고 있다.

이런식으로 전달되면 ThirdComponent 컴포넌트에서 sausage을 받을 수 있다.

참 간단한 방법이지만 이 방법은 너무나 큰 단점이 존재한다.

그것은 바로....


Prop Drilling


Prop Drilling이란 상위 컴포넌트에서 props를 하위 컴포넌트로 전달할 때 사용은 하지않는 컴포넌트들도 거쳐가는 현상이다. 이것을 드릴로 비유하여 이름을 지은 것이다.

작은 규모의 프로젝트라면 Prop Drilling은 크게 문제가 되지 않지만 큰 규모의 프로젝트에서 prop이 많은 하위 컴포넌트를 거쳐가게 된다면 해당 prop을 추적하기도 어렵고 관리하기도 어려워 유지보수에 많은 힘이 든다.

( 만약 위에 코드에서 3남매가 아닌 20남매라면 ...? )

이러한 Prop Drilling을 겪지 않고 상태관리를 하는 방법이 있을까 ??


Props.children 👪



props.children이라는 녀석은 합성과 관련된 친구다.

코드로 표현해보자 !

function App() {
  const sausage = "소세지";
  return (
    <div>
      <FirstComponent>
        <SecondComponent>
          <ThirdComponent sausage={sausage} />
        </SecondComponent>
      </FirstComponent>
    </div>
  );
}

function FirstComponent(props) {
  console.log(props);
  return (
    <div>
      <h3>난 첫째 ! 둘째야 받아 !</h3>
      {props.children}
    </div>
  );
}

function SecondComponent(props) {
  console.log(props);
  return (
    <div>
      <h3>난 둘째 ! 막내야 받아 !</h3>
      {props.children}
    </div>
  );
}

function ThirdComponent(props) {
  console.log(props);
  return (
    <div>
      <h3>막내 {props.sausage} 잘 받았습니다 !</h3>
    </div>
  );
}

export default App;

console.log로 각 컴포넌트마다 props의 형태를 살펴보았다.

FirstComponentpropschildren이 한번더 들어있고 그 안에 소세지가 있다.
SecondComponentprops는 소세지가 들어가있고 ThirdComponent는 소세지가 그대로 출력이 된 걸 확인할 수 있다.

한마디로 props.children은 상위 컴포넌트 사이에 있는 하위 컴포넌트를 가져온다. 이것을 바로 합성이라고 하는데 기존 상위 컴포넌트에서 하위 컴포넌트로 상속 하는 방식과는 달리 컴포넌트들을 합치는 과정에 가깝다.


Context API 👀



Context APIReact에서 전역으로 상태관리를 할 수 있도록 도와주는 API이다.

이러한 전역적인 상태관리를 이용하면 상속과 합성을 사용하지 않고도 상태관리를 할 수 있다.


코드로 표현해보자 !

const gift = "소세지";
const giftContext = createContext(gift);

function App() {
  return (
    <div>
      <giftContext.Provider value={gift}>
        <FirstComponent>
          <SecondComponent>
            <ThirdComponent />
          </SecondComponent>
        </FirstComponent>
      </giftContext.Provider>
    </div>
  );
}

function FirstComponent() {
  return (
    <div>
      <h3>난 첫째 ! 둘째야 받아 !</h3>
      <SecondComponent />
    </div>
  );
}

function SecondComponent() {
  return (
    <div>
      <h3>난 둘째 ! 막내야 받아 !</h3>
      <ThirdComponent />
    </div>
  );
}

function ThirdComponent() {
  const sausage = useContext(giftContext);
  return (
    <div>
      <h3>막내 {sausage} 잘 받았습니다 !</h3>
    </div>
  );
}

export default App;

createContextcontext 객체를 만들어준다.
객체를 구독하고 있는 컴포넌트를 렌더링 할 때 React는 트리 상위에서 가장 가까이 있는 짝이 맞는 Provider로 부터 현재 값을 읽는다.

쉽게 말해 createContext() 괄호 안에 있는 값을 초기 값으로 설정하고 해당 값을 전역적으로 사용할 수 있도록 해준다.



giftContext를 콘솔로 찍어 본 결과 위와 같이 객체형태로 나오게 된다.

useContextcreateContext의 값을 사용할 수 있게 해준다.

테스트 결과 위와 같이 giftContext에서 _currentValue를 가져와서 사용해도 사용은 가능하다.

하지만 useContext를 사용하면 그냥 바로 해당 값을 받아 올 수 있다.


function ThirdComponent() {
  const sausage = useContext(giftContext);
  return (
    <div>
      <h3>막내 {giftContext._currentValue} 잘 받았습니다 !</h3>
      <h3>막내 {sausage} 잘 받았습니다 !</h3>
    </div>
  );
}

그래도 변수를 설정하고 사용을 하는게 더 깔끔하다.

이렇게 쓰기 좋은 Context API의 치명적인 단점이 있다. 🚨

바로 Context API는 상태 값이 변하게 되면 provider로 감싼 모든 하위 컴포넌트들이 리렌더링한다.

때문에 불필요한 리렌더링이 일어나게 된다.



오늘의 느낀점✍



상속에 대해서는 이해가 잘 되었다. HTML,CSS,JavaScript에서도 부모 자식 관계에 대해 나름 잘 이해했기 때문이다.

문제는 합성이였는데 합성에 대한 이해만 3시간이 걸린거 같다... (뻥 안치고)

상위 컴포넌트와 하위 컴포넌트는 항상 상위에서 하위에게 props를 전달한다고 생각을 했는데 이런 고정관념이 이해하는데 큰 벽과 같은 역할을 해버렸다.

이곳 저곳 유튜브랑 블로그 설명을 듣고 직접 구현하는데 3시간 가량 쏟은 결과 바깥 컴포넌트가 안쪽 컴포넌트를 집어삼킨다고 이해를 했다.

그리고 Context API에 대해서 알아봤는데 채용 공고에서 Context API를 사용한다는 회사는 딱 한 곳 봤다.

그만큼 많이 사용 안하는 상태관리이고 대부분의 상태관리는 Redux로 하는거 같다.

아마 리렌더링을 하는 단점이 가장 큰 원인이 아닐까 생각이 든다.



예고편...



0개의 댓글