[React] Memoization(useMemo, useCallback)

zzincode·2024년 3월 6일

React

목록 보기
14/20
post-thumbnail

Memoization(메모이제이션)

계산 결과를 메모리에 저장해두고 동일한 계산이 요청될 때 다시 계산하지 않고 저장된 값을 반환하는 최적화 기법

useMemo

함수 실행 결과값 리턴

import { useEffect, useState } from "react";
import "./styles.css";

export default function App() {
  const [number, setNumber] = useState(0);
  const [isKorea, setIsKorea] = useState(true);

  const location = {
    country: isKorea ? "한국" : "외국",
  };

  useEffect(() => {
    console.log("호출");
  }, [location]);

  return (
    <div className="App">
      <h2>하루에 몇끼?</h2>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(e.target.value)}
      />
      <h2>어느나라?</h2>
      <p>나라 : {location.country} </p>
      <button onClick={() => setIsKorea(!isKorea)}>비행기 타자</button>
    </div>
  );
}

useEffect는 location이 변할 때만 콘솔을 호출하고 있지만 위에 input이 바뀔 때도 콘솔이 출력됨

Why❓ 🤷‍♀️
변수에 원시 타입의 값을 넣으면 바로 들어가지만 (ex. const location = “korea”)
변수에 객체 타입의 값을 넣으면 메모리 상에 공간이 할당되어서 그 메모리 안에 보관 → 변수 안에는 그 메모리의 주소가 할당이 됨
그러므로 주소와 isKorea 값이 다르다고 판단하여 console이 렌더링될 때마다 출력되는 것!!

useEffect(() => {
    console.log("호출");
  }, [isKorea]);

으로 수정해주면 isKorea 값이 변경될때에만 useEffect가 작동하도록 한다!

useCallback

함수 리턴

import { useEffect, useState, useMemo } from "react";
import "./styles.css";

export default function App() {
  const [number, setNumber] = useState(0);

  const someFunction = () => {
    console.log(`someFunc : number : ${number}`);
  };

  useEffect(() => {
    console.log("someFunction 변경");
  }, [someFunction]);

  return (
    <div className="App">
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(e.target.value)}
      />
      <button onClick={someFunction}>Call someFunc</button>
    </div>
  );
}
  1. number의 state 변경 → App 컴포넌트 렌더링(state가 변경되어지면 컴포넌트는 렌더링되어진다)
  2. someFunction 초기화되며 함수 객체가 새로 생성 → 또 다른 메모리 공간에 저장되어지므로 메모리 주소가 변경되어짐
  3. useEffect는 주소가 변경되었으므로 someFunction이 변경되었다고 판단 → console 출력
    ⇒ 따라서 number state가 변하면 “someFunction 변경”이 계속 호출

💡 함수가 재생성되지 않도록 하기 위해 useCallback을 적용

const someFunction = useCallback(() => {
    console.log(`someFunc : number : ${number}`);
  }, []);

  useEffect(() => {
    console.log("someFunction 변경");
  }, [someFunction]);

해당 경우에는 버튼을 눌렀을 때 number의 값은 여전히 0으로 콘솔에 찍힌다
이유❗️ : useCallback된 함수의 number는 0인 상태로 메모이제이션이 된것이기 때문


const someFunction = useCallback(() => {
    console.log(`someFunc : number : ${number}`);
  }, [number]);

  useEffect(() => {
    console.log("someFunction 변경");
  }, [someFunction]);

따라서 의존성 배열안에 number를 넣어주면 배열안에 number가 변경될 때마다 useCallback속 함수가 계속 갱신될 것이다.

관련 영상
https://www.youtube.com/watch?v=e-CnI8Q5RY4
https://www.youtube.com/watch?v=XfUF9qLa3mU

0개의 댓글