React - 숙련 : 최적화를 위한 도구들 - 3. useMemo

최문길·2023년 12월 19일
0

react

목록 보기
11/14

useMemo란?

여기서 말하는 memo는 memoization을 뜻하며, 기억한다는 말이다. 무엇을 기억할까??


동일한 값을 반환하는 함수를 께속 호출해야 하면 필요 없는 렌더링을 한다고 볼수 있는데, 맨 처음 해당 값을 반환 할 때 그 값을 특별한 곳(메모리)에 저장한다. 이렇게 하면 필요할 때 마다 다시 함수를 호출해서 계산하는게 아니라 `이미 저장한 값` 을 단순히 꺼내와서 쓸 수 있는데, 보통 이러한 기법을 `캐싱한다` 라고 표현한다.

사용방법

// as-is
const value = 반환할_함수();

// to-be
const value = useMemo(()=> {
	return 반환할_함수()
}, [dependencyArray]);

dependency Array의 값이 변경 될 때만 반환할_함수()가 호출된다.

그 외의 경우에는 memoization 해놨던 값을 가져오기만 한다.

사용해보자

Case 1

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

function HeavyButton() {
  const [count, setCount] = useState(0);

  const heavyWork = () => {
    for (let i = 0; i < 1000000000; i++) {}
    return 100;
  };

	// CASE 1 : useMemo를 사용하지 않았을 때
  const value = heavyWork();//

	// CASE 2 : useMemo를 사용했을 때
  const value = useMemo(() => heavyWork(), []);

  return (
    <>
      <p>나는 {value}</p>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        누르면 count 가 올라간다. 
      </button>
      <br />
      {count}
    </>
  );
}

export default HeavyButton;

Case 2

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

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

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

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

  return (
    <>
      <div>
        이름은 {me.name}이고, 나이는 {me.age}.
      </div>
      <br />
      <div>
        <button
          onClick={() => {
            setIsAlive(!isAlive);
          }}
        >
          누르면 살았다가 죽었다함
        </button>
        <br />
        생존여부 : {me.isAlive}
      </div>
      <hr />
    //---------------
      <br />
      {uselessCount}
      <br />
      <button
        onClick={() => {
          setUselessCount(uselessCount + 1);
        }}
      >
        누르면 숫자가 올라간다
      </button>
    </>
  );
}

export default ObjectComponent;

신기하게도 useEffect hook을 이용해서 me의 정보가 바뀔 때 발동되게끔 dependency array를 넣었는데도 count를 증가하는 button을 눌러보면 계속 해서 콘솔이 찍힌다...

Q . Why...

A. uselessCount state 가 바뀌면 리렌더링이 된다.
-> 컴포넌트 함수가 새롭게 호출된다.
-> me 객체도 다시 할당이 된다.
-> useEffect의 dependency array에 의해 me 객체가 바뀌었는지 주소를 확인 하는데 당연히 새롭게 그려진 me 객체 이므로 useEffect가 실행된다.

이러한 상황에서 해결할 수 있는 것은

  • React.memo : 컴포넌트를 캐싱
  • useCallback : 함수를 캐싱
  • useMemo : 값을 캐싱

셋 중에서 당연히 객체도 값으로 정의 내릴 수 있으니

useMemo로 해결해보자

const me = useMemo(() => {
  return {
    name: "Ted Chang",
    age: 21,
    isAlive: isAlive ? "생존" : "사망",
  };
}, [isAlive]);

useMemo() 만 써주면, uselessCount 가 아무리 증가돼도 영향이 없게 된다.

0개의 댓글