useCallback()

useCallback()

1. ๊ฐœ์š”

useCallback()ํ›…์€ useMemo()์™€ ๋”๋ถˆ์–ด ์„ฑ๋Šฅ ์ตœ์ ํ™”์— ์‚ฌ์šฉ๋˜๋Š” React์˜ ํ›…์ด๋‹ค. useMemo()๋Š” ํŠน์ • ๊ฒฐ๊ณผ๊ฐ’์„ ์žฌ์‚ฌ์šฉํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ˜๋ฉด, useCallback()ํ›…์€ ํŠน์ • ํ•จ์ˆ˜๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ์žฌ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํ›…์ด๋‹ค.


2. useCallback() ์‚ฌ์šฉ๋ฒ•

์‚ฌ์šฉ๋ฒ• const fn = useCallback(function, deps)

  • function: Memoization์„ ํ•˜๋Š” ํ•จ์ˆ˜

  • deps: ์˜์กด์„ฑ ๋ฐฐ์—ด๋กœ useEffect()์˜ deps์™€ ๊ฐ™๋‹ค.

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•์€ useMemo()๊ณผ ๊ฐ™์•„ ๋ณด์ธ๋‹ค. ํ•˜์ง€๋งŒ ํ•จ์ˆ˜๋ฅผ Memoizationํ•˜๋Š”์ง€ ํŠน์ • ๊ฐ’์„ Memoization์ด ํ•˜๋Š” ๊ฒƒ์— ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.


3. useCallback()๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ๋žœ๋”๋ง

๋จผ์ € useCallback()ํ›…์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ๋žœ๋”๋งํ•˜๋Š” ๊ณผ์ •์„ ์‚ดํŽด๋ณด์ž. ์ตœ๊ทผ์— ์ œ์ฃผ๋„ ์—ฌํ–‰์„ ๋‹ค๋…€์™”๊ธฐ์— ์ด์™€ ๊ด€๋ จํ•œ ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋ฅผ ์˜ˆ์‹œ๋กœ ์†Œ๊ฐœํ•œ๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด ๋‘ ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

// Test ์ปดํฌ๋„ŒํŠธ
import React, { useState } from "react";
import { useForm } from "react-hook-form";
import Children from "./Children";

const Test = () => {
  const { register, handleSubmit, setValue } = useForm();
  const [isSunny, setIsSunny] = useState(true);
  const [gift, setGift] = useState([]);

  const getMyGift = () => {
    return gift.join(", ");
  };

  return (
    <div>
      <div>
        <span>๊ธฐ๋…ํ’ˆ์„ ๊ฐ€์ง€๊ณ  ์ง‘์œผ๋กœ ๋Œ์•„๊ฐˆ ์ˆ˜ ์žˆ์„๊นŒ์š”?</span>
        <button onClick={() => setIsSunny(!isSunny)}>๋‚ ์”จ ๋ฐ”๊พธ๊ธฐ</button>
        <div>
          {isSunny
            ? "๋‚ ์”จ๊ฐ€ ๋งค์šฐ ์ข‹๋„ค์š”! ๋น„ํ–‰๊ธฐ๊ฐ€ ์ด๋ฅ™ํ•  ์ˆ˜ ์žˆ์–ด์š” ๐Ÿ›ซ"
            : "ํƒœํ’์ด ์™”๋„ค์š”ใ… ใ…  ๋‚ด์ผ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค๋ด์š” โ›ˆ"}
        </div>
      </div>
      <form
        onSubmit={handleSubmit(({ gift }) => {
          setGift((prev) => [...prev, gift]);
          setValue("gift", "");
        })}
      >
        <input {...register("gift")} placeholder="์‚ฌ๊ณ  ์‹ถ์€ ๊ธฐ๋…ํ’ˆ" />
        <input type="submit" value="๊ธฐ๋…ํ’ˆ ๊ณ ๋ฅด๊ธฐ" />
      </form>
      <Children getMyGift={getMyGift} />
    </div>
  );
};

export default Test;

// Children ์ปดํฌ๋„ŒํŠธ
import React, { useState, useEffect } from "react";

const Children = ({ getMyGift }) => {
  const [myGift, setMyGift] = useState();
  useEffect(() => {
    console.log("์ƒˆ๋กœ์šด ๊ธฐ๋…ํ’ˆ์ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค!");
    setMyGift(getMyGift());
  }, [getMyGift]);
  return <div>๋‚˜์˜ ๊ธฐ๋…ํ’ˆ ๋ชฉ๋ก: {myGift}</div>;
};

export default Children;

