프론트엔드/React

[React] Memoization과 useMemo 사용법

s_omi 2024. 1. 28. 12:40
728x90
반응형
SMALL

useMemo

React Hooks 중에 하나로서 컴포넌트 성능 최적화를 위해 사용한다. 

성능 최적화를 위해 사용하는 Hooks에는 useCallback도 있다. 

 

[React] useCallback 사용한 성능 최적화

useCallback React Hooks 중 하나로서 useMemo와 같이 Memoization 기법으로 컴포넌트 성능을 최적화시키는 방법이다. useMemo나 memoization을 모른다면 아래의 링크를 통해 꼭 보고 오자! [React] 성능 최적화를 위

mi-dairy.tistory.com

 

useMemo에서 Memo는 Memoization을 뜻하는데

이때 Memoization이란 동일한 값을 리턴하는 코드를 반복적으로 호출해야 할 때 제일 처음 호출했을 때 해당 값을 메모리에 저장해서 필요할 때마다 메모리에서 꺼내 사용하는 기법을 말한다. 

 

 

사용법

useMemo는 첫 번째 인자로는 콜백함수, 두 번째 인자로는 의존성 배열을 받아 총 두 개의 인자를 받는다. 

const result = useMemo(() => {
  return add();
}, [value]);

 

첫 번째 인자인 콜백 함수가 return 하는 값이 바로 useMemo가 return 하는 값, 즉 result의 값이 된다.


두 번째 인자인 의존성 배열은 배열 안의 요소가 업데이트될 때마다 useMemo의 콜백 함수를 재실행시킨다. 콜백 함수를 재실행시킴으로써 메모리에 저장된 값은 업데이트되어 메모리에 새로 저장된다. 

빈 배열일 경우 제일 처음 마운트될 때만 값을 메모리에 저장하고 그 이후엔 메모리에 있는 값만 불러오게 된다.

 

 

사용 이유

function Example() {
  const result = add();

  return <div>{value}</div>
}

function add() {
  return 1 + 2;
}

 

위와 같은 경우 함수 컴포넌트인 Example이 렌더링 될 때마다 add라는 함수를 계속해서 호출시키게 된다. 렌더링 될 때마다 모든 내부 변수들은 초기화되고 add 함수의 결과도 렌더링 될 때마다 똑같은 값인 3을 반환하는데 만약 add 함수가 오래 걸리는 일을 맡고 있다면 Example 컴포넌트 하나를 렌더링 하는데 많은 시간이 소요될 것이다.

 

 

function Example() {
  const result = useMemo(() => 
    add()
  , []);
    
  return <div>{value}</div>
}

 

이때 다음과 같이 useMemo를 사용하여 코드를 수정해준다면 함수 컴포넌트인 Example이 렌더링되어 add 함수를 처음 호출했을 때의 결과값을 메모리에 저장한다. 그 후 또 컴포넌트가 렌더링 되었을 경우 add 함수를 다시 호출하지 않고 이전에 저장된 결과값을 재사용하여 불필요한 호출을 없애준다. 

 

 

! 알아두어야 할 점

타입에는 원시 타입인 String, Number, Boolean 등과 객체 타입인 Object, Array 등으로 나뉘어진다.

 

원시 타입인 변수에 값을 넣으면 변수에 바로 값이 저장된다.

하지만 객체 타입인 변수에 객체를 넣으면 변수에 바로 저장되지 않고 메모리 상의 공간이 할당되어 메모리 주소 안에 객체가 저장되고 변수에는 메모리 주소가 저장된다. 

 

때문에 변수명이 다른 2개의 변수에 같은 문자열(또는 숫자) 값을 저장하면 일치 비교 연산자(===)를 실행했을 때 true가 return 된다.

하지만 변수명이 다른 2개의 변수에 같은 객체 값을 저장하면 일치 비교 연산자(===)를 실행했을 때 false가 return 된다. 이것은 우리의 눈으로 본 객체의 모양이 같을 지라도 변수에는 각각 다른 메모리 주소가 할당되어 있어 주소는 같지 않으므로 false가 나오는 것이다. 

 

 

사용 예시

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

function App(){
  const [age, setAge] = useState(0);
  const [complete, setComplete] = useState(true);
    
  const whether = {
    state: complete? '취소' : '완료',
  }
    
  useEffect(() => {
    console.log('useEffect !!');
  }, [whether]);
    
  return(
    <div>
      <input 
        type="number" 
        value={age} 
        placeholder="나이를 입력하세요." 
        onChange={(e) => setAge(e.target.value)} 
      />
      <button onClick={() => setComplete(!complete)}>{whether.state}</button>
    </div>
  );
}

export default App;

 

다음과 같은 코드를 실행시키면 useEffect의 의존성 배열로 whether만 넣었음에도 불구하고 age를 변경할 때도 console.log()가 찍히는 것을 볼 수가 있다. 

이것은 위에 설명하다싶이 whether가 객체 타입이라 age가 변경될 때(렌더링이 될 때)마다 새로운 메모리 주소가 생성되어 의존성 배열로 넣은 whether의 값(메모리 주소 값)이 달라져 useEffect가 계속해서 실행되는 것이다. 

 

이를 객체 타입을 사용했어도 age를 변경할 때가 아닌 whether의 값만 변경될 때 useEffect가 실행되게 수정하려면 useMemo를 활용하여 다음과 같이 수정하면 된다.

const whether = useMemo(() => {
  return {
    state: complete? '취소' : '완료',
  };
}, [complete]);

 

 

 

 


출처 : 유튜브 별코딩 (직접 듣기 강추!)

728x90
반응형
LIST