그렇기 때문에 배워야해..
참고한 포스팅의 글 첫머리에 지극히 공감을 하게 되었다.
이제
useState
와useEffect
에 완전히 익숙해졌다고 느꼈는데, 컴포넌트 내에서 저 두 개의 hook 만으로도 props나 state를 다루는 로직에 관련된 기본적인 기능을 모두 구현할 수 있기 때문에 굳이useMemo
나useCallback
을 사용할 필요를 느끼지 못했다.
게다가 나는 완전히는 더더욱 아니라서 최적화를 생각해보기엔 어려운 부분이 있었다.
하지만 쓰지도 않으면서 부르기만 하는건, 프로그램 입장에서도 좋지 않겠단(?)
생각에 최적화에 대한 생각도 해보기로 했다.
그럼에도 불구하고 사용해 볼 필요를 못 느낀다는 것이 그 기술의 장단점을 파악해서 결정한 것이 아니라 “단지 익숙하지 않은 기술을 배우지 않으려고 하는 나의 좁은 마음 때문” 이라는 생각이 스쳐지나갔다.
네, 바로 접니다...
그래서 이번 기회로 기술의 장단점을 정리하면서 사용법
을 익혀두기로 했다.
state
가 변하거나 부모에게서 받는 props
에 변동이 일어나면 렌더링이 일어난다.useMemo
, useCallback
를 사용한다. 말 그대로 이미 연산된 값을 메모해둠으로서 재사용하는 hook이다.
공식문서에 나와있는 사용법이다. (공식문서 보는 습관을 기르도록 하자)
useMemo
를 사용하게 되면, 모든 랜더링시의 고비용 계산을 방지하게 해준다.
아래 코드를 예로 들어보자면,
import React from "react";
const expensiveFunction = (prop) => {
// 에너지가 많이 소모되는 계산이 일어난다는 가정을 했을 때,
}
const ComponentRender = ({ prop1, prop2 }) => {
const valueProp1 = computeValueFromProp(prop1);
return (
<>
<div>{valueProp1}</div>
<div>{prop2}</div>
</>
);
};
이 경우에는 ComponentRender
함수가 랜더링 될 때마다
valueProp1
함수 또한 계속 랜더링 될 것이다.
그렇기에 변경되는 props
만을 감지해서 다시 계산할 수 있도록
useMemo
를 사용해서 성능최적화를 해보자.
import React from "react";
const expensiveFunction = (prop) => {
// 에너지가 많이 소모되는 계산이 일어난다는 가정을 했을 때,
}
const ComponentRender = ({ prop1, prop2 }) => {
const valueProp1 = useMemo(() => {
return computeValueFromProp(prop1);
}, [prop1]);
return (
<>
<div>{valueProp1}</div>
<div>{prop2}</div>
</>
);
};
이제 valueProp1
함수는 prop1
이 변경될때만 랜더링된다.
만약 prop2
가 변경되어 ComponentRender
함수가 리랜더링 될 경우엔
prop1
은 마지막으로 계산된 값을 사용하게 된다.
useMemo
가 계산된 '값'을 재사용한다면, useCallback
은 계산된 함수를 기억하고 재사용한다.
코드로 예를 들어보자면,
import React, { useState } from 'react';
const ComponentRender = ({ cb1, cb2 }) => {
const [state, setState] = useState(...);
const expensiveFunction = () => {
// 에너지가 많이 소모되는 계산이 일어남
...
setState(...);
cb1();
};
return (
<button onClick={expensiveFunction} />
);
};
이 경우엔 useMemo
와 동일하게,
컴포넌트의 랜더링이 일어나게 되면, 그 안에 있는 함수까지
다시 랜더링이 일어나게 된다.
그렇기 때문에 호출되지 않은 함수에 대해서는
계산의 낭비가 없도록 useCallback
을 사용한다.
import React, { useState } from 'react';
const ComponentRender = ({ cb1, cb2 }) => {
const [state, setState] = useState(...);
const expensiveFunction = useCallback(() => {
// 에너지가 많이 소모되는 계산이 일어남
...
setState(...);
cb1();
}, [cb1]);
return (
<button onClick={expensiveFunction} />
);
};
이렇게 deps
까지 설정해주게 되면,
cb1
함수에 대해서는, 변경이 일어나지 않는 한
쓸데없이 호출되지 않게 된다.
참고하였습니다 :)