[React] 최적화1 - useMemo : 함수의 결과값을 memorized

2022. 8. 4. 15:47React

1. 불필요하게 자꾸 호출되는 문제 발생 

  // 감정분석
  const getDiaryAnalysis = () => {
    console.log('감정분석')
    const goodCount = data.filter((item) => item.emotion >= 3).length;
    const badCount = data.length - goodCount;
    const goodRatio = (goodCount / data.length) * 100;
    return { goodCount, badCount, goodRatio }
  }
  
  const { goodCount, badCount, goodRatio } = getDiaryAnalysis();

 

감정을 계산하는 함수를 만들었는데, 우리가 일기를 수정할 때 마다 콘솔에 계속 찍히게 된다 ㄴㅇㄱ !!! 

근데 수정 하거나, 다른일을 할 때는 필요없는데 불필요하게 자꾸 호출이 된다. 

그래서 우리는 일기의 data.length 가 바뀔 때만 계산이 되어 감정점수가 나오면 되니깐 

이럴 때 useMemo를 사용할 수 있다. 

 

 

렌더링 최적화

기본적으로 react는 부모 component로부터 받는 state,props가 변동될 경우 rerendering 된다.

하지만 여기에는 분명한 문제가 존재한다.

더보기

예를들어 state,props가 여러가지라면?
state1, state2, state3이 존재하는 상태에서 state1을 변경시켜주었는데 state2, state3도 재계산된다면??
이것이 과연 좋은 rerendering일까??

 

 

 

2. useMemo

// 감정분석
const getDiaryAnalysis = useMemo(() => {
  console.log('감정분석')
  const goodCount = data.filter((item) => item.emotion >= 3).length;
  const badCount = data.length - goodCount;
  const goodRatio = (goodCount / data.length) * 100;
  return { goodCount, badCount, goodRatio }
}, [data.length]);

const { goodCount, badCount, goodRatio } = getDiaryAnalysis;

getDiaryAnalysis 는 더이상 함수가 아니라 값으로써 사용되는거 주의하자!

 

 

3. memoization

메모이제이션.

컴퓨터 프로그램이 동일한 계산을 반복해야 할 때,

이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술.

 

 

 

4. Vue의 computed속성

생각해보니,, vue에서 computed와 비슷한데 해서 검색해보니 역시나! 

Vue에서 data를 연산하는 방법으로 computed가 있다면, react에서는 useMemo를 사용할 수 있습니다. 

// Vue.js
<template>
	<div> {{ computedName }}  </div>
</template>

<script>
export default {
	computed: {
    	computedName() {
        	let myName = "yoy"
        	return myName.split('').reverse().join('');
        }
    }
}
</script>
// react.js
function App() {
	const myName = "yoy"
    
	const computedName = useMemo(()=>{
            return name.split('').reverse().join('');
        },[myName])
    
    return <div> { computedName } </div>
}

 

 

 

 

5. useMemo 예제

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

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

  // 1번 location
  const location = {
    country: isKorea ? "한국" : "일본"
  };

  // 2번 location
  // const location = useMemo(() => {
  //   return {
  //     country: isKorea ? '한국' : '일본'
  //   }
  // }, [isKorea])

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

  return (
    <header className="App-header">
      <h2>하루에 몇 끼 먹어요?</h2>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(e.target.value)}
      />
      <hr />

      <h2>내가 있는 나라는?</h2>
      <p>나라: {location.country}</p>
      <button onClick={() => setIsKorea(!isKorea)}>Update</button>
    </header>
  );
}

export default App;

useEffect의 의존성 배열에 location을 넣었는데 number state를 변경해도 useEffect가 실행된다.

그 이유는 자바스크립트에서 객체는 원시 타입과는 다르게 값이 저장될 때 주소 값으로 저장되기 때문이다.

그렇기 때문에 리액트에선 number state가 바뀌면 App 컴포넌트가 재호출되면서

location의 주소값이 변경이 되었기 때문에 location이 변경이 되었다고 인식을 한다.

여기서도 useMemo 훅을 통해 이를 방지할 수 있다.

위 식에서 주석을 통해 1번 location과 2번 location을 구분해놨으니

두개를 번갈아가며 사용해보면 어떤 차이가 있는지 확인할 수 있다.

 

1번코드 >  하루몇끼 먹어요, 내가 있는 나라는 둘다 변경

2번코드 > 내가 있는 나라만 클릭했을 때, 변경