useMemo?
- 이전에 연산된 값을 기억해놓았다가 재사용하는 Hook.
useMemo 사용법
useMemo(() => {
실행할 함수 문장
}, [의존성 배열]);
- 이때, 의존성 배열은 변화를 감지할 변수들의 목록
예제로 알아보기
예제 코드
import React, { ChangeEvent, useMemo, useState } from 'react';
/**
* 부모 컴포넌트의 값을 내려받아 UI에 뿌려주는 자식 컴포넌트
* @param propName 부모로부터 받은 이름
* @param propAge 부모로부터 받은 나이
*/
function ChildrenComponent({ propName, propAge }: { propName: string; propAge: number }) {
const getName = (name: string) => {
console.log('name 변경 : ', name);
return name;
};
const getAge = (age: number) => {
console.log('age 변경 : ', age);
return age;
};
const showName = getName(propName);
const showAge = getAge(propAge);
return (
<div>
{showName}님 {showAge}살
</div>
);
}
/**
* 부모 컴포넌트
*/
function UseMemoExample() {
const [name, setName] = useState('');
const [age, setAge] = useState(0);
return (
<div>
<input value={name} onChange={(e) => setName(e.target.value)} />
<input value={age} onChange={(e) => setAge(+e.target.value)} />
<ChildrenComponent propName={name} propAge={age} />
</div>
);
}
export default UseMemoExample;
- 부모 컴포넌트(<UseMemoExample/>)에서는, <input/>을 통해 useState 변수 name과 age를 업데이트.
- name과 age를 자식컴포넌트인 <ChildrenComponent/>에 prop으로 내려준다. (propName, propAge)
- 자식컴포넌트에서, getName()과 getAge()를 통해,
prop으로 받은 name과 age를 내려받을 때마다 console.log를 찍고,
값을 그대로 return.
문제 상황
- <input/>으로 이름(name)만 바꿨는데, 값(상태)의 변화가 전혀 없는 age도 함께 재렌더링되면서 함께 log가 찍힘.
- 이는, 불필요한 자원 낭비. === 굳이 age는 렌더링 하지 않아도 된다.
해결
- useMemo() hook을 사용!
- 앞선 코드에서 //here ! 주석 표기된 부분을 다음과 같이 교체
const showName = useMemo(() => getName(propName), [propName]);
const showAge = useMemo(() => getAge(propAge), [propAge]);
- 따라서, name과 age 각각의 값(상태)을 기억(memoization)해두었다가, 변화가 없다면 재렌더링을 수행하지 않음.
- 값(상태)의 변화가 있을 때만 재렌더링을 수행하기 때문에 성능적으로 유리.
주의점
- 모든 경우에 성능적으로 유리한 것은 아님.
- 값을 기억해야 하기 때문에, 별도의 공간(메모리)가 필요함.
- 따라서, 변화가 거의 없는 값이나 불필요한 값들의 메모이제이션(memoization)은 결과적으로 성능저하를 유발.
- useMemo()는 마구 남발하지 않고, 꼭 필요한 경우에만 사용해야한다!