🪛

[React] useMemo, useCallback


알아야 하는 것

  1. 함수형 컴포넌트는 jsx를 반환하는 함수일 뿐이다

  2. 컴포넌트가 렌더링 된다는 것은 누군가가 그 함수(컴포넌트)를 호출하여서 실행되는 것을 말한다

  3. 컴포넌트는 자신의 state가 변경되거나, 부모에게서 받는 props가 변경되었을 때마다 리렌더링 된다

useMemo

일단 세 번째 항목에 주목해보자.

s1, s2, s3, 세 개의 state가 있는 컴포넌트가 있다. 이 state들은 서로 다른 함수로 각각 값을 계산한 후 보여준다. 여기서 s1을 변경시키면 다른 함수도 모두 계산된다.

예제 코드를 보자!

1const getColorKor = color => {
2 console.log("getColorKor");
3 switch (color) {
4 case "red":
5 return "빨강";
6 case "orange":
7 return "주황";
8 case "yellow":
9 return "노랑";
10 default:
11 return "검정";
12 }
13};
14
15const getDrinkKor = drink => {
16 console.log("getDrinkKor");
17 switch (drink) {
18 case "soju":
19 return "소주";
20 case "beer":
21 return "맥주";
22 case "wine":
23 return "와인";
24 default:
25 return "전부 다!";
26 }
27};
28
29
30const App = () => {
31 const [color, setColor] = useState("");
32 const [drink, setDrink] = useState("");
33
34 const colorKor = getColorKor(color);
35 const drinkKor = getDrinkKor(drink);
36
37 return (
38 <div>
39 <input
40 name="color"
41 value={color}
42 onChange={(e) => setColor(e.target.value)}
43 />
44 <input
45 tname="drink"
46 value={drink}
47 onChange={(e) => setDrink(e.target.value)}
48 />
49 <div>
50 제가 가장 좋아하는 색은 {colorKor} 이고, <br />
51 즐겨 마시는 술은 {drinkKor} 입니다.
52 </div>
53 </div>
54 );
55};
56
57export default App;

이 코드에서 color의 값만 바꿔보면 로그의 결과로 getColorKorgetDrinkKor 둘 다 찍히는 것을 볼 수 있다. 변경하고자 하는 state에 의존성이 없는 함수도 다시 실행되니 너무 비효율적이다. 이럴 때 useMemo를 사용할 수 있다. useMemo메모이제이션된 값(memoized value)을 반환한다. 특정 결과 값을 재사용하는 것이다.

state에 의존성이 있는 함수에 useMemo를 적용해보자.

1const colorKor = useMemo(() => getColorKor(color), [color]);
2const drinkKor = useMemo(() => getDrinkKor(drink), [drink]);

color의 값을 변경하면 color의존성 있는 함수만 다시 실행되는 것을 확인할 수 있다.

메모이제이션 된 값의 재계산이 expensive, 즉 복잡하고 계산량이 많은 경우 useMemo의 성능을 극대화 시킬 수 있을 것이다.

useCallback

useMemo메모이제이션 값을 반환한다면, useCallback메모이제이션 된 함수를 반환한다. 즉, 함수를 재선언하지 않고 재사용하는 것이다.

리렌더링 시에 props나 state에 의존적이지 않고, 받게 되는 parameter에 따라 계산한 값만 반환하는 함수를 다시 재선언할 필요는 없을 것 같다. 여기서 useCallback을 사용하면 첫 마운트 때만 선언하고 함수를 재사용할 수 있다.

하위 컴포넌트가 useMemo 같은 것으로 최적화 되어 있고 그 하위 컴포넌트에게 callback 함수를 props로 넘길 때, 상위 컴포넌트에서 useCallback 으로 함수를 선언하는 것이 유용하다. 함수가 매번 재선언되면 하위 컴포넌트는 넘겨 받은 함수가 달라졌다고 인식하기 때문이다.


참조: