React/React 개념 정리
React hook! 성능 개선을 위한 useMemo
Dev dreamer
2022. 10. 22. 13:19
useMemo
useMemo를 사용하면 함수 컴포넌트 내부에서 발생하는 연산을 최적화할 수 있습니다.
Memo를 통해서 리랜더링의 과정의 불필요한 액션이나 메모리를 아낄 수 있습니다.
import { useState } from "react";
const getAverage = numbers => {
console.log("평균값 계산 중");
if(numbers.length === 0) return 0;
// 배열의 각 요소를 순회하며 callback 함수의 실행 값을 누적하여 하나의 결과값을 반환 합니다.
const sum = numbers.reduce((a, b) => a + b);
return sum / numbers.length;
};
const Average = () => { // 컴포넌트 이름은 대문자
const [list, setList] = useState([]);
const [number, setNumber] = useState('');
const onChange = e => {
setNumber(e.target.value);
};
const onInsert = e => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
};
return (
<div>
<input value={number} onChange={onChange} />
<button onClick={onInsert}>등록</button>
<ul>
{list.map((value, index) => <li key={index}>{value}</li>)}
</ul>
<div>
<b>평균값 : </b> {getAverage(list)}
</div>
</div>
);
};
export default Average;
위의 코드를 실행시켰을때 관리자 모드에서 보면
평균값을 구할때 list에 기록된 값으로 평균값을 구하는 getAverage 함수만 작동하면 되는데 계속 키를 하나 입력 할 때마다 getAverage 함수가 작동이 된다. 엄청난 성능의 낭비를 가져오는 것이다.
이를 보완하기 위해 useMemo 훅을 사용하는데. useEffect의 의존성 배열 기능을 한번더 생각해 보면 좋을듯 싶다.
useEffect 는 어떠한 랜더링이 작동했을때 특정한 동작을 하도록 만든 함수인데 의존성 배열을 통해서 특정한 동작만 작동하게 하거나 처음 화면이 켜질때 작동하도록 해서 성능을 향상시켰다.
즉 useEffect 는 본인의 행동 범위를 설정했다면!
useMemo는 다른 함수가 특정한 기능에서만 혹은 특정한 변화에서만 작동하도록 세팅이 가능한 것이다.!
//useMemo ? 컴포넌트의 최적화를 위한 Hook(불필요한 렌더링을 막음)
import { useState, useMemo } from "react";
const getAverage = nums =>{
console.log("평균 값 계산 중....")
if(nums.length === 0) return 0;
// 배열의 각 요소를 순회하면서 함수의 실행결과를 누적하여 하나의 결과값을 반환
const sum = nums.reduce((a,b) => a+b);
return sum / nums.length;
}
const Memo =() =>{
const [list, setList] = useState([]);
const [number, setNumber] =useState('');
const onChange = e =>{
setNumber(e.target.value);
}
const onInsert = e => {
// concat 은 기존의 배열을 그대로 놔두고 새로 만드는 것.
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
}
// 의존성 배열을 붙여서 list 가 바뀔때만
// 계속 반복되는 함수의 작동을 방지하고자 그 함수 대신에 useMemo로
// 의존성 함수의 기능을 추가 시켜준 값을 대신 넣어준다.
//avg 에는 두값이 들어감, 내가 호출해야하는 함수 , 의존성함수
const avg = useMemo(() =>getAverage(list) , [list])
return(
<div>
<input value = {number} onChange = {onChange} />
<button onClick={onInsert}>등록</button>
<ul>
{list.map((value, index) => <li key={index}>{value}</li>)}
</ul>
{/* useMemo를 통해 만든 avg를 기존에 있던 getAverage(list) 대신에 넣는다. */}
<p><b>평균값 : </b>{avg} </p>
</div>
);
};
export default Memo;
딱 봐도 위의 영상을 비교해 봤을때 관리자 창이 훨씬 편안하게 작동하고 있음을 알 수 있다.
변화된 코드는
const avg = useMemo(() =>getAverage(list) , [list])
//avg에 getAverage 함수의 기능을 부여함과 동시에 의존성 배열을 두어
//list 가 변화할 때에만 getAveraget(list)의 기능이 작동하게 했다.
//그래서 return 문 안에 들어있는
getAverage(list) 대신 avg를 넣어 사용한다.
<p><b>평균값 : </b>{getAverage(list)} </p>
<p><b>평균값 : </b>{avg} </p>
다음과 같이 바뀐다.
useEffect 를 배울때 의존성 배열로 본인의 일부 필요한 기능만 작동하게 했던것에 유용하다고 느꼈었는데
useMemo는 다른 함수의 기능을 딱 필요한 기능만 하게끔 설정한다는 점에서 많이 쓰이는 기능일 듯 싶다.