본문 바로가기
React

React - useMemo

by 리슨업 2023. 12. 9.

 

useMemo

 

 

 

 


 

 

 

 

useEffect, useState만 으로도 CRUD 로 구현 CRUD 투두리스트, 달력 등 여러 기능을 구현 할 수 있다.구현 하는 것 외에도 백그라운드에서 성능관리하는 hook도 존재한다. 

 

성능관리의 이유는 뭔가 무거운 계산을 하는 함수나, 무거운 API, DB데이터 등을 리액트 특성 상 상태가 변경이 되면Rerendering 되는 특징이 있는데 이는 매우 큰 장점이나 불필요한 자원낭비하는 사이드이펙트를 가져올 수 있다.

 

이를 방지하기 위해 사용되는 훅으로 useMemo, useCallback Hook이 존재하며useMemo에 대해 포스팅을 해보겠다

 

 

 


 

 

"useMemo 란"

 

아래는 간단한 예제로

useEffect로 userObj를 의존하여 해당 객체 배열이 변경이 되면 'Data Change!!!'가 콘솔에 찍히도록 만든 예제이다.

function App() {
  const [value , setValue ] = useState('');
  const [boolean, setBulian ] = useState(false);
  const userObj = [
      {
        user : 'Squirrel'
      }
    ]
  
  useEffect(()=>{
    console.log('Data Change!!!');
  },[userObj]);

  const inputHandler = (e) =>{
      setValue(e.target.value);
  }

  return (
    <div className="app">
        {userObj[0].user}
        <input type="text" value={value} onChange={inputHandler} />
        <Button onClick={() => setBulian(!boolean)}>BTN</Button>
    </div>
  );
}

 

 

동적으로 할당되는 객체 배열이 아니기 때문에 변경되는 값는 고정 값이다.

예로  똑같은 구조의 userObj1 , userObj2 의 객체배열이 있다고 가정하면 userObj1 === userObj2 는 'true'라고 보통 예상을 하지만 false를 Return한다.

 

  const userObj1 = [
      {
        user : 'Squirrel'
      }
    ]
    
  const userObj2 = [
      {
        user : 'Squirrel'
      }
    ]

 

이유는 객체, 배열은 숫자와 같이 1 === 1(원시타입) 이면 데이터 타입을 검사하지만 객체, 배열의 경우는 객체타입으로 서로 참조 하고 있는 참조 값, 즉 메모리 주소를 비교한다. 

 

물론 Stringfly 해버리면 문자열 비교라 "True"를 유도 할 수 있겠지만..

 

그러므로 useEffect는 userObj 배열이 변경되었다고 판단하게 되고 "Data Change"를 지속적으로 랜더링 하게 된다.

이를 방지 하기위해서 useMemo 여기서 Memo는 메모리제이션( memoization )을 하는데 이는 이전에 계산 이나 초기화된 값을 주소값, 고정 메모리에 저장하고 의존성으로 지정된 배열이나 객체가 변경 되었을때만 다시 계산하도록

지정하는 것이다.

React에서는 [Dependency] , useEffec와 동일하게 의존성에 선언된 값이 변경이 될때 랜더링 된다.

 

"useMemo 의 사용"

  const [boolean, setBulian ] = useState(false);
  const userObj = useMemo(()=>{
    return [
      {
        user : 'squirrel309'
      }
    ]
  },[boolean])

 

useMemo에서 [boolean]을 위와 같이 의존한다고 하면 boolean 값이 변경이 되어야지만 userObj를 재 랜더링 한다. 

불필요한 사이드 이펙트가 사라지게 되는 것이다.

 

컴포넌트가 랜더링 되어도 값이 변경이 되지 않는 한 랜더링을 하지 않는다는 것은 

무거운 함수나 데이터를 불필요하게 랜더링 하지않아 자원낭비를 하지 않을 수 있으며 이는 곧 성능향상으로 이어지는

큰 장점이있다. 

 

 

난 처음에 그럼 useMemo를 전부 싹 도배해버리면 되지않나라는 생각했었는데 사람은 비슷한가보다 나랑 같은사람이검색해보니 인터넷에 널렸더라..

 

 

useMemo도 메모리 자원을 사용하여 지정한 값을 메모리 주소에 저장하는 것임으로 useMemo도 자원을 소비한다.불필요하게 useMemo를 남발하게되면 성능향상을 위한 hook이 성능 저하를 일으킬 수 있는 아이러니 상황이 나올 수도 있다. 

 

useMemo를 이용하여 성능을 향상시키려면 소규모의 어플리케이션에서는 성능 향상이 미비할 수 있으며,값이 변경되었을때만 재 계산이 되도록 유의하여 사용하면 효율적인 어플리케이션을 구축할 수 있을 것이다.