๐Ÿค” ๊ฐ„๋‹จํ•œ memo useMemo useCallback ์‚ฌ์šฉ ์ด์œ 

KHWยท2022๋…„ 4์›” 24์ผ
1

React

๋ชฉ๋ก ๋ณด๊ธฐ
7/7

๊ฐ„๋‹จํ•œ ์ฝ”๋“œ 2๊ฐœ

  • App.js
import { useEffect, useState } from "react";
import AppChild from "./AppChild";

const App = () => {
  const [count, setCount] = useState(0);
  const clickIncrease = () => {
    setCount(count + 1);
  };

  console.log("App rendering");

  useEffect(() => {
    console.log("App useEffect ");
  }, []);

  const clickChild = () => {
    console.log("clickChild");
  };

  return (
    <div>
      <button onClick={clickIncrease}></button>
      <AppChild clickAppChild={clickChild}></AppChild>
    </div>
  );
};

export default App;
  • AppChild.jsx
import { useEffect, useState } from "react";

const sum = (n) => {
  console.log("sum calculate start");
  let result = 0;
  for (let i = 1; i <= n; i += 1) {
    result += i;
  }
  console.log("sum calculateend");
  return result;
};

const Child = ({ clickChild }) => {
  const [sumNum, setSumNum] = useState(100000000);
  const result = sum(sumNum);
  console.log("Child rendering");
  useEffect(() => {
    console.log("Child useEffect ");
  }, []);

  return <div onClick={clickChild}>child , {result}</div>;
};

export default Child;

์ฝ”๋“œ์„ค๋ช…

App์ปดํฌ๋„ŒํŠธ๋Š” ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ƒํƒœ๊ฐ’ count๊ฐ€ ์ฆ๊ฐ€ํ•˜๋Š”๊ฒƒ์ด ์žˆ๊ณ 
AppChild์—์„œ ๋ฐ›์•„ ์ด๋ฒคํŠธ๋ฅผ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์ธ App์—์„œ ๋™์ž‘ํ•˜๊ฒŒํ•˜๋Š” clickChild ๊ฐ€ ์žˆ๋‹ค.

AppChild์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” click ์ด๋ฒคํŠธ๊ฐ€ ์žˆ๊ณ  ์ด๋ฅผ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ ์˜ฌ๋ ค์ฃผ๋Š” clickChild๊ฐ€ ์žˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  sumํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด result๊ฐ€ ์กด์žฌํ•œ๋‹ค.

์‹คํ–‰๊ฒฐ๊ณผ๋ณด๊ธฐ

๊ธฐ๋ณธ์ ์ธ ์ดˆ๊ธฐ ์ฝ˜์†” ๊ฒฐ๊ณผ์ด๋‹ค.
App ์ฝ˜์†”์ถœ๋ ฅ -> return์˜ AppChild์„ ๋งŒ๋‚˜ AppChild ์ปดํฌ๋„ŒํŠธ ์ฝ”๋“œ์‹คํ–‰ -> AppChild ์ปดํฌ๋„ŒํŠธ์˜ sum ์‹คํ–‰ -> AppChild ์ฝ˜์†”์ถœ๋ ฅ -> AppChild๊ฐ€ ๋ Œ๋”๋ง์ด๋˜๋ฉด useEffect ์‹คํ–‰ ๋ฐ ์ฝ˜์†” ์ถ”๊ฐ€ -> App์ด ๋ Œ๋”๋ง์ด๋˜๋ฉด useEffect ์‹คํ–‰ ๋ฐ ์ฝ˜์†” ์ถ”๊ฐ€

๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ฒŒ ๋œ๋‹ค๋ฉด(2๋ฒˆ์‹คํ–‰) App๊ณผ Child ๋ชจ๋‘ ๋ฆฌ๋ Œ๋”๋ง๋œ๋‹ค.
์šฐ๋ฆฌ๋Š” count๊ฐ’์€ Child์™€ ์—ฐ๊ด€์ด ์—†๋Š”๋ฐ๋„ ๋‹จ์ง€ ๋ถ€๋ชจ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋œ๋‹ค๋Š” ์ด์œ ๋กœ ๊ฐ™์ด ๋ Œ๋”๋ง๋œ๋‹ค. ์ด๋กœ์ธํ•ด sum ํ•จ์ˆ˜ ๋˜ํ•œ ์‹คํ–‰๋œ๋‹ค.

useMemo ์‚ฌ์šฉํ•˜๊ธฐ

sum ํ•จ์ˆ˜๋Š” ๋‹จ์ง€ ์˜ํ–ฅ์„ ๋ฐ›๋Š” sumNum ์— ์˜ํ•ด์„œ๋งŒ ์‹คํ–‰๋˜๊ฒŒ ํ•˜๊ณ  ์‹ถ๋‹ค.
ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด๋ณธ๋‹ค.

  const result = useMemo(() => sum(sumNum), [sumNum]);

