useMemo 란
컴포넌트의 성능을 최적화시킬 수 있는 대표적인 react hooks 중 하나
useMemo 의 Memo 는 Memoization 을 뜻함
memoization이란
- 기존에 수행한 연산의 결괏값을 어딘가에 저장해 두고 동일한 입력이 들어오면 재활용하는 프로그래밍 기법
- 자주 사용되는 값을 캐싱해두어서, 필요할 때마다 다시 계산하는게 아니라, 재사용하는 것
함수형 컴포넌트에 대해
- 함수형 컴포넌트는
렌더링 -> component 함수 호출 -> 모든 내부 변수 초기화 과정을 거친다.
UseMemo 를 사용했을 때 함수형 컴포넌트 모습
const calculate = () => {
return 10
}
function App() {
const value = useMemo(() => {
calculate()
}, [])
return (
<div>
{ value }
</div>
);
}
1. 렌더링
2. component 함수 호출 (Memoization)
3. 렌더링
4. component 함수 호출 ( Memoize 된 값을 재사용 )
UseMemo 의 기본 구문
const value = useMemo(() => {return 계산하는 동작}, [item]);
1. 첫번째 인자인 콜백함수
: Memoization 해줄 값을 계산해서 리턴해주는 함수
2. 두번째 인자인 의존성 배열
: 배열 안에 요소의 값이 업데이트될 때만 콜백함수를 호출해준다.
빈 배열을 줄 때는, 처음 렌더링 될 때만 계산해서 Memoization 해준다.
useMemo 는 꼭 필요할 때만 !
- 값을 재사용하기 위해서 따로 값을 메모리에 저장해놓기 때문에, 너무 많이 사용하면 성능 저하가 될 수 있다.
useMemo 예제
const hardCalculate = (number) => {
console.log("어려운 계산!");
for (let i = 0; i < 999999; i++) {} // 오래 걸리는 계산
return number + 10000;
}
const easyCalculate = (number) => {
console.log("쉬운 계산!");
return number + 1;
}
function App() {
const [hardNumber, setHardNumber] = useState(1);
const [easyNumber, setEasyNumber] = useState(1);
const hardSum = useMemo(() => {
return hardCalculate(hardNumber)
},[hardNumber])
const easySum = easyCalculate(easyNumber)
return (
<div>
<h3>어려운 계산기</h3>
<input type="number" value={hardNumber} onChange={(e) => setHardNumber(parseInt(e.target.value))} />
<span> + 10000 = {hardSum}</span>
<h3>쉬운 계산기</h3>
<input type="number" value={easyNumber} onChange={(e) => setEasyNumber(parseInt(e.target.value))} />
<span> + 1 = {easySum}</span>
</div>
);
}
- 복잡한 계산을 하는 hardCalculate 함수는 useMemo 의 의존성 배열에 hardNumber 만 수정할 때 실행될 수 있도록 하였다
- easyCalculate 는 쉬운 계산이기때문에 useMemo 를 사용하지 않았다.

useEffect 와의 차이
useEffect 를 사용할 경우
- 원시 타입일 때
function App() {
const [number, setNumber] = useState(0);
const [isKorea, setIsKorea] = useState(false);
const location = isKorea ? "한국" : "외국"
useEffect(() => {
console.log("useEffect 호출")
}, [location])
return (
<div>
<h2>하루에 몇끼 먹어요?</h2>
<input
type="number"
value={number}
onChange={(e) => setNumber(e.target.value)}
/>
<hr />
<h2>어느 나라에 있어요?</h2>
<p>나라 : {location}</p>
<button onClick={() => setIsKorea(!isKorea)}>비행기 타자</button>
</div>
);
}
- useMemo 와 같이 의존성 배열에 있는 location 의 값이 변경될 때 실행된다.

- 객체 타입일 때
function App() {
const [number, setNumber] = useState(0);
const [isKorea, setIsKorea] = useState(false);
const location = {
country : isKorea ? "한국" : "외국",
}
useEffect(() => {
console.log("useEffect 호출")
}, [location])
return (
<div>
<h2>하루에 몇끼 먹어요?</h2>
<input
type="number"
value={number}
onChange={(e) => setNumber(e.target.value)}
/>
<hr />
<h2>어느 나라에 있어요?</h2>
<p>나라 : {location.country}</p>
<button onClick={() => setIsKorea(!isKorea)}>비행기 타자</button>
</div>
);
}
- useMemo 에 location 의 값이 변하면 실행되도록 했지만, input 의 number 값이 변해도 console.log 가 실행되는 모습이다.

원시 타입과 객체 타입

- 변수에 원시타입을 넣으면, 변수라는 상자에 바로 원시타입이 저장이 되는 반면에
객체 타입은 너무 커서, 어떠한 메모리 상의 공간이 할당되어서 그 메모리 안에 보관이 된다. 그리고 그 변수 안에는 그 메모리의 주소가 담긴다.

- 비교 연산자로 비교를 할 때, 차이점이 들어난다.
- 객체는 메모리의 주소가 서로 다르기 때문에, 다른 값이라고 나오게 된다.
객체 타입을 useMemo 로 사용하기
location 이 렌더링이 될 때마다 변수가 초기화되기 때문에, 주소가 계속 바뀐다.
그래서 이 상황을 막기 위해 useMemo 로 memoization 해주도록 한다.
function App() {
const [number, setNumber] = useState(0);
const [isKorea, setIsKorea] = useState(false);
const location = useMemo(() => {
return {
country : isKorea ? "한국" : "외국",
}
}, [isKorea])
useEffect(() => {
console.log("useEffect 호출")
}, [location])
return (
<div>
<h2>하루에 몇끼 먹어요?</h2>
<input
type="number"
value={number}
onChange={(e) => setNumber(e.target.value)}
/>
<hr />
<h2>어느 나라에 있어요?</h2>
<p>나라 : {location.country}</p>
<button onClick={() => setIsKorea(!isKorea)}>비행기 타자</button>
</div>
);
}
iskorea 의 값이 변화될때마다 location 의 값이 변경될 수 있도록 해주면, useEffect 를 사용할 때 location 의 값 변화를 인지할 수 있도록 됨.

'React > 이론공부' 카테고리의 다른 글
[React Hooks] useReducer (0) | 2023.01.25 |
---|---|
[React Hooks] useCallback (0) | 2023.01.25 |
[React Hooks] useContext & Context (0) | 2023.01.24 |
[React Hooks] useRef (0) | 2023.01.24 |
[React Hooks] useEffect (0) | 2023.01.24 |