memo
React.memo는 고차 컴포넌트(HOC)이다.
const Component = React.memo(function Component(props) {
/* props.흠냐흠냐 */
});
만약 컴포넌트가 동일한 props를 받아 동일한 결과를 렌더링하는 경우, React.memo를 사용하여 몇몇 경우에서 메모화된 결과를 이용하여 성능 향상을 이룰 수 있다. 이 경우 React는 컴포넌트 렌더링을 건너 뛰고 마지막으로 렌더링된 결과를 재사용한다.
이때 React.memo는 오직 props의 변화만 얕은 비교(shallow compare)를 한다. 문서에도 나와있지만 이 함수는 성능 최적화 용도로만 사용해야지, 렌더링 방지용으로는 사용하지 말자. 버그가 발생할 수 있으니 정말 앱이 느려지는 것을 발견하거나 아주 많은 목록을 렌더링할 때만 고려해 보고 도입하자.
+실제로 메모를 사용하여 성능 향상을 느낄 수 있는 부분은 상당히 적지만, 또 하나의 장점이 존재한다. 바로 props를 비교 함수를 통해 직접 비교하여 컴포넌트의 렌더링 시기를 정확하게 선택할 수 있다는 점이다.
물론 이것을 위해 memo를 쓰진 말자. 그냥 참고용이다.
useMemo
useMemo의 경우 React 컴포넌트 내부에서 사용되며, 메모된 값을 반환한다.
useMemo는 React.memo와 달리 종속성을 처리한다. 즉 React.memo는 두번째 인자로 비교 함수를 받지만, useMemo의 경우 함수 대신 종속성 배열을 받아, 종속성 배열의 변경 사항을 체크하여 값이 변경된 경우에만 함수를 다시 실행하며 새 메모화된 값을 가져온다.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useCallback
값을 메모하는 useMemo와 달리 함수를 메모한다. useMemo의 경우 인자를 받아 값을 반환하는 비용이 많이 드는 코드가 있는 경우 사용하여, 렌더링 간이 계산 비용이 많이 드는 코드를 다시 실행하지 않고 해당 값을 계속 참조할 수 있다.
반면 useCallback은 렌더링 간에 지속되는 함수가 필요한 경우 함수의 해당 인스턴스를 기억할 수 있게 하기 위해 필요한다. 이는 컴포넌트 밖에서 함수를 만드는 것과 비슷하다고 생각할 수 있으며, 코드가 리렌더링될 때, 함수도 유지되게 된다.
const [sec, setSec] = useState(0);
const nextSec1 = useMemo(() => sec + 1, [sec]);
const nextSec2 = useCallback(() => sec + 1, [sec]);
nextSeconds1에서 useMemo가 기억하고 있는 것은 1이다.
nextSeconds2에서 useCallback이 기억하고 있는 것은 () => seconds + 1이다.