2๋ฒˆ ํด๋ฆญ์„ ๋ˆŒ๋ €์„ ๋•Œ AppChild์˜ sumํ•จ์ˆ˜๋Š” sumNum์˜ ๊ฐ’์ด ๋ฐ”๋€Œ์ง€์•Š๋Š” ์ด์ƒ ํ•˜์ง€์•Š์•„ ๋ถˆํ•„์š”ํ•œ sumํ•จ์ˆ˜์˜ ์‹คํ–‰๊ณผ ๊ด€๋ จ๋œ ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

memo ์‚ฌ์šฉํ•˜๊ธฐ

์ž ์‹œ ์ฝ”๋“œ์—์„œ ์ด๋ฒคํŠธ๋ฅผ props๋กœ ์ฃผ๋Š” ์ฝ”๋“œ๋ฅผ ์•„๋ž˜์™€๊ฐ™์ด ์ƒ๋žตํ•ด๋ณด์ž

  • App.js
import { useEffect, useState } from "react";
import AppChild from "./AppChild";

const App = () => {
  const [count, setCount] = useState(0);
  const clickIncrease = () => {
    setCount(count + 1);
  };

  console.log("App rendering");

  useEffect(() => {
    console.log("App useEffect ");
  }, []);

  // const clickChild = () => {
  //   console.log("clickChild");
  // };

  return (
    <div>
      <button onClick={clickIncrease}></button>
      <AppChild></AppChild>
    </div>
  );
};

export default App;
  • AppChild.jsx
import { useEffect, useState, useMemo } from "react";

const sum = (n) => {
  console.log("sum calculate start");
  let result = 0;
  for (let i = 1; i <= n; i += 1) {
    result += i;
  }
  console.log("sum calculateend");
  return result;
};

const Child = () => {
  const [sumNum, setSumNum] = useState(100000000);
  const result = useMemo(() => sum(sumNum), [sumNum]);
  console.log("Child rendering");
  useEffect(() => {
    console.log("Child useEffect ");
  }, []);

  return <div>child , {result}</div>;
};

export default Child;

ํ˜„์žฌ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ App์˜ count ์ƒํƒœ๊ฐ’์ด ๋ฐ”๋€๋‹ค๋ฉด AppChild๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง์ด ๋˜์–ด console.log('Child rendering') ์ด ์‹คํ–‰๋œ๋‹ค.

memo๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ

  • AppChild.jsx

    memo๋กœ Child ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ „์ฒด๋ฅผ ๋ฌถ์–ด์ค€๋‹ค.
    ์ด๋ฅผ ํ†ตํ•ด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋˜๋”๋ผ๋„ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋˜๋Š” ๊ฒƒ์„ ๋ง‰์•„์ค€๋‹ค.

import { useEffect, useState, useMemo, memo } from "react";

const sum = (n) => {
  console.log("sum calculate start");
  let result = 0;
  for (let i = 1; i <= n; i += 1) {
    result += i;
  }
  console.log("sum calculateend");
  return result;
};

const Child = memo(() => {
  const [sumNum, setSumNum] = useState(100000000);
  const result = useMemo(() => sum(sumNum), [sumNum]);
  console.log("Child rendering");
  useEffect(() => {
    console.log("Child useEffect ");
  }, []);

  return <div>child , {result}</div>;
});

export default Child;

์ด์™€๊ฐ™์ด ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ count๊ฐ€ ๋ฐ”๋€Œ์–ด๋„ AppChild๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜์ง€์•Š๋Š”๋‹ค.

useCallback ์‚ฌ์šฉํ•˜๊ธฐ

๋‹ค์‹œ ์ฒ˜์Œ์˜ App.js์™€ AppChild.jsx์—์„œ memo์™€ useMemo๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋Œ์•„๊ฐ€๋ณด์ž

  • App.js
import { useEffect, useState } from "react";
import AppChild from "./AppChild";

const App = () => {
  const [count, setCount] = useState(0);
  const clickIncrease = () => {
    setCount(count + 1);
  };

  console.log("App rendering");

  useEffect(() => {
    console.log("App useEffect ");
  }, []);

  const clickChild = () => {
    console.log("clickChild");
  };

  return (
    <div>
      <button onClick={clickIncrease}></button>
      <AppChild clickChild={clickChild}></AppChild>
    </div>
  );
};

export default App;
  • AppChild.jsx
import { useEffect, useState, useMemo, memo } from "react";

const sum = (n) => {
  console.log("sum calculate start");
  let result = 0;
  for (let i = 1; i <= n; i += 1) {
    result += i;
  }
  console.log("sum calculateend");
  return result;
};

const Child = memo(({ clickChild }) => {
  const [sumNum, setSumNum] = useState(100000000);
  const result = useMemo(() => sum(sumNum), [sumNum]);
  console.log("Child rendering");
  useEffect(() => {
    console.log("Child useEffect ");
  }, []);

  return <div onClick={clickChild}>child , {result}</div>;
});

