react - useCallback, memo re-render ์ตœ์ ํ™”

React์˜ Hook ์ค‘์— useCallback๊ณผ useMemo๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ตœ์ ํ™” ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์•˜๋‹ค.

React๊ฐ€ ๋ Œ๋”๋ง์„ ์‹คํ–‰ํ•˜๋Š” ํ–‰๋™

  1. Props๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ
  2. State๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ
  3. ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋˜์—ˆ์„ ๋•Œ
  4. focueUpdate() ๋ฅผ ์‹คํ–‰ํ•˜์˜€์„ ๋•Œ

์ฃผ๋ชฉํ•ด์•ผ ๋  ์ ์€ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง ๋˜์—ˆ์„๋•Œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๊นŒ์ง€ ๋‹ค์‹œ ๋ Œ๋”๋ง์ด ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์ž์‹์ปดํฌ๋„ŒํŠธ๋Š” ๋ณ€ํ™”์— ์•„๋ฌด๋Ÿฐ ์˜ํ–ฅ์ด ์—†๋‹ค๋ฉด ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜์—ฌ ์„ฑ๋Šฅ ์†์‹ค์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค. ์ฆ‰ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ณต์žกํ•˜๊ณ  ๋งŽ์„์ˆ˜๋ก ์†์‹ค์€ ์‹ฌํ•ด์ง€๊ฒŒ ๋œ๋‹ค.

๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง

import React from "react";
import ReactDOM from "react-dom";

const CountButton = function CountButton({ count, onClick }) {
  return <button onClick={onClick}>{count}</button>;
};

function DualCounter() {
  const [count1, setCount1] = React.useState(0);
  const increment1 = () => { setCount1(c => c + 1) };
  const [count2, setCount2] = React.useState(0);
  const increment2 = () => { setCount2(c => c + 1) };

  return (
    <>
      <CountButton count={count1} onClick={increment1} />
      <CountButton count={count2} onClick={increment2} />
    </>
  );
}
const rootElement = document.getElementById("root");
ReactDOM.render(<DualCounter />, rootElement);

์•„์ฃผ ๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ์ด๋‹ค ์œ„ ์ฝ”๋“œ๋Š” increment1 ์„ ํ˜ธ์ถœ์‹œํ‚ค๋ฉด count1์ด 1 ๋”ํ•ด์ง€๋ฉฐ state ๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด ๋ฆฌ๋ Œ๋”๋ง ๋œ๋‹ค. ๊ทธ๋ ‡๊ฒŒ๋˜๋ฉด ์œ„ ๋ณ€ํ™”์— ์•„๋ฌด๋Ÿฐ ๋ณ€๊ฒฝ์ด ์—†์–ด๋„ count2๋Š” ๋ถ€๋ชจ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง์ด ๋˜์–ด ๋ฆฌ ๋ Œ๋”๋ง์ด ์ด๋ฃจ์›Œ์ง„๋‹ค

React.memo ์™€ React.useCallback

shouldComponentUpdate ๊ฐ€ ์žˆ๋“ฏ์ด React.memo ๊ฐ€ ์žˆ๋‹ค ์œ„ ์˜ˆ์ œ๋ฅผ memo์™€ useCallback ์‚ฌ์šฉํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ ๋ฆฌ ๋ Œ๋”๋ง์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

const CountButton = React.memo(function CountButton({ count, onClick }) {
  return <button>{count}</button>;
});

function DualCounter() {
  const [count1, setCount1] = React.useState(0);
  const increment1 = () => { setCount1(c => c + 1) };
  const [count2, setCount2] = React.useState(0);
  const increment2 = () => { setCount2(c => c + 1) };

  return (
    <>
      <CountButton count={count1} onClick={increment1} />
      <CountButton count={count2} onClick={increment2} />
    </>
  );
}

์œ„ ์˜ˆ์ œ์—์„œ๋Š” memo๋งŒ ์‚ฌ์šฉํ•˜์˜€๋‹ค. React.memo()๋Š” props ํ˜น์€ props์˜ ๊ฐ์ฒด๋ฅผ ๋น„๊ตํ•  ๋•Œ ์–•์€(shallow) ๋น„๊ต๋ฅผ ํ•œ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋œ๋‹ค๋ฉด count๊ฐ’์€ ๋ถˆ๋ณ€๊ฐ’์ด๋‹ˆ ์ƒ๊ด€์ด ์—†์œผ๋‚˜ onClick์€ ๋ฆฌ ๋ Œ๋”๋ง ๋ ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ ์ƒ์„ฑ๋˜์–ด ๋ฆฌ ๋ Œ๋”๋ง ๋œ๋‹ค.

React.useCallback

function DualCounter() {
  const [count1, setCount1] = React.useState(0);
  const increment1 = React.useCallback(() => setCount1(c => c + 1), []);;
  const [count2, setCount2] = React.useState(0);
  const increment2 = React.useCallback(() => setCount2(c => c + 1), []);;

  return (
    <>
      <CountButton count={count1} onClick={increment1} />
      <CountButton count={count2} onClick={increment2} />
    </>
  );
}

์œ„ ์†Œ์Šค๋ฅผ ๋ณด๋ฉด ์ฆ๊ฐ€ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ useCallback์œผ๋กœ ๊ฐ์‹ธ๊ณ  ๋‘๋ฒˆ์งธ ์ธ์ž์— ์˜์กด์„ฑ ๊ฐ’๋“ค์„ ๋„ฃ์–ด์ฃผ๊ณ  ํ•ด๋‹น ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๊ฐ์ง€๋ฅผ ํ•˜์—ฌ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค. ์ด๋ฒˆ์—” ๋นˆ ๋ฐฐ์—ด์„ ๋„˜๊ฒจ์ค˜์„œ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด onClick๊ฐ’์ด ๋ณ€ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ฆฌ ๋ Œ๋”๋ง ๋˜์ง€ ์•Š๋Š”๋‹ค. ํ˜น์€ React.memo์— ๋‘๋ฒˆ์งธ ์ธ์ž์— ์กฐ๊ฑด์„ ๊ฑฐ๋Š” ๋ฐฉ์‹์ด ์žˆ๋‹ค.

React.useMemo

useCallback์€ ํ•จ์ˆ˜๋งŒ ๋ฐ˜ํ™˜ํ•œ๋‹ค ์ƒ๊ฐํ•˜๊ณ  useMemo๋Š” ๊ฐ’(ํ•จ์ˆ˜ํฌํ•จ) ๋ฐ˜ํ™˜ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฃผ๋กœ ๋ณต์žกํ•˜๊ณ  ์˜ค๋ž˜๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์— ์‚ฌ์šฉํ•ด์•ผ๋œ๋‹ค.

useCallback ๋ฐ useMemo ์ฃผ์˜ํ• ์ 

  1. ๊ฐ„๋‹จํ•œ ์ž‘์—…์—๋„ ์‚ฌ์šฉํ•˜๊ฒŒ๋œ๋‹ค๋ฉด ์˜คํžˆ๋ ค ์„ฑ๋Šฅ์ด ์•…ํ™” ๋  ์ˆ˜๋„ ์žˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์ž‘์—…์€ garbage collected ๋˜๊ณ  ์ƒˆ๋กœ์šด๊ฒƒ์ด ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ด๋‹ค.
  2. useCallback, useMemo์˜ ํ•จ์ˆ˜๋Š” ์ƒ์„ฑ๋˜๋˜ ๋‹น์‹œ์˜ ์ƒํƒœ๋ฅผ ๋ณด์กดํ•œ๋‹ค.

์ฐธ๊ณ ํ•œ ์ž๋ฃŒ

When to useMemo and useCallback


@๊น€๋Œ€์™„
์•ˆ๋…•ํ•˜์„ธ์š”

AboutGitHub