개발공작소
article thumbnail
728x90
반응형

 

 

 

오늘은 그냥 리액트에서 Context를 사용하는 또 다른 방법을 정리해보려고 한다..

 

 

 

Context.Provider 분리하는 이유

 

유튜브에서 Context관련 글을 검색해 보는데, 다음과 같은 영상이 눈에 들어왔다.

 

This Context API Mistake Ruins Your Whole React App (All Components Re-Render)

 

썸네일만 보면 Context 컴포넌트의 Provider 프로퍼티를 쓰지 말고, Comtext.Provider 컴포넌트를 만들어 써라

라는 느낌의 그림이다.

 

대충 내용만 요약하자면, Context컴포넌트를 따로 모듈로 분리해서 사용해라인데,

그 이유는 일반적으로 상위 컴포넌트에서 하위 컴포넌트들에게 데이터를 전달하기 위해 <Context.Provider>를 쓰면

 

state가 변경되면서 useContext로 데이터를 받지 않는 다른 자식컴포넌트 즉, 모든 컴포넌트가 리랜더링 되니

성능상 좋지 않다. 라는 내용이었다..

 

위 영상을 포함해서 gpt4 친구에게 물어보니 다음과 같은 이유를 들었다.

 

1. 하위 컴포넌트들이 모두 리랜더링 되며 성능에 문제가 생길 가능성이 있음

2. 모듈 단위로 분리하여 가독성과 유지보수성을 높임

3. 동일한 로직을 가지는 컴포넌트에서 Provider 컴포넌트를 재사용할 수 있음.

4. 코드의 간결화...

 

곰곰히 생각해보면 대충 다 맞는 말 같다..

 

아래 샘플코드를 보도록 하자. 

 

샘플코드

import { createContext, useState, useContext } from "react";

const NewContextProvider = createContext();
const App = () => {
  const [count, setCount] = useState(1);

  const increase = () => {
    setCount((count) => count + 1);
  };

  return (
    <>
      <div className="App">
        <NewContextProvider.Provider value={{ count, setCount, increase }}>
          <Child1 />
          <Child2 />
          <Child3 />
        </NewContextProvider.Provider>
      </div>
    </>
  );
};

const Child1 = () => {
  console.log("Child1이 리랜더링 됨");
  const { count, setCount, increase } = useContext(NewContextProvider);
  return (
    <>
      Child1 컴포넌트입니다.. 👉<button onClick={increase}>+</button> 👉 값:
      {count}
      <br></br>
    </>
  );
};

const Child2 = () => {
  console.log("Child2이 리랜더링 됨");
  return (
    <>
      Child2 컴포넌트입니다.. 👉<button>+</button> 👉 값: <br></br>
    </>
  );
};

const Child3 = () => {
  console.log("Child3이 리랜더링 됨");
  return (
    <>
      Child3 컴포넌트입니다.. 👉<button>+</button> 👉 값:
    </>
  );
};
export default App;

 

 

결과

0

 

보면 useContext를 통해 state를 사용하는 자식컴포넌트는 Child1뿐이지만, Child2와 Child3까지 리랜더링 되는 걸

확인할 수 있다..

 

당연한 이야기이지만, state가 변경되며 부모 컴포넌트인 App 컴포넌트가 리랜더링 되며, 자식 컴포넌트들이

모두 리랜더링 된다. 

 

이런 문제를 방지하기 위해 Context 로직을 분리하는 방법이 있다.

 

 

Context.Provider 컴포넌트로 분리하는 방법

 

그냥 코드만 보면서 이야기 하도록 하겠다..

 

 

App.jsx

import { createContext, useState, useContext } from "react";
import {
  NewContextProvider,
  CountContext,
  GetCountContext,
} from "./context/NewContext.jsx";

const App = () => {
  return (
    <>
      <div className="App">
        <NewContextProvider>
          <Child1 />
          <Child2 />
          <Child3 />
        </NewContextProvider>
      </div>
    </>
  );
};

const Child1 = () => {
  console.log("Child1이 리랜더링 됨");
  const { count, setCount, increase } = useContext(NewContextProvider);
  return (
    <>
      Child1 컴포넌트입니다.. 👉<button onClick={increase}>+</button> 👉 값:{" "}
      {count}
      <br></br>
    </>
  );
};

const Child2 = () => {
  console.log("Child2이 리랜더링 됨");
  return (
    <>
      Child2 컴포넌트입니다.. 👉<button>+</button> 👉 값: <br></br>
    </>
  );
};

const Child3 = () => {
  console.log("Child3이 리랜더링 됨");
  return (
    <>
      Child3 컴포넌트입니다.. 👉<button>+</button> 👉 값:
    </>
  );
};
export default App;

 

 

NewContext.jsx

import { createContext, useContext, useState } from "react";

export const CountContext = createContext();

export const NewContextProvider = ({ children }) => {
  const [count, setCount] = useState(1);

  console.log(children);

  const increase = () => {
    setCount((count) => count + 1);
  };

  return (
    <CountContext.Provider value={{ count, setCount, increase }}>
      {children}
    </CountContext.Provider>
  );
};
export const GetCountContext = () => useContext(CountContext);

 

 

결과

0

 

 

위 같이 Context.Provider를 따로 컴포넌트(모듈)로 분리해서 사용하니 useContext를 통해

data를 사용하는 자식 컴포넌트(Child1)만 리랜더링 되는 결과물을 볼 수 있다..

 

그래서 성능을 고려해서 가능하면 Context를 이렇게 분리하여 사용하든, Provider 라이브러리를 사용해서

개발하는 것도 또 하나의 방법 같다..

 

 

 

# 참조 링크

https://www.youtube.com/watch?v=16yMmAJSGek

 

 

 

 

728x90
반응형
profile

개발공작소

@모찌바라기

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!