export default Child;

ํ•ด๋‹น ์ฝ”๋“œ์—์„œ๋Š” ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ(2๋ฒˆํด๋ฆญ) count ์ƒํƒœ๊ฐ’์ด ๋ฐ”๋€Œ๋ฉด AppChild๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋œ๋‹ค.
์ด๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์˜จ clickChild๊ฐ€ App ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜๋ฉด์„œ ์ด์ „๊ณผ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ์ธ์‹๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

useCallback ์ ์šฉํ•˜๊ธฐ

  • App.js ์ ์šฉ
  const clickChild = useCallback(() => {
    console.log("clickChild");
  }, []);

๊ธฐ์กด ํ•จ์ˆ˜์—์„œ ์ „์ฒด๋ฅผ useCallback์œผ๋กœ ๋ฌถ์–ด์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด App์ด ๋ Œ๋”๋ง๋˜์–ด๋„ clickChild๊ฐ€ ์žฌ์ •์˜๋˜๋ฉด์„œ ์ƒˆ๋กœ์šด ์ •์˜๊ฐ€ ๋ ํ•„์š”์—†๊ณ (์ฃผ์†Œ๊ฐ’์ด ๋ฐ”๋€”ํ•„์š”๋„์—†๊ณ ) ์ด๋ฅผ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์œผ๋กœ ์ธ์‹ํ•˜์ง€์•Š์•„์„œ AppChild๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋  ํ•„์š”๋„ ์—†๋‹ค.

์ •๋ฆฌํ•˜๊ธฐ

  • App.js
import { useEffect, useState, useCallback } from "react";
import AppChild from "./AppChild";

const App = () => {
  const [count, setCount] = useState(0);
  const clickIncrease = () => {
    setCount(count + 1);
  };

  console.log("App rendering");

  useEffect(() => {
    console.log("App useEffect ");
  }, []);

  const clickChild = useCallback(() => {
    console.log("clickChild");
  }, []);

  return (
    <div>
      <button onClick={clickIncrease}></button>
      <AppChild clickChild={clickChild}></AppChild>
    </div>
  );
};

export default App;
  • AppChild.jsx
import { useEffect, useState, useMemo, memo } from "react";

const sum = (n) => {
  console.log("sum calculate start");
  let result = 0;
  for (let i = 1; i <= n; i += 1) {
    result += i;
  }
  console.log("sum calculateend");
  return result;
};

const Child = memo(({ clickChild }) => {
  const [sumNum, setSumNum] = useState(100000000);
  const result = useMemo(() => sum(sumNum), [sumNum]);
  console.log("Child rendering");
  useEffect(() => {
    console.log("Child useEffect ");
  }, []);

  return <div onClick={clickChild}>child , {result}</div>;
});

export default Child;

memo , useMemo ,useCallback์€ ๊ฐ๊ฐ์˜ ํ•„์š”ํ•œ ์ƒํ™ฉ์ด ์กด์žฌํ•œ๋‹ค.
memo๋Š” ๋ถ€๋ชจ๊ฐ€ ๋‹จ์ง€ ๋ฆฌ๋ Œ๋”๋ง๋œ๋‹ค๊ณ ( ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ props๊ฐ€ ๋ฐ”๋€๊ฒƒ๋„ ์•„๋‹Œ๋ฐ) ์ž์‹์ด ๋ฆฌ๋ Œ๋”๋ง ๋˜๋Š” ๊ฒƒ์„ ๋ง‰๊ณ 
useMemo๋Š” ๋ฆฌ๋ Œ๋”๋ง์ด ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์‹œ๊ฐ„์ด ๋งŽ์ด๋“œ๋Š” ํ•จ์ˆ˜๊ณ„์‚ฐ์„ ํ•˜์—ฌ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ๋ถˆํ•„์š”ํ•œ ์‹คํ–‰์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๊ณ 
useCallback์€ ๋ฆฌ๋ Œ๋”๋ง์— ์˜ํ•ด ๋ถˆํ•„์š”ํ•œ ์žฌ์ •์˜๋ฅผ ํ†ตํ•ด props๋กœ ์ „๋‹ฌ๋˜์–ด ์ƒํƒœ๋ณ€ํ™”๋กœ ์ธ์‹๋˜์–ด ์ž์‹์—์„œ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ์‹คํ–‰ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ๋ง‰์•„์ค€๋‹ค. (memo๋กœ๋„ ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ props๊ฐ€ ๋ณ€ํ–ˆ๋‹ค๋ฉด ๋ง‰์•„ ์ค„ ์ˆ˜๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ)

profile
๋‚˜์˜ ํ•˜๋ฃจ๋ฅผ ๊ฐ€๋Šฅํ•œ ๊ธฐ์–ตํ•˜๊ณ  ์ฆ๊ธฐ๊ณ  ํ›„ํšŒํ•˜์ง€๋ง์ž

0๊ฐœ์˜ ๋Œ“๊ธ€