aotoyae

[React] 최적화 & 리렌더링 막기(3) : useMemo, value 값 캐싱 본문

React

[React] 최적화 & 리렌더링 막기(3) : useMemo, value 값 캐싱

aotoyae 2024. 1. 24. 20:08

 

 

 

[React] 최적화 & 리렌더링 막기(2) : useCallback, 함수 캐싱

[React] 최적화 & 리렌더링 막기(1) : React.memo, 자식 리렌더링 막기 💡 리렌더링의 발생하는 경우 1. 컴포넌트에서 state 가 바뀌었을 때 2. 컴포넌트가 내려받은 props 가 바뀌었을 때 3. 부모 컴포넌트

aotoyae.tistory.com

 

 

🫐 useMemo : 값을 기억한다. 반환되는 값이 바뀌어야 리렌더 할거다.

 

아래와 같이 무거운 작업을 하는 컴포넌트가 있을 때

리렌더링을 매번 해버리면 항상 로딩이 오래 걸린다.

function App() {
  return (
    <>
      <nav style={style}>네비게이션 바</nav>
      <HeavyComponent />
      <footer style={style2}>FOOTER</footer>
    </>
  );
}
function HeavyComponent() {
  const [count, setCount] = useState(0);

  const heavyWork = () => {
    for (let i = 0; i < 10000000000; i++) {}

    return 100;
  };

  const value = heavyWork();

  return (
    <>
      <p>난 엄청 무거운 컴포넌트야 ~</p>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        누르면 Count 올라가요 ~
      </button>
      <p>{count}</p>
    </>
  );
}

 

 

무거운 컴포넌트 때문에 첫 로딩도 오래 걸리지만 카운트 업도 오래 걸린다.

 

 

💡 useMemo 로 감싸주고, 의존성 배열 넣어주고, import

heavyWork 의 리턴 값을 value 에 저장해둔 것!

  const value = useMemo(() => heavyWork(), []);

useMemo 적용 전과 후 ~~

 

 

💡 의존성 배열 Dependency Array 를 활용해 보자

import React, { useState, useEffect, useMemo } from "react";

function HeavyComponent() {
  const [isAlive, setIsAlive] = useState(true);
  const [uselessCount, setUselessCount] = useState(0);

  const me = {
    name: "Ted",
    age: 20,
    isAlive: isAlive ? "생존" : "사망",
  };

  useEffect(() => {
    console.log("생존 여부가 바뀔 때만 호출해 주세요!");
  }, [me]);

  return (
    <>
      <p>
        난 {me.name} 라고 해. 나이는 {me.age} ~
      </p>
      <div>
        <button
          onClick={() => {
            setIsAlive(!isAlive);
          }}
        >
          누르면 살았다가 죽었다가 해요
        </button>
        <br />
        생존여부 : {me.isAlive}
      </div>
      <hr />
      <p>필요 없는 숫자 영역이에요</p>
      {uselessCount}
      <br />
      <button
        onClick={() => {
          setUselessCount(uselessCount + 1);
        }}
      >
        누르면 숫자가 올라가요
      </button>
    </>
  );
}

export default HeavyComponent;

 

위 버튼을 눌렀을 때 me 가 set 되면서 콘솔이 찍히는데,

아래 버튼을 눌러도 콘솔이 찍히고 있다.

 

🥲 객체는 같은 값의 두 객체를 저장하면
(값이 같지만!!!!)다른 주솟값으로 연결하기 때문이다.

 

그래서 아래 버튼을 누르고 HeavyComponent 가 읽힐 때

me 를 다시 저장하고 useEffect 는 me 가 바뀌었다고 인식해 실행이 되버린다.

 

 

[JS] 데이터의 불변성 : 원시 데이터, 참조형 데이터

💡 데이터의 불변성에 대해 알아보자 원시 데이터 : 숫자, 문자, 불리언.. 원시 데이터들은 같은 값을 저장하면 그 값의 같은 주소를 적어둔다. number1 = @111 ➡️ @111 = 1 number2 = @111 ➡️ @111 = 1 참

aotoyae.tistory.com

 

그러니 me 를 isAlive 가 바뀔 때만 바뀌도록 설정해야 한다.

  const me = useMemo(() => {
    return { name: "Ted", age: 20, isAlive: isAlive ? "생존" : "사망" };
  }, [isAlive]); {/*수정한 부분*/}

  useEffect(() => {
    console.log("생존 여부가 바뀔 때만 호출해 주세요!");
  }, [me]);

 

그럼 카운트 버튼을 눌러도 콘솔이 찍히지 않는다!!

➡️ 원하던 대로 me 가 바뀔 때만 찍힌다!

 

❗️ 주의할 점

useMemo 를 남발하게 되면 별도의 메모리 확보를 너무 많이 해버려서

오히려 성능이 떨어질 수 있다. 필요할 때만 쓰도록 하자.

 

 

 

728x90
반응형