💫

6.3 (실습1) useMemo 사용해보기

 
이번 챕터에서는 예제를 통해 useMemo를 사용해보겠습니다. 해당 예제는 무거운 연산을 실행하면서 숫자와 텍스트를 변경하는 코드입니다. App.jsx에서는 화면이 렌더링 될 때마다 heavyCalc 함수를 실행하며 number와 text를 바꿔주는 함수 핸들러, 그리고 바뀐 number와 text값을 보여주는 ShowState 컴포넌트가 있습니다.
 
import React, { useState,useMemo } from 'react'; import ShowState from './ShowState'; export default function App() { const [number, setNumber] = useState(0); const [text, setText] = useState(''); // 무거운 연산을 실행하는 함수 function heavyCalc() { let s = 0; for (let i = 0; i < 1000000000; i++) { s += i; } return s; } let calc = heavyCalc(); // number 값 바꿔주는 함수 const increaseNum = () => { setNumber((prev) => prev + 1); }; const decreaseNum = () => { setNumber((prev) => prev - 1); }; // text값 바꿔주는 함수 const handleText = (e) => { setText(e.target.value); }; return ( <> <h4> ✨ 엄청난 연산값</h4> <p>{calc}</p> <h4> ✨ 숫자바꾸기</h4> <button onClick={increaseNum}>+</button> <button onClick={decreaseNum}>-</button> <h4> ✨ 글자바꾸기</h4> <input type="text" onChange={handleText} /> <ShowState number={number} text={text} /> </> ); }
App.jsx
 
ShowState 컴포넌트에서는 App.jsx에서 바꾼 값들을 출력해주고 값이 바뀔 때 마다 '숫자가 변경되었습니다.' 와 '글자가 변경되었습니다.' 라는 문구를 콘솔에 출력합니다.
 
import React, { useMemo } from 'react'; export default function ShowState({ number, text }) { const consoleNumber = (number) => { console.log('숫자가 변경되었습니다.'); return number; }; const consoleText = (text) => { console.log('글자가 변경되었습니다.'); return text; }; const showNum = consoleNumber(number); const showText = consoleText(text); return ( <div> <p> 숫자 : {showNum}</p> <p> 글자 : {showText}</p> </div> ); }
ShowState.jsx
 
notion imagenotion image
 
위 예제를 실행하면 이런 모습입니다. +- 버튼을 누르면 숫자 값이 바뀌고, input창에 글자를 입력하면 입력하는대로 글자가 출력되는 것을 알 수 있습니다. 이를 실행해보면 매우 느리게 실행되는데, 이는 숫자나 글자를 바꿈으로써 화면이 리렌더링될 때마다 heavyCalc 함수가 실행되기 때문입니다.
하지만 heavyCalc 함수의 결과값인 calc는 계속 같은 값을 가지기 때문에 매번 새로 연산을 할 필요가 없습니다. 이 때 쓸 수 있는 것이 이전에 이미 계산한 값을 재사용할 수 있도록 도와주는 훅이  useMemo 입니다.
 
App.jsx의 heavyCalc 함수 실행문을 이렇게 useMemo를 이용하여 감싼다면 어떻게 될까요?
 
const calc = useMemo(() => { return heavyCalc(); }, []);
 
useMemo를 통해 이전에 계산했던 499999999067109000 라는 값을 계속 재사용하여 화면에 출력해주기 때문에 같은 계산을 위해 부하를 일으키지 않는 것을 확인할 수 있습니다.
이처럼 useMemo는 렌더링이 발생했을 때, 이전 렌더링과 현재 렌더링 사이에 값이 동일하다면 다시 함수를 호출을 하여 결과를 구하는 대신, 기존에 메모리에 저장해두었던 값을 그대로 사용하도록 도와줍니다.
 
이제 불필요한 계산을 하지 않게 되었으니 다시 값을 변경해볼까요?
notion imagenotion image
increaseNum 함수를 두번 실행하여 숫자가 2가 되었습니다. 하지만 콘솔창을 확인하니 increaseNum 함수가 실행될 때마다 Text값을 바꾸지 않았음에도 '글자가 변경되었습니다.' 라는 문구가 같이 출력된 것을 확인할 수 있습니다.
변경하고자 하는 state에 해당되지 않는 함수가 실행될 필요는 없기 때문에 useMemo를 사용하여 숫자가 변경될 경우와 글자가 변경될 경우에만 각각 그에 맞는 console 출력을 하도록 해보겠습니다.
 
const showNum = useMemo(() => consoleNumber(number), [number]); const showText = useMemo(() => consoleText(text), [text]);
showNum과 showText 값을 이렇게 변경하여 number 값이 변했을때만 consoleNumber 함수가, text값이 변했을때만 consoleText함수가 실행되도록 합니다.
notion imagenotion image
이전처럼 increasNum 을 두 번 실행했을 때 text의 값을 변경하지 않았으므로 consoleNumber 함수만 두 번 실행되는 것을 확인할 수 있습니다.
 
notion imagenotion image
이 상태에서 text의 값을 다섯 번 변경하면 consoleText함수도 다섯 번 실행되는 것을 알 수 있습니다.
즉, 숫자가 변경될 때는 ‘숫자가 변경되었습니다.’ 라는 console만 출력되고, 글자가 변경될 때는 '글자가 변경되었습니다.' 라는 console만 출력됩니다.
이처럼 useMemo 를 사용하면 메모이제이션 기법을 이용하여 이전에 저장되었던 결과를 다시 가져와 재사용할 수 있기 때문에 코드 최적화에 도움을 줄 수 있습니다.