react에서는 컴포넌트의 상태가 업데이트되면, 부모 컴포넌트의 하위 자식 컴포넌트들은 함께 리렌더링 된다.
그런데 너무 많은 리렌더링이 이루어지게 되면 앱의 성능이 떨어지게 되는데 이럴때 최적화시키는 방법 이 useMemo와 useCallback 이라는 Hook 함수들이다.
import { useMemo } from "react";
function Calculator({value}){
const result = useMemo(() => calculate(value), [value]);
return <>
<div>
{result}
</div>
</>;
}
calculate
함수의 계산값을 useMemo
를 사용해 값을 저장(메모) 해 두면, 이 Calculator 함수가 리렌더링 되더라도 value 값이 동일하면, calculate
함수를 다시 실행하는 불필요성을 막을 수 있다.
import React, { useCallback } from "react";
function Calculator({x, y}){
const add = useCallback(() => x + y, [x, y]);
return <>
<div>
{add()}
</div>
</>;
}
useCallback
의 첫번째 인자로 콜백함수를 호출하고, 두번째 인자로 함수에서 사용되는 state들을 넣으면 동작한다. 단순히 useCallback
를 함수를 사용하는데에 사용하는 것은 최적화에 큰 효과를 내지 않는다. 하지만, 자식 컴포넌트의 props로 함수를 전달해 줄 때 useCallback
을 사용하기 좋다.
useCallback 의 참조 동등성
자바스크립트의 함수는 매 선언과 할당마다 다른 메모리 주소 객체에 함수를 할당한다.
동일한 두 함수를 다른 변수에 할당을 하면, 할당된 메모리의 주소값은 서로 다르기에 완전히 동치하지 않는다.const add = (x,y) => x+y; const a = add(); const b = add(); a(1,1); b(1,1) a === b // false
허나 useCallback을 사용하는 경우 하나의 메모리 안에서 함수를 불러와 재사용하기 때문에 완전히 동치하는 주소값을 얻을 수 있고, 이게 아주 좋은게 자식 컴포넌트에서 불러오더라도 동치하는 함수를 불러올 수 있기 때문에 React 컴포넌트 함수 내에서 다른 함수의 인자로 넘기거나 자식 컴포넌트의 prop으로 넘길 때 예상치 못한 성능 문제를 막을 수 있다.