์ฝ”๋“œ์˜ ๋ถ„์„๋ถ€ํ„ฐ ํ•ด๋ณด์ž.

  • ๋จผ์ € ๋‚˜๋Š” useFormํ›…์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ์ด ํ›…์€ react-hook-form ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•œ ํ›„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•ด๋‹น ๋ชจ๋“ˆ๊ณผ ํ›…์— ๋Œ€ํ•ด์„œ๋Š” ๋‹ค๋ฅธ ์ฑ•ํ„ฐ์—์„œ ์ž์„ธํžˆ ๋‹ค๋ฃจ๋„๋ก ํ•˜๊ฒ ๋‹ค.

  • isSunny์™€ gift๋ผ๋Š” state๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

    const [isSunny, setIsSunny] = useState(true);
    const [gift, setGift] = useState([]);
  • isSunny state๋Š” ๋‚ ์”จ ๋ฐ”๊พธ๊ธฐ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ๊ฐ’์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๊ณ  ๊ฐ’์— ๋”ฐ๋ผ ๋น„ํ–‰๊ธฐ๊ฐ€ ์ด๋ฅ™ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—†๋Š”์ง€ ํ…์ŠคํŠธ๋กœ ์•Œ๋ ค์ฃผ๊ณ  ์žˆ๋‹ค.

  • gift state๋Š” ์ดˆ๊ธฐ๊ฐ’์ด ๋ฐฐ์—ด์ด๊ณ  input์—์„œ ๋ฐ›์€ ๊ฐ’์„ ์ฐจ๋ก€๋Œ€๋กœ Array.push()๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ €์žฅํ•˜๊ณ  ์žˆ๋‹ค.

    handleSubmit(({ gift }) => {
      setGift((prev) => [...prev, gift]);
      setValue("gift", "");
    });
  • getMyGift()๋Š” Children์ปดํฌ๋„ŒํŠธ์— props๋กœ ์ „๋‹ฌํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. ํ•ด๋‹น ํ•จ์ˆ˜๋Š” ๋ฐฐ์—ด์„ Array.join()๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊พธ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

    const getMyGift = () => {
      return gift.join(", ");
    };
  • Children์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” myGift state๊ฐ€ ์„ ์–ธ์ด ๋˜์–ด ์žˆ๋‹ค. ํ•ด๋‹น state๋Š” props์œผ๋กœ ์ „๋‹ฌ๋ฐ›์€ getMyGift()๊ฐ€ ์—…๋ฐ์ดํŠธ ๋  ๋•Œ ๋งˆ๋‹ค useEffect() ์„ ํ†ตํ•ด ์—…๋ฐ์ดํŠธ ๋˜๊ณ  ์žˆ๋‹ค.

    const [myGift, setMyGift] = useState();
    useEffect(() => {
      console.log("์ƒˆ๋กœ์šด ๊ธฐ๋…ํ’ˆ์ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค!");
      setMyGift(getMyGift());
    }, [getMyGift]);

์ฝ”๋“œ ๋ถ„์„์ด ๋๋‚ฌ์œผ๋‹ˆ state๊ฐ’๋“ค์„ ๋ณ€๊ฒฝํ•˜์—ฌ ํ™”๋ฉด์ด ๋žœ๋”๋งํ•˜๋Š” ๊ณผ์ •์„ ์•Œ์•„๋ณด์ž. ์ผ๋‹จ ์ œ์ฃผ๋„์— ๊ฐ”์œผ๋‹ˆ ๊ธฐ๋…ํ’ˆ์„ ์‚ฌ์•ผํ•œ๋‹ค. ์‚ฌ๊ณ  ์‹ถ์€ ๊ธฐ๋…ํ’ˆ์„ ์ž…๋ ฅํ•˜๊ณ  ๊ธฐ๋…ํ’ˆ ๊ณ ๋ฅด๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ๋‚˜์˜ ๊ธฐ๋…ํ’ˆ ๋ชฉ๋ก์— ์ถ”๊ฐ€ํ•˜์ž.

์ดˆ์ฝœ๋ฆฟ, ๋จธ๊ทธ์ž”, ์ œ์ฃผ๋ฆฌ์–ผํƒ€๋ฅดํŠธ, ํ–ฅ์ˆ˜๋ฅผ ๊ธฐ๋…ํ’ˆ ํ’ˆ๋ชฉ์— ์ถ”๊ฐ€ํ•˜์˜€๋‹ค. ์ถ”๊ฐ€๊ฐ€ ๋  ๋•Œ ๋งˆ๋‹ค getMyGift()๊ฐ€ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ํ• ๋‹นํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Children์ปดํฌ๋„ŒํŠธ์˜ useEffect()๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด getMyGift()์™€ ์ „ํ˜€ ์ƒ๊ด€์—†๋Š” isSunny์˜ ๊ฐ’์„ ๋ฐ”๊พธ๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ๋‚ ์”จ ๋ฐ”๊พธ๊ธฐ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ ๋น„ํ–‰๊ธฐ๋ฅผ ๋‹ค์Œ๋‚ ์— ๋„์–ด๋ณด์ž.

๋‚ ์”จ๊ฐ€ ๋ฐ”๋€Œ์–ด ํƒœํ’์ด ์˜ค๊ณ  ์žˆ๋‹ค. isSunny๊ฐ’์€ ์„ฑ๊ณต์ ์œผ๋กœ ๋ฐ”๋€Œ์—ˆ๊ณ  gift์˜ ๊ฐ’์€ ๋ฐ”๋€Œ์ง€ ์•Š์•˜๋‹ค. ํ•˜์ง€๋งŒ getMyGift()๊ฐ€ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ํ• ๋‹นํ•˜๊ณ  ์žˆ์–ด Children์ปดํฌ๋„ŒํŠธ์˜ useEffect()๊ฐ€ ์‹คํ–‰์ด ๋˜์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” "์ƒˆ๋กœ์šด ๊ธฐ๋…ํ’ˆ์ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค!"๋ผ๋Š” ํ…์ŠคํŠธ๊ฐ€ ์ฝ˜์†”์— ํ•˜๋‚˜ ๋” ์ถ”๊ฐ€๋œ ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์ฆ‰ ๋ฆฌ๋žœ๋”๋ง์ด ํ•„์š”ํ•˜์ง€ ์•Š๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋žœ๋”๋ง์ด ์ผ์–ด๋‚œ ๊ฒƒ์ด๋‹ค.

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


4. useCallback()๋ฅผ ์‚ฌ์šฉํ•œ ์ปดํฌ๋„ŒํŠธ์˜ ๋žœ๋”๋ง

์ด์ œ useCallback()ํ›…์„ ์‚ฌ์šฉํ•˜์—ฌ ์œ„์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ž.

getMyGift()์˜ ํ•จ์ˆ˜๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•˜์ž.

const getMyGift = useCallback(() => {
  return gift.join(", ");
}, [gift]);

๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ ๋‹ค์‹œ ๊ธฐ๋…ํ’ˆ ๋ชฉ๋ก์„ ์ถ”๊ฐ€ํ•ด๋ณด์ž.

์ด๋ฒˆ์—๋„ ๊ธฐ๋…ํ’ˆ ์ถ”๊ฐ€ ๋  ๋•Œ๋งˆ Children์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋žœ๋”๋ง์ด ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋‚ ์”จ ๋ฐ”๊พธ๊ธฐ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ Children์ปดํฌ๋„ŒํŠธ์™€ ๊ด€๋ จ์—†๋Š” isSunny์˜ ๊ฐ’์„ ๋ฐ”๊พธ์–ด ๋ณด์ž.

isSunny์˜ ๊ฐ’์ด ๋ฐ”๋€Œ์–ด ๋‚ ์”จ๊ฐ€ ํƒœํ’์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋˜์–ด๋„ Children์ปดํฌ๋„ŒํŠธ๋Š” ๋ฆฌ๋žœ๋”๋ง์ด ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋Š” useCallback()ํ›…์˜ ์˜์กด์„ฑ ๋ฐฐ์—ด์˜ ๊ฐ’์œผ๋กœ gift๋งŒ ์ถ”๊ฐ€ํ–ˆ๊ธฐ์— isSunny๊ฐ€ ์•„๋ฌด๋ฆฌ ๋ฐ”๋€Œ์–ด๋„ getMyGift()ํ•จ์ˆ˜๊ฐ€ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด์˜ ์ฃผ์†Œ๋Š” ๋ฐ”๋€Œ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.


5. Conclusion

useMemo()ํ›…๊ณผ useCallback()ํ›…์„ ๊ณต๋ถ€ํ•˜๋ฉด์„œ ๋Š๊ผˆ๋˜ ์ ์€ "๊ณผ์—ฐ ๋‚ด๊ฐ€ ์ ์ œ์ ์†Œ์— ํ•ด๋‹น ํ›…์„ ์ž˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„๊นŒ?"์˜€๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ ๋žœ๋”๋ง ์ตœ์ ํ™”์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์„ ํ•˜์ง€ ์•Š๊ณ  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•„์š”ํ•œ ๊ณณ์— ๋‚ด๊ฐ€ ์ž˜ ์ ์šฉ์„ ํ•  ์ˆ˜ ์žˆ์„์ง€ ๊ฑฑ์ •์ด ๋œ๋‹ค. ๊ทธ๋ž˜๋„ ์–ผ๋ฅธ ํ‹ฐ์ฒ˜์บ” ๋ฆฌํŒฉํ† ๋ง์„ ์‹œ์ž‘ํ•ด์„œ ์ง์ ‘ ํ”„๋กœ์žญํŠธ์— ์ ์šฉ์„ ํ•˜๊ณ  ์‹ถ๋‹ค. ๋ฆฌํŒฉํ† ๋ง์€ ๋‹ค์Œ์ฃผ ์›”์š”์ผ(22.8.8) ๋ถ€ํ„ฐ ์‹œ์ž‘!


์ฐธ๊ณ 

[React] ๋ฆฌ์•กํŠธ Hooks : useCallback() ํ•จ์ˆ˜ ์‚ฌ์šฉ๋ฒ• React Hooks: useCallback ์‚ฌ์šฉ๋ฒ•

๋„์›€์ด ๋งŽ์ด ๋˜์—ˆ๋˜ ์œ ํŠœ๋ธŒ ๐ŸŽฌ

  • React Hooks์— ์ทจํ•œ๋‹ค - useCallback ์งฑ ์‰ฌ์šด ๊ฐ•์˜ | ๋ฆฌ์•กํŠธ ํ›…์Šค ์‹œ๋ฆฌ์ฆˆ


๐Ÿ‘†

๐Ÿ“… 2022-08-04

Last updated