[TIL] 0606 | React with Redux, Next.js, TypeScript

TeasanΒ·2022λ…„ 6μ›” 6일
0

TIL

λͺ©λ‘ 보기
2/36
post-thumbnail

λͺ©μ°¨

  • React.memo()둜 λΆˆν•„μš”ν•œ μž¬ν‰κ°€ λ°©μ§€ν•˜κΈ°
  • useCallback()으둜 ν•¨μˆ˜ μž¬μƒμ„± λ°©μ§€ν•˜κΈ°
  • useCallback() 및 쒅속성에 λŒ€ν•˜μ—¬

✧ React.memo()둜 λΆˆν•„μš”ν•œ μž¬ν‰κ°€ λ°©μ§€ν•˜κΈ°

  • 사싀 이런 κ°„λ‹¨ν•œ μ•±μ—μ„œλŠ” λͺ‡ 개의 μžμ‹ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ¦¬λ Œλ”λ§ν•˜λŠ” 것은 μ„±λŠ₯ λ©΄μ—μ„œ 크게 λ¬Έμ œκ°€ λ˜μ§€ μ•Šμ„ μˆ˜λ„ μžˆλ‹€. ν•˜μ§€λ§Œ 이보닀 큰 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄λΌλ©΄ μžμ‹ μ»΄ν¬λ„ŒνŠΈλŠ” 더 λ³΅μž‘ν•˜κ³  λ‹€μ–‘ν•˜κ²Œ λ§Žμ•„μ§ˆ 것이고, λ¦¬λ Œλ”λ§μœΌλ‘œ μΈν•œ μ„±λŠ₯을 κ³ λ €ν•˜μ§€ μ•Šμ„ 수 μ—†λ‹€. μ’€ 더 μ΅œμ ν™”κ°€ ν•„μš”ν•˜λ‹€λŠ” 이야기닀. λ”°λΌμ„œ κ°œλ°œμžλŠ” νŠΉμ •ν•œ 상황일 κ²½μš°μ—λ§Œ μžμ‹ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ¦¬λ Œλ”λ§ ν•˜λ„λ‘ React 에 μ§€μ‹œν•  수 μžˆμ–΄μ•Ό ν•  것이닀.

React.memo() μ‚¬μš©ν•˜κΈ°

  • μ•žμ„œ κ±°λ‘ ν•œ νŠΉμ •ν•œ μƒν™©μ΄λž€ λ¬΄μ—‡μΌκΉŒ? 예λ₯Ό λ“€λ©΄, μžμ‹ μ»΄ν¬λ„ŒνŠΈκ°€ λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈλ‘œ λΆ€ν„° 받은 props κ°€ λ³€κ²½λ˜μ—ˆμ„ λ•Œλ₯Ό μƒκ°ν•΄λ³΄μž.

App.js

<DemoOutput show={false} />
  • App μ»΄ν¬λ„ŒνŠΈμ—μ„œ DemoOutput μ»΄ν¬λ„ŒνŠΈλ‘œ μ „λ‹¬ν•˜λŠ” show 뢀뢄을 λ‹€μ‹œ 뢈러였면, ReactλŠ” show μƒνƒœ(state) 값이 λ°”λ€” λ•Œμ—λ§Œ DemoOutput μ»΄ν¬λ„ŒνŠΈλ₯Ό λ¦¬λ Œλ”λ§μ„ ν•  수 μžˆλ‹€λ©΄ 이것이 νŠΉμ •ν•œ 상황이라고 말할 수 μžˆμ„ 것이닀. κ·Έλ ‡λ‹€λ©΄, μš°λ¦¬λŠ” μ–΄λ–»κ²Œ React 에 'νŠΉμ •ν•œ 상황' 일 λ•Œλ§Œ μžμ‹ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ¦¬λ Œλ”λ§ ν•  수 μžˆλ„λ‘ μ§€μ‹œν•  수 μžˆμ„κΉŒ?

  • λ¨Όμ €, propsκ°€ λ°”λ€Œμ—ˆλŠ”μ§€ 확인할 μ»΄ν¬λ„ŒνŠΈλ₯Ό μ§€μ •ν•œ λ’€

DemoOutput.js

const DemoOutput = (props) => {
  console.log("DemoOutput RUNNUNG");
  return <MyParagraph>{props.show ? "This is New!" : ""}</MyParagraph>;
};

export default DemoOutput;
  • 이것을 ν†΅μ§Έλ‘œ warp ν•΄μ£Όλ©΄ λœλ‹€.
const DemoOutput = (props) => {
  console.log("DemoOutput RUNNUNG");
  return <MyParagraph>{props.show ? "This is New!" : ""}</MyParagraph>;
};

export default React.memo(DemoOutput);
  • μ΄λ ‡κ²Œ React.memo() 둜 warp을 ν•΄μ£ΌλŠ” 것은 ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈμ—μ„œλ§Œ κ°€λŠ₯ν•˜λ‹€. 클래슀 기반의 μ»΄ν¬λ„ŒνŠΈμ˜ 경우 μž‘λ™ν•˜μ§€ μ•ŠλŠ”λ‹€.

  • React.memo()λŠ” ν•¨μˆ˜ν˜• μ»΄ν¬λ„ŒνŠΈλ₯Ό μ΅œμ ν™”ν•œλ‹€. 이 memo()λŠ” μ–΄λ–€ 역할을 ν• κΉŒ? React.memo()λŠ” 인자둜 λ“€μ–΄κ°„ μ»΄ν¬λ„ŒνŠΈμ— μ–΄λ–€ propsκ°€ μž…λ ₯λ˜λŠ”μ§€λ₯Ό ν™•μΈν•˜κ³ , μž…λ ₯λ˜λŠ” λͺ¨λ“  props의 μƒˆλ‘œμš΄ 값을 ν™•μΈν•œ λ’€ 이λ₯Ό 기쑴의 props κ°’κ³Ό λΉ„κ΅ν•˜λ„λ‘ React에 μ „λ‹¬ν•˜λŠ” 역할을 ν•œλ‹€. 그리고 props의 값이 λ°”κΎΈλ‹ˆ κ²½μš°μ—λ§Œ μ»΄ν¬λ„ŒνŠΈλ₯Ό μž¬μ‹€ν–‰ 및 μž¬ν‰κ°€ ν•œλ‹€.

  • 즉, λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈκ°€ λ³€κ²½λ˜μ—ˆμ§€λ§Œ React.memo()둜 감싼 μ»΄ν¬λ„ŒνŠΈμ˜ propsκ°€ λ³€ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ 이 μ»΄ν¬λ„ŒνŠΈμ˜ μž¬μ‹€ν–‰μ€ κ±΄λ„ˆλ›°κ²Œ λ˜λŠ” 것이닀.

  • μ €μž₯ν•˜κ³  μ½˜μ†”μ„ ν™•μΈν•΄λ³΄μž. μ΅œμ΄ˆμ— μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ λ Œλ”λ§λ˜λ©΄, DemoOutput μ»΄ν¬λ„ŒνŠΈμ—μ„œ 좜λ ₯ν•˜λŠ” ν…μŠ€νŠΈμΈ "DemoOutput RUNNUNG" 도 ν•¨κ»˜ 좜λ ₯λœλ‹€. ν•˜μ§€λ§Œ μ½˜μ†”μ„ μ΄ˆκΈ°ν™”ν•œ λ’€ λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ "APP RUNNING" 와 "Button RUNNING" λŠ” 좜λ ₯λ˜μ§€λ§Œ "DemoOutput RUNNUNG"λŠ” 좜λ ₯λ˜μ§€ μ•ŠλŠ” 것을 λ³Ό 수 μžˆλ‹€. MyParagraph μ»΄ν¬λ„ŒνŠΈλŠ” React.memo()둜 감싼 DemoOutput μ»΄ν¬λ„ŒνŠΈμ˜ μžμ‹ μ»΄ν¬λ„ŒνŠΈμ΄λ―€λ‘œ 이 λ˜ν•œ 좜λ ₯λ˜μ§€ μ•ŠλŠ”λ‹€.

  • μ΄λ ‡κ²Œ, λΆˆν•„μš”ν•œ μž¬λ Œλ”λ§μ„ ν”Όν•˜κΈ° μœ„ν•΄ React.memo()λ₯Ό μ‚¬μš©ν•˜μ—¬ μ΅œμ ν™”λ₯Ό μ§„ν–‰ν–ˆλ‹€. 그리고 μš°λ¦¬λŠ” μ—¬κΈ°μ„œ μƒˆλ‘œμš΄ μ§ˆλ¬Έμ„ 마주치게 λœλ‹€. μ΄λ ‡κ²Œ λ Œλ”λ§ μ΅œμ ν™”κ°€ κ°€λŠ₯ν•˜λ‹€λ©΄, μ™œ λͺ¨λ“  μ»΄ν¬λ„ŒνŠΈμ— μ μš©ν•˜μ§€ μ•ŠλŠ” 걸까?

μ™œ λͺ¨λ“  μ»΄ν¬λ„ŒνŠΈλ₯Ό μ΅œμ ν™”ν•˜μ§€ μ•ŠλŠ”κ°€

  • μ΅œμ ν™”μ—λŠ” λΉ„μš©μ΄ λ”°λ₯Έλ‹€. 이 React.memo()λŠ” μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ— 변경이 일어날 λ•Œλ§ˆλ‹€ λ°œμƒν•œλ‹€. 그리고 App μ»΄ν¬λ„ŒνŠΈκ°€ λ Œλ”λ§μ΄ 될 λ•Œλ§ˆλ‹€ React.memo()둜 감싼 μ»΄ν¬λ„ŒνŠΈλ‘œ μ΄λ™ν•˜μ—¬, 기쑴의 props κ°’κ³Ό μƒˆλ‘œμš΄ props 값을 λΉ„κ΅ν•œλ‹€. 그러면 ReactλŠ” μ—¬κΈ°μ„œ 두 가지 μž‘μ—…μ΄ ν•„μš”ν•˜λ‹€. λ¨Όμ €, 기쑴의 props 값을 μ €μž₯ν•  곡간이 ν•„μš”ν•˜κ³  λΉ„κ΅ν•˜λŠ” μž‘μ—…μ΄ 첫 번째이고 λ‘λ²ˆμ§Έλ‘œ 이 각각의 μž‘μ—…μ—μ„œ κ°œλ³„μ μΈ μ„±λŠ₯ λΉ„μš©μ΄ ν•„μš”ν•˜λ‹€. λ”°λΌμ„œ 이 μ„±λŠ₯ νš¨μœ¨μ€ μ–΄λ–€ μ»΄ν¬λ„ŒνŠΈλ₯Ό μ΅œμ ν™”ν•˜λŠλƒμ— 따라 달라진닀.

React.memo()둜 μ΄λ£¨μ–΄μ§€λŠ” μ„±λŠ₯ λΉ„μš©μ˜ κ΅ν™˜

  • μš°λ¦¬κ°€ React.memo() λ₯Ό μ‚¬μš©ν•˜μ—¬ νŠΉμ • μ»΄ν¬λ„ŒνŠΈλ₯Ό 감싼닀면, 맀번 μ»΄ν¬λ„ŒνŠΈλ₯Ό λ¦¬λ Œλ”λ§ν•˜λŠ” 데에 ν•„μš”ν•œ μ„±λŠ₯ λΉ„μš©κ³Ό, React.memo()둜 감싼 νŠΉμ • μ»΄ν¬λ„ŒνŠΈμ˜ propsλ₯Ό λΉ„κ΅ν•˜λŠ” μ„±λŠ₯ λΉ„μš©μ„ μ„œλ‘œ λ§žλ°”κΎΈλŠ” 것과 λ™μΌν•˜λ‹€.

  • 그리고 이런 λΉ„μš©μ€ νŠΉμ • μ»΄ν¬λ„ŒνŠΈμ— ν•„μš”ν•œ props의 κ°―μˆ˜μ™€ ν•΄λ‹Ή μ»΄ν¬λ„ŒνŠΈμ˜ λ³΅μž‘λ„, 그리고 ν•΄λ‹Ή μ»΄ν¬λ„ŒνŠΈκ°€ 가지고 μžˆλŠ” μžμ‹ μ»΄ν¬λ„ŒνŠΈμ˜ μˆ«μžμ— 따라 λ‹¬λΌμ§€λŠ” κ²ƒμ΄λ―€λ‘œ λ‘˜ 쀑 μ–΄λŠ μͺ½μ˜ λΉ„μš©μ΄ 항상 λ†’λ‹€κ³  λ§ν•˜λŠ” 것은 λΆˆκ°€λŠ₯ν•˜λ‹€. λ¬Όλ‘ , μžμ‹ μ»΄ν¬λ„ŒνŠΈκ°€ λ§Žμ•„μ„œ μ»΄ν¬λ„ŒνŠΈ νŠΈλ¦¬κ°€ 크닀면 이 React.memo()λŠ” 맀우 μœ μš©ν•˜κ²Œ 쓰일 수 μžˆμ§€λ§Œ 말이닀. λ˜ν•œ μ»΄ν¬λ„ŒνŠΈ 트리의 μƒμœ„μ— μœ„μΉ˜ν•΄ μžˆλ‹€λ©΄ 전체 μ»΄ν¬λ„ŒνŠΈ νŠΈλ¦¬μ— λŒ€ν•œ λΆˆν•„μš”ν•œ μž¬λ Œλ”λ§μ„ 막을 수 μžˆλ‹€.

const DemoOutput = (props) => {
  console.log("DemoOutput RUNNUNG");
  return <MyParagraph>{props.show ? "This is New!" : ""}</MyParagraph>;
};

export default React.memo(DemoOutput);
  • μ§€κΈˆμ²˜λŸΌ DemoOutput μ»΄ν¬λ„ŒνŠΈλ₯Ό React.memo()둜 κ°μ‹Έλ©΄μ„œ μžλ™μ μœΌλ‘œ DemoOutput μ»΄ν¬λ„ŒνŠΈμ˜ μžμ‹ μ»΄ν¬λ„ŒνŠΈμΈ MyParagraph μ»΄ν¬λ„ŒνŠΈμ˜ λ¦¬λ Œλ”λ§λ„ ν”Όν•  수 μžˆλŠ” κ²ƒμ²˜λŸΌ 말이닀.

React.memo() κ°€ ν•„μš”ν•˜μ§€ μ•ŠλŠ” 경우

  • μœ„μ˜ μ‚¬λ‘€μ™€λŠ” λ°˜λŒ€λ‘œ λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈλ₯Ό 맀 번 μž¬ν‰κ°€ν•  λ•Œλ§ˆλ‹€ μ»΄ν¬λ„ŒνŠΈμ˜ λ³€ν™”κ°€ μžˆκ±°λ‚˜ props의 값이 λ³€ν™”ν•  수 μžˆλŠ” κ°€λŠ₯성이 높은 μ»΄ν¬λ„ŒνŠΈλΌλ©΄ React.memo() λ©”μ†Œλ“œλŠ” 크게 의미λ₯Ό 갖지 λͺ»ν•  것이닀. μ™œλƒν•˜λ©΄ React.memo() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λ”λΌλ„, ν•΄λ‹Ή μ»΄ν¬λ„ŒνŠΈμ˜ μž¬λ Œλ”λ§μ΄ μ–΄λ–»κ²Œλ“  이루어지기 λ•Œλ¬Έμ΄λ‹€. λ¬Όλ‘  props κ°’μ˜ 좔가적인 비ꡐ에 λŒ€ν•œ λΉ„μš©μ€ μ•„λ‚„ 수 μžˆμ„μ§€λŠ” λͺ¨λ₯΄κ² μ§€λ§Œ μ–΄μ¨Œλ“  μ˜€λ²„ν—€λ“œλ‘œ λ°œμƒν•˜λŠ” λΉ„μš©λ„ κ³ λ €ν•΄λ³Έλ‹€λ©΄ ꡳ이 React.memo()λ₯Ό μ‚¬μš©ν•  ν•„μš”λŠ” 없을 것이닀.

  • React.memo()κ°€ ν•„μš”ν•˜μ§€ μ•ŠλŠ” κ²½μš°λŠ” 또 μžˆλ‹€. 맀우 μž‘μ€ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜, ν˜Ήμ€ 맀우 μž‘μ€ μ»΄ν¬λ„ŒνŠΈ 트리의 κ²½μš°μ—λŠ” ꡳ이 React.memo()둜 트리의 가지λ₯Ό μž˜λΌλ‚΄λŠ” 것이 크게 μ˜λ―Έκ°€ μ—†κΈ° λ•Œλ¬Έμ΄λ‹€. 이렇듯, λͺ¨λ“  μ»΄ν¬λ„ŒνŠΈλ₯Ό React.memo()둜 λž©ν•‘ν•  ν•„μš”λŠ” μ—†λ‹€. κ²½μš°μ— λ”°λΌμ„œ μ»΄ν¬λ„ŒνŠΈ νŠΈλ¦¬μ—μ„œ μž˜λΌλ‚Ό 수 μžˆλŠ” μ†Œμˆ˜μ˜ μ£Όμš” μ»΄ν¬λ„ŒνŠΈλ₯Ό μ„ νƒν•΄μ„œ μ‚¬μš©ν•˜λŠ” 게 쒋을 것이닀. μ΄λ ‡κ²Œ μ ν•©ν•œ μš©λ„λ‘œ React.memo()λ₯Ό 골라 μ‚¬μš©ν•œλ‹€λ©΄, λͺ¨λ“  μ»΄ν¬λ„ŒνŠΈλ₯Ό React.memo()둜 κ°μ‹ΈλŠ” κ²ƒλ³΄λ‹€λŠ” μ–΄μ¨Œλ“  훨씬 효율적일 것이닀. (μ˜€λ²„ν—€λ“œλ„ 방지할 수 μžˆλ‹€.)

Button μ»΄ν¬λ„ŒνŠΈμ— React.memo()λ₯Ό μ μš©ν•˜λŠ” 게 μ’‹μ„κΉŒ?

  • Button μ»΄ν¬λ„ŒνŠΈλŠ” 트리거 μ»΄ν¬λ„ŒνŠΈμ΄κΈ° λ•Œλ¬Έμ— React.memo()λ₯Ό μ μš©ν•˜λŠ” 게 μ˜³μ€μ§€ μ•„λ‹Œμ§€μ— λŒ€ν•΄ λ…Όν•  수 μžˆμ„μ§€λ„ λͺ¨λ₯Έλ‹€.
const Button = (props) => {
  console.log("Button RUNNING");
  return (
    <button
      type={props.type || "button"}
      className={`${classes.button} ${props.className}`}
      onClick={props.onClick}
      disabled={props.disabled}
    >
      {props.children}
    </button>
  );
};
  • ν•˜μ§€λ§Œ 이 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ Button μ»΄ν¬λ„ŒνŠΈλŠ” λ‹€μ‹œ 변경될 일이 μ—†λ‹€λŠ” 것을 μ•Œκ³  μžˆμœΌλ―€λ‘œ 맀번 λ¦¬λ Œλ”λ§ λ˜λŠ” 것은 λΆˆν•„μš”ν•˜λ‹€λŠ” 사싀은 λΆ„λͺ…ν•˜λ‹€. Button μ»΄ν¬λ„ŒνŠΈλ₯Ό React.memo() 둜 κ°μ‹Έλ³΄μž.
const Button = (props) => {
  console.log("Button RUNNING");
  return (
    <button
      type={props.type || "button"}
      className={`${classes.button} ${props.className}`}
      onClick={props.onClick}
      disabled={props.disabled}
    >
      {props.children}
    </button>
  );
};

export default React.memo(Button);
  • 이제 μ €μž₯을 ν•˜κ³ , μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μƒˆλ‘œκ³ μΉ¨ν•΄λ³΄μž.

  • μƒˆλ‘œκ³ μΉ¨ 해보면, "Button RUNNING" 이 ν‘œμ‹œλ˜κ³ , λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ λ‹€μ‹œ "Button RUNNING"이 좜λ ₯λœλ‹€. μš°λ¦¬λŠ” Button μ»΄ν¬λ„ŒνŠΈλ₯Ό React.memo()둜 감쌌고, 더이상 λ¦¬λ Œλ”λ§μ΄ λ˜μ§€ μ•Šλ„λ‘ μž‘μ—…ν–ˆλ‹€. ν•˜μ§€λ§Œ μ™œ 이런 일이 λ°œμƒν•˜λŠ” 걸까?

Button μ»΄ν¬λ„ŒνŠΈκ°€ 계속 λ¦¬λ Œλ”λ§ λ˜λŠ” 이유

  • "Button RUNNING"이 계속 좜λ ₯λœλ‹€λŠ” 것은 props의 값이 계속 λ°”λ€λ‹€λŠ” λœ»μ΄λ‹€.
const Button = (props) => {
  console.log("Button RUNNING");

  return (
    <button
      type={props.type || "button"}
      className={`${classes.button} ${props.className}`}
      onClick={props.onClick}
      disabled={props.disabled}
    >
      {props.children}
    </button>
  );
};

export default React.memo(Button);
  • Button μ»΄ν¬λ„ŒνŠΈλ₯Ό 확인해보면 μ•ˆμ—λŠ” onClick μ΄λΌλŠ” props와 children μ΄λΌλŠ” props λ₯Ό 가지고 μžˆλ‹€. ν•˜μ§€λ§Œ 이 λ‘˜ λͺ¨λ‘ 값은 λΆˆλ³€ 값이닀. children으둜 λ°›λŠ” ν…μŠ€νŠΈλ„ λ™μΌν•˜κ³ , onClick μ΄λΌλŠ” ν•¨μˆ˜λ„ λ™μΌν•˜λ‹€. 그리고 이것은 Reactμ—μ„œ ν”ν•˜κ²Œ λ°œμƒν•˜λŠ” 였λ₯˜ 쀑 ν•˜λ‚˜μ΄λ‹€.

App.js

function App() {
  const [showParagraph, setShowParagraph] = useState(false);

  console.log("APP RUNNING");

  const toggleParagraphHandler = () => {
    setShowParagraph((prevParagraph) => !prevParagraph);
  };

  return (
    <div className="app">
      <h1>Hi there!</h1>
      <DemoOutput show={false} />
      <Button onClick={toggleParagraphHandler}>Toggle Paragraph!</Button>
    </div>
  );
}
  • App μ»΄ν¬λ„ŒνŠΈλ₯Ό 보면, μ–΄μ¨Œκ±΄ ν•¨μˆ˜μ΄κΈ° λ•Œλ¬Έμ— 마치 일반적인 μžλ°”μŠ€ν¬λ¦½νŠΈ ν•¨μˆ˜μ²˜λŸΌ μž¬μ‹€ν–‰λ˜λŠ” κ±Έ μ•Œ 수 μžˆλ‹€. μ™œλƒν•˜λ©΄ κ²°κ΅­ 이것은 μƒνƒœ(state)κ°€ λ°”λ€Œλ©΄ 일반적인 μžλ°”μŠ€ν¬λ¦½νŠΈ ν•¨μˆ˜μ™€ κ°™κΈ° λ•Œλ¬Έμ΄λ‹€. μ—¬κΈ°μ„œ 쑰금 λ‹€λ₯Έ 점은 App μ»΄ν¬λ„ŒνŠΈ ν•¨μˆ˜λŠ” μ‚¬μš©μžκ°€ μ•„λ‹Œ React에 μ˜ν•΄ ν˜ΈμΆœλœλ‹€λŠ” 것 뿐이닀. κ·Έλ ‡μ§€λ§Œ μ—¬μ „νžˆ 일반 ν•¨μˆ˜μ²˜λŸΌ μ‹€ν–‰λ˜λŠ”λ° 이 말인 μ¦‰μŠ¨, μ½”λ“œκ°€ λ‹€μ‹œ μ‹€ν–‰λœλ‹€λŠ” μ˜λ―Έμ΄λ‹€. 이것은 무슨 뜻일까?
const toggleParagraphHandler = () => {
  setShowParagraph((prevParagraph) => !prevParagraph);
};
  • Button에 onClickμ΄λΌλŠ” props둜 μ „λ‹¬λ˜λŠ” 이 ν•¨μˆ˜λŠ” 맀번 μž¬μƒμ„±λœλ‹€. μ΄λŠ” App ν•¨μˆ˜μ˜ λͺ¨λ“  λ Œλ”λ§ λ˜λŠ” λͺ¨λ“  μ‹€ν–‰ μ‚¬μ΄ν΄μ—μ„œ 맀번 μƒˆλ‘œμš΄ ν•¨μˆ˜λΌλŠ” λœ»μ΄λ‹€. μš°λ¦¬κ°€ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ λ Œλ”λ§ 될 λ•Œλ§ˆλ‹€ 맀번 μƒˆλ‘œ λ§Œλ“€μ–΄μ§€λŠ” μƒμˆ˜μ΄κ³ , μž¬μ‚¬μš©λ˜μ§€ μ•ŠλŠ”λ‹€λŠ” μ˜λ―Έμ΄λ‹€.

App μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ‹€ν–‰λ˜λŠ” ν•¨μˆ˜λŠ” λ¦¬λ Œλ”λ§ 될 λ•Œλ§ˆλ‹€ λͺ¨λ‘ μƒˆλ‘œ λ§Œλ“€μ–΄μ§„λ‹€

  • App μ»΄ν¬λ„ŒνŠΈκ°€ λ¦¬λ Œλ”λ§ 될 λ•Œλ§ˆλ‹€ App μ»΄ν¬λ„ŒνŠΈ 내뢀에 μžˆλŠ” λͺ¨λ“  μ½”λ“œ μ—­μ‹œ λ‹€μ‹œ μ‹€ν–‰λ˜λ―€λ‘œ λ‹Ήμ—°ν•˜κ²Œλ„ μƒˆλ‘œμš΄ ν•¨μˆ˜μ™€ μƒμˆ˜λ“€μ΄ λ§Œλ“€μ–΄μ§„λ‹€. toggleParagraphHandler ν•¨μˆ˜ μ—­μ‹œ 이전에 λ Œλ”λ§ λ˜μ—ˆλ˜ toggleParagraphHandler ν•¨μˆ˜κ°€ μ•„λ‹ˆλ©°, κ·Έμ € 같은 κΈ°λŠ₯을 ν•˜λŠ” μƒˆλ‘œμš΄ toggleParagraphHandler ν•¨μˆ˜μΌ 뿐이닀. 이처럼, App μ»΄ν¬λ„ŒνŠΈ ν•¨μˆ˜κ°€ 싀행될 λ•Œλ§ˆλ‹€ λ§Œλ“€μ–΄μ§€λŠ” μƒμˆ˜μ™€ ν•¨μˆ˜λŠ” λͺ¨λ‘ μƒˆλ‘œμš΄ μƒμˆ˜μ™€ ν•¨μˆ˜μ΄λ‹€.
<DemoOutput show={false} />
  • 그런데 DemoOutput μ»΄ν¬λ„ŒνŠΈμ— false λ₯Ό props 둜 전달할 λ•Œμ—λ„ μ•žμ„œ μ„€λͺ…ν•œ μ˜ˆμ‹œλ“€μ΄ λͺ¨λ‘ ν•΄λ‹Ήλœλ‹€. κ·Έλ ‡μ§€λ§Œ Button μ»΄ν¬λ„ŒνŠΈμ²˜λŸΌ React.memo()둜 감싼 DemoOutput μ»΄ν¬λ„ŒνŠΈλŠ” λ¦¬λ Œλ”λ§ λ˜μ§€ μ•ŠλŠ”λ‹€. App μ»΄ν¬λ„ŒνŠΈ ν•¨μˆ˜κ°€ λ¦¬λ Œλ”λ§ 될 λ•Œλ§ˆλ‹€ false κ°’ μ—­μ‹œ 맀번 μƒˆλ‘œ λ§Œλ“€μ–΄μ§€λŠ”λ°λ„ λΆˆκ΅¬ν•˜κ³  말이닀. κ·Έλ ‡λ‹€λ©΄, μ™œ DemoOutput μ»΄ν¬λ„ŒνŠΈμ™€ 같은 경우처럼 λ³΄μ΄λŠ” Button μ»΄ν¬λ„ŒνŠΈλ§Œ λ¦¬λ Œλ”λ§ λ˜λŠ” κ²ƒμΌκΉŒ? false propsμ™€λŠ” 뭐가 λ‹€λ₯Έ κ²ƒμΌκΉŒ?

DemoOutput μ»΄ν¬λ„ŒνŠΈμ™€ Button μ»΄ν¬λ„ŒνŠΈμ™€μ˜ 차이점

  • DemoOutput에 props 둜 μ „λ‹¬ν•˜λŠ” falseλŠ” Boolean 값이고, λ¬Έμžμ—΄ λ˜λŠ” μˆ«μžμ—΄ 같은 μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ μ›μ‹œκ°’μœΌλ‘œ μ·¨κΈ‰λœλ‹€. React.memo()λŠ” props의 값을 ν™•μΈν•˜κ³  props.showλ₯Ό μ—…λ°μ΄νŠΈ μ΄μ „μ˜ props.show와 λΉ„κ΅ν•œλ‹€.
<DemoOutput show={false} />
  • μ΄λ ‡κ²Œ μ΄μ „μ˜ props.show와 μž¬μ‹€ν–‰λ˜μ–΄ μƒμ„±λœ μ΅œμ‹  κ°’ props.showλ₯Ό λΉ„κ΅ν•˜λŠ”λ° 이 μž‘μ—…μ€ 일반 비ꡐ μ—°μ‚°μžλ₯Ό 톡해 이루어진닀. 그리고 이 일반적인 비ꡐ μ—°μ‚°μžλŠ” 비ꡐ 값이 μ›μ‹œκ°’ λ•Œμ—μ„œλ§Œ μ˜¬λ°”λ₯΄κ²Œ 비ꡐ-계산할 수 있게 λœλ‹€.

React.memo()λŠ” 일반 비ꡐ μ—°μ‚°μžλ₯Ό 톡해 비ꡐ κ³„μ‚°ν•œλ‹€

false === false;
// true
"hi" === "hi";
// true
  • λ‘κ°œμ˜ boolean 값을 λΉ„κ΅ν•΄μ„œ true κ°€ λ‚˜μ™”λ‹€λ©΄, μ΄λŠ” λ™μΌν•œ 값이닀. λ‘κ°œμ˜ λ¬Έμžμ—΄μ„ λΉ„κ΅ν•΄μ„œ true κ°€ λ‚˜μ™”λ‹€λ©΄ 이 μ—­μ‹œ λ™μΌν•œ 값이닀. ν•˜μ§€λ§Œ 기술적으둜 λ”°μ§€μžλ©΄, 이 λ‘κ°œμ˜ boolean κ°’κ³Ό λ‘κ°œμ˜ λ¬Έμžμ—΄ 값은 μ„œλ‘œ λ‹€λ₯Έ 값이닀. ν•˜μ§€λ§Œ μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ μ›μ‹œκ°’μ΄λΌλ©΄ 이런 비ꡐ가 κ°€λŠ₯ν•˜λ‹€.
[1, 2] === [1, 2];
// false
  • κ·ΈλŸ¬λ‚˜, λ°°μ—΄μ΄λ‚˜ 객체, ν•¨μˆ˜λ₯Ό λΉ„κ΅ν•œλ‹€λ©΄ 말이 달라진닀. λ°°μ—΄μ΄λ‚˜ 객체, ν•¨μˆ˜λŠ” μ›μ‹œκ°’μ΄ μ•„λ‹ˆλΌ μ°Έμ‘°κ°’ 이기 λ•Œλ¬Έμ΄λ‹€. μš°λ¦¬κ°€ λ³΄κΈ°μ—λŠ” λ™μΌν•œ κ°’μ²˜λŸΌ λ³΄μ΄μ§€λ§Œ μžλ°”μŠ€ν¬λ¦½νŠΈ λ‚΄μ—μ„œλŠ” 이 λ‘κ°œμ˜ 배열은 같은 값이 μ•„λ‹ˆλ‹€. μ΄λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 핡심적인 κ°œλ…μ΄λ―€λ‘œ λ°˜λ“œμ‹œ μ΄ν•΄ν•΄ν•˜κ³  λ„˜μ–΄κ°€μ•Ό ν•œλ‹€.
<Button onClick={toggleParagraphHandler}>Toggle Paragraph!</Button>
  • λ‹€μ‹œ React둜 λŒμ•„μ™€μ„œ Button에 props 둜 λ„˜κ²¨μ£ΌλŠ” ν•¨μˆ˜λ₯Ό 보자. 직전에 κ±°λ‘ ν–ˆλ“―μ΄ μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ ν•¨μˆ˜λŠ” ν•˜λ‚˜μ˜ 객체이며 μ°Έμ‘° 값에 λΆˆκ³Όν•˜λ‹€. App μ»΄ν¬λ„ŒνŠΈ ν•¨μˆ˜κ°€ μž¬μ‹€ν–‰λ  λ•Œλ§ˆλ‹€ ν•¨μˆ˜ 내뢀에 μžˆλŠ” μ½”λ“œλ“€μ€ 재창쑰 되며, 이 toggleParagraphHandler ν•¨μˆ˜ μ—­μ‹œ μƒˆλ‘œ λ§Œλ“€μ–΄μ§„λ‹€. 그리고 React.memo()둜 감싼 Button μ»΄ν¬λ„ŒνŠΈλŠ” 이전에 μƒμ„±λœ props.onClickκ³Ό μƒˆλ‘­κ²Œ μƒμ„ λœ μ΅œμ‹  값인 props.onClickκ³Ό λΉ„κ΅ν•˜κ²Œ λœλ‹€. 그리고 λ‹Ήμ—°ν•˜κ²Œλ„ 이 λ‘κ°œμ˜ 비ꡐꡰ 값듀은 같은 λ‚΄μš©μ„ 가지고 μžˆλ‹€κ³  ν•˜λ”λΌλ„ μžλ°”μŠ€ν¬λ¦½νŠΈ λ‚΄μ—μ„œλŠ” λ™μΌν•œ 값이 μ•„λ‹ˆλΌκ³  μ·¨κΈ‰ν•  것이닀. (μ°Έμ‘° 값을 λΉ„κ΅ν•˜λŠ” 것이기 λ•Œλ¬Έμ΄λ‹€.)

정리

  • React.memo() κ°€ ν•˜λŠ” 일은 props 의 값을 ν™•μΈν•˜κ³ , μ΄μ „μ˜ props 와 κ°€μž₯ 졜근의 props μŠ€λƒ…μƒ·μ„ λΉ„κ΅ν•œλ‹€. 그리고 이 비ꡐ μž‘μ—…μ€ 일반적인 비ꡐ μ—°μ‚°μžλ₯Ό 톡해 이뀄진닀. 일반적인 μ›μ‹œ 값이라면 이런 일반적인 비ꡐ μ—°μ‚°μžλ₯Ό ν†΅ν•΄μ„œ 비ꡐ가 κ°€λŠ₯ν•  것이닀. ν•˜μ§€λ§Œ λ°°μ—΄μ΄λ‚˜ 객체, ν•¨μˆ˜λ₯Ό λΉ„κ΅ν•œλ‹€λ©΄ 말이 달라진닀. λ°°μ—΄μ΄λ‚˜ 객체, ν•¨μˆ˜λŠ” μ°Έμ‘° 값이기 λ•Œλ¬Έμ— 일반적인 비ꡐ μ—°μ‚°μžλ₯Ό ν†΅ν•΄μ„œλŠ” λ™μΌν•œ κ°’μœΌλ‘œ μ·¨κΈ‰ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€.
  • 이것은 React μ—μ„œμ˜ 일반적인 이슈 쀑 ν•˜λ‚˜λ‘œ, 이 λ•Œλ¬Έμ— λ§Žμ€ κ°œλ°œμžλ“€μ΄ 어렀움을 κ²ͺκ³  μžˆλ‹€. 그렇기에 React.memo()의 μž‘λ™λ°©μ‹ 즉, μžλ°”μŠ€ν¬λ¦½νŠΈ λ‚΄μ—μ„œ λΉ„κ΅μ—°μ‚°μžλ₯Ό 톡해 μ΄λ£¨μ–΄μ§€λŠ” μž‘λ™λ°©μ‹μ„ μ΄ν•΄ν•˜κ³  μ‚¬μš©ν•˜λŠ” 것은 무척 μ€‘μš”ν•œ 일이닀. κ·Έλ ‡λ‹€λ©΄, React.memo()λŠ” propsλ₯Ό ν†΅ν•œ κ°μ²΄λ‚˜ λ°°μ—΄ λ˜λŠ” ν•¨μˆ˜λ₯Ό κ°€μ Έμ˜€λŠ” μ»΄ν¬λ„ŒνŠΈμ—λŠ” μ‚¬μš©ν•  수 μ—†λŠ” 걸까? λ‹€ν–‰νžˆλ„ ν•΄κ²° 방법은 μ‘΄μž¬ν•œλ‹€.

✧ useCallback() 으둜 ν•¨μˆ˜ μž¬μƒμ„± λ°©μ§€ν•˜κΈ°

  • React.memo()둜 props둜 μ „λ‹¬ν•˜λŠ” κ°μ²΄λ‚˜ λ°°μ—΄ ν˜Ήμ€ ν•¨μˆ˜μ—λ„ μž‘λ™ν•˜κ²Œλ” λ§Œλ“€ 수 μžˆλ‹€. 객체λ₯Ό μƒμ„±ν•˜κ³  μ €μž₯ν•˜λŠ” 방식을 쑰금 λ³€κ²½ν•΄μ€€λ‹€λ©΄ 말이닀. 그리고 이 μž‘μ—…μ€ React μ—μ„œ μ œκ³΅ν•˜λŠ” hook 을 ν†΅ν•΄μ„œ κ°€λŠ₯ν•˜λ‹€. λ°”λ‘œ useCallback() μ΄λΌλŠ” hook 이닀.

useCallback μ‚¬μš©ν•˜κΈ°

React 곡식 λ¬Έμ„œ μ°Έμ‘° : useCallback()

  • useCallback 은 기본적으둜 μ»΄ν¬λ„ŒνŠΈ μ‹€ν–‰ μ „λ°˜μ— 걸쳐 ν•¨μˆ˜λ₯Ό μ €μž₯ν•  수 μžˆλ„λ‘ ν•˜λŠ” hook 으둜써 useCallbackλ₯Ό ν†΅ν•΄μ„œ 감싼 ν•¨μˆ˜λ₯Ό μ €μž₯ν•˜μ—¬ 이 ν•¨μˆ˜κ°€ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 맀번 싀행될 λ•Œλ§ˆλ‹€ μž¬μƒμ„±ν•  ν•„μš”κ°€ μ—†λ‹€λŠ” 것을 React에 μ•Œλ¦¬λŠ” 역할을 ν•œλ‹€. useCallback을 μ‚¬μš©ν•˜μ—¬ νŠΉμ • ν•¨μˆ˜λ₯Ό 감싼닀면, 이 ν•¨μˆ˜ 객체가 λ©”λͺ¨λ¦¬μ˜ λ™μΌν•œ μœ„μΉ˜μ— μ €μž₯λ˜λ―€λ‘œ 이λ₯Ό 톡해 비ꡐ μž‘μ—…μ„ ν•  수 있게 λœλ‹€. ꡬ체적으둜 예λ₯Ό λ“€μ–΄λ³΄μž.
let obj1 = {};
let obj2 = {};
  • μ—¬κΈ° λ‘κ°œμ˜ 객체가 μžˆλ‹€. 이 λ‘˜μ€ λΉ„μŠ·ν•΄λ³΄μΌμ§€ λͺ¨λ₯΄κ² μ§€λ§Œ, 적어도 μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” λΆ„λͺ… 이 λ‘κ°œμ˜ κ°μ²΄λŠ” λ™μΌν•œ 취급을 받을 수 없을 것이닀.
let obj1 = {};
let obj2 = {};

obj1 === obj2;
// false
  • ν•˜μ§€λ§Œ obj1κ³Ό obj2κ°€ 같은 λ©”λͺ¨λ¦¬ μ•ˆμ˜ 같은 μœ„μΉ˜λ₯Ό 가리킀고 μžˆλ‹€λ©΄ μ–΄λ–¨κΉŒ?
let obj1 = {};
let obj2 = {};

obj1 = obj2;
  • λ™μΌν•œ λ©”λͺ¨λ¦¬ μ•ˆμ˜ 같은 μœ„μΉ˜λ₯Ό 가리킀도둝 obj1에 obj2λ₯Ό ν• λ‹Ήν•΄λ³΄μž.
let obj1 = {};
let obj2 = {};
obj1 = obj2;

obj1 === obj2;
// true
  • μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 이 obj1에 obj2λ₯Ό 같은 객체둜 κ°„μ£Όν•˜κ²Œ λœλ‹€. μ΄λŠ” useCallback이 ν•˜λŠ” 일과 μ •ν™•ν•˜κ²Œ λ™μΌν•œ 역할을 ν•œλ‹€.
const toggleParagraphHandler = () => {
  setShowParagraph((prevParagraph) => !prevParagraph);
};
  • μš°λ¦¬κ°€ μ„ νƒν•œ ν•¨μˆ˜λ₯Ό React 의 λ‚΄λΆ€ λ©”λͺ¨λ¦¬μ— μ €μž₯ν•΄μ„œ ν•΄λ‹Ή ν•¨μˆ˜ 객체가 μž¬μ‹€ν–‰ 될 λ•Œλ§ˆλ‹€ 이λ₯Ό μž¬μ‚¬μš©ν•  수 μžˆλ„λ‘ ν•˜λŠ” 것이닀. useCallback의 μ‚¬μš©λ²•λ„ 맀우 κ°„λ‹¨ν•˜λ‹€.
const toggleParagraphHandler = useCallback(() => {
  setShowParagraph((prevParagraph) => !prevParagraph);
});
  • useCallback으둜 μ €μž₯ν•˜λ €λŠ” ν•¨μˆ˜λ₯Ό λž˜ν•‘ν•˜κΈ°λ§Œ ν•˜λ©΄ λœλ‹€. useCallback을 ν†΅ν•΄μ„œ μ–΄λ–€ ν•¨μˆ˜λ₯Ό 첫 번째 인자둜 μ „λ‹¬ν•˜λ©΄, useCallbackλŠ” 이 μ €μž₯된 ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•œλ‹€. 이런 μž‘λ™ 과정을 ν†΅ν•΄μ„œ App μ»΄ν¬λ„ŒνŠΈ ν•¨μˆ˜κ°€ μž¬μ‹€ν–‰λ  λ•Œλ§ˆλ‹€ useCallback 이 React 의 λ‚΄λΆ€ λ©”λͺ¨λ¦¬μ— μ €μž₯된 ν•¨μˆ˜λ₯Ό μ°Ύμ•„μ„œ μž¬μ‚¬μš©ν•˜λŠ” 것이닀. λ”°λΌμ„œ, μ–΄λ–€ ν•¨μˆ˜κ°€ μ ˆλŒ€ λ³€κ²½λ˜μ–΄μ„œλŠ” μ•ˆλœλ‹€λ©΄, 이 useCallback hook 을 μ‚¬μš©ν•΄μ„œ κ·Έ ν•¨μˆ˜λ₯Ό React λ‚΄λΆ€μ˜ λ©”λͺ¨λ¦¬μ— μ €μž₯ν•˜λ©΄ λœλ‹€.
const toggleParagraphHandler = useCallback(() => {
  setShowParagraph((prevParagraph) => !prevParagraph);
}, []);
  • useCallback 은 λ‘κ°œμ˜ μΈμžκ°€ ν•„μš”ν•œλ° 첫 번째 μΈμžλŠ” μ•žμ„œ κ±°λ‘ ν•œ ν•¨μˆ˜μ΄κ³ , 두 번째 μΈμžλŠ” μ˜μ‘΄μ„± 배열이닀. μ˜μ‘΄μ„± 배열은 useEffect hook μ—μ„œ λ§ν•˜λŠ” μ˜μ‘΄μ„± λ°°μ—΄κ³Ό 같은 의미둜 쓰인닀.
  • useCallback ν˜ΈμΆœμ— λŒ€ν•œ μ˜μ‘΄μ„± 배열은 첫 번째 인자인 ν•¨μˆ˜λ₯Ό 감싼 μ»΄ν¬λ„ŒνŠΈλ‘œλΆ€ν„° μ „λ‹¬λ°›λŠ” λͺ¨λ“  것을 μ‚¬μš©ν•  수 μžˆλ‹€. (useEffect 처럼) 즉, μƒνƒœ(state)λ‚˜ props, μ»¨ν…μŠ€νŠΈ 같은 것 말이닀.
const toggleParagraphHandler = useCallback(() => {
  setShowParagraph((prevParagraph) => !prevParagraph);
}, []);
  • 이 toggleParagraphHandler ν•¨μˆ˜μ—μ„œλŠ” μ—…λ°μ΄νŠΈ ν•¨μˆ˜ setShowParagraph λ₯Ό λͺ…μ‹œν•˜λ©΄ λœλ‹€. λ¬Όλ‘  setShowParagraph을 μ˜μ‘΄μ„± λ°°μ—΄ μ•ˆμ— μΆ”κ°€ν•  μˆ˜λ„ μžˆμ§€λ§Œ Reactκ°€ useCallback을 톡해 ν•΄λ‹Ή ν•¨μˆ˜λŠ” μ ˆλŒ€ λ³€ν•˜μ§€ μ•ŠμœΌλ©°, 이전과 λ™μΌν•œ ν•¨μˆ˜ κ°μ²΄μž„μ„ 보μž₯ν•˜κ³  있기 λ•Œλ¬Έμ— ꡳ이 μΆ”κ°€ν•  ν•„μš”κ°€ μ—†μ–΄μ„œ μƒλž΅ν•˜μ˜€λ‹€. λ‹€λ§Œ 이런 μ½”λ“œλŠ” setShowParagraph 에 μ „λ‹¬λœ ν•¨μˆ˜λΌλŠ” κ±Έ κΈ°μ–΅λ§Œ ν•˜λ©΄ 될 것이닀. κΈ°μ–΅ν•œλ‹€λŠ” 것은 즉, 이 λͺ¨λ‘κ°€ 콜백 ν•¨μˆ˜μ— ν¬ν•¨λ˜μ–΄ μžˆλ‹€λŠ” λœ»μ΄λ‹€.

정리

  • ν˜„μž¬ toggleParagraphHandler ν•¨μˆ˜λ₯Ό 감싼 useCallback의 μ˜μ‘΄μ„± 배열은 React에 toggleParagraphHandler ν•¨μˆ˜λ₯Ό μ €μž₯ν•˜λ €κ³  ν•˜λŠ” 이 콜백 ν•¨μˆ˜λŠ” μ ˆλŒ€ λ³€κ²½λ˜μ§€ μ•Šμ„ 것이라고 React에 μ•Œλ €μ£ΌλŠ” 역할을 ν•œλ‹€. λ”°λΌμ„œ App μ»΄ν¬λ„ŒνŠΈκ°€ λ‹€μ‹œ λ¦¬λ Œλ”λ§ λ˜μ–΄λ„ 항상 같은 ν•¨μˆ˜ 객체가 μ‚¬μš©λ˜κ²Œλ” ν•˜λŠ” 것이닀.

  • μ €μž₯ν•˜κ³  μƒˆλ‘œκ³ μΉ¨ 해보면, λ²„νŠΌμ„ μ—¬λŸ¬ 번 클릭해봐도 더이상 "Button RUNNING" 문ꡬ가 좜λ ₯λ˜μ§€ μ•ŠλŠ” 것을 μ•Œ 수 μžˆλ‹€. μš°λ¦¬κ°€ μ „λ‹¬ν•œ λͺ¨λ“  props 값이 μ›μ‹œ κ°’ 뿐만 μ•„λ‹ˆλΌ ν•¨μˆ˜ λ˜ν•œ useCallback을 톡해 일반 비ꡐ μ—°μ‚°μžλ₯Ό 톡해 비ꡐ가 κ°€λŠ₯ν•˜λ„λ‘ μ „λ‹¬ν–ˆκΈ° λ•Œλ¬Έμ— React.memo()이 역할을 μ œλŒ€λ‘œ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ ν–ˆκΈ° λ•Œλ¬Έμ΄λ‹€. 즉, useCallback 덕뢄에 toggleParagraphHandler 객체가 React의 λ©”λͺ¨λ¦¬ μ•ˆμ—μ„œ 항상 같은 κ°μ²΄μž„μ„ 보μž₯ν•˜κ³  μžˆλŠ” 것이닀.

✧ useCallback() 및 쒅속성에 λŒ€ν•˜μ—¬

  • useCallback 을 μ΄μš©ν•˜λ©΄ ν•¨μˆ˜λ₯Ό μ €μž₯ν•˜κ³  이λ₯Ό μž¬μ‚¬μš©ν•  수 있게 λœλ‹€.
const toggleParagraphHandler = useCallback(() => {
  setShowParagraph((prevParagraph) => !prevParagraph);
}, []);
  • 이제 useCallback 으둜 μ €μž₯ν•œ ν•¨μˆ˜μ˜ μ˜μ‘΄μ„± 배열을 지정해야 ν•˜λŠ”λ°, 이 μ˜μ‘΄μ„± 배열이 μ™œ ν•„μš”ν•œμ§€μ— λŒ€ν•΄μ„œ μ˜μ•„ν•  μˆ˜κ°€ μžˆλ‹€. μ§€κΈˆμ˜ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ λ‚΄μ˜ ν•¨μˆ˜λŠ” λͺ¨λ“  μž¬λ Œλ”λ§ μ£ΌκΈ°λ§ˆλ‹€ 항상 λ˜‘κ°™μ€ λ‘œμ§μ„ μ“°λŠ”λ°, 이 μ˜μ‘΄μ„± 배열은 μ™œ ν•„μš”ν•œ κ²ƒμΌκΉŒ?

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œμ˜ ν•¨μˆ˜λŠ” ν΄λ‘œμ €μ΄λ‹€.

  • μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œμ˜ ν•¨μˆ˜λŠ” ν΄λ‘œμ €μ΄λ‹€. 즉, 이 ν™˜κ²½μ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” 값에 ν΄λ‘œμ €λ₯Ό λ§Œλ“€κ²Œ λœλ‹€. ꡬ체적인 μ˜ˆμ‹œλ₯Ό 톡해 μ΄ν•΄ν•΄λ³΄μž.
  <DemoOutput show={showParagraph} />
  <Button>Allow Toggling</Button>
  <Button onClick={toggleParagraphHandler}>Toggle Paragraph!</Button>
  • App μ»΄ν¬λ„ŒνŠΈκ°€ λ Œλ”ν•˜λŠ” Button μ»΄ν¬λ„ŒνŠΈ μœ„μ— "Allow Toggling" μ΄λΌλŠ” ν…μŠ€νŠΈλ₯Ό 넣은 Button μ»΄ν¬λ„ŒνŠΈ ν•˜λ‚˜λ₯Ό 더 μΆ”κ°€ν•œλ‹€. 이 λ²„νŠΌμ€ Toggle κΈ°λŠ₯을 ν™œμ„±ν™”ν•΄μ„œ μ•„λž˜μ˜ λ²„νŠΌμ΄ μž‘λ™ν•˜κ²Œλ” ν•˜λŠ” λ²„νŠΌμœΌλ‘œ λ§Œλ“€ 것이닀.
const [allowToggle, setAllowToggle] = useState(false);
  • Toggle 의 ν™œμ„±ν™”/λΉ„ν™œμ„±ν™” κΈ°λŠ₯을 μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” 이 λ²„νŠΌμ˜ μƒνƒœ(state)κ°€ ν•„μš”ν•  것이닀. allowToggle μƒνƒœ(state)λ₯Ό μΆ”κ°€ν•΄μ£Όμž. μ΄ˆκΈ°κ°’μ€ false 둜 μ„€μ •ν•΄μ€€λ‹€. 그리고 ν•΄λ‹Ή Toggle κΈ°λŠ₯을 μ μš©ν•  λ²„νŠΌμ— onClick 이벀트둜 ν•΄λ‹Ή 트리거 ν•¨μˆ˜λ₯Ό ν• λ‹Ήν•œλ‹€.
const allowToggleHandler = () => {
  setAllowToggle(true);
};

...
<Button onClick={allowToggleHandler}>Allow Toggling</Button>;
  • Toggle 을 ν•  것인지 말 것인지λ₯Ό κ²°μ •ν•˜λŠ” μƒνƒœ(state)λ₯Ό ν•Έλ“€λ§ν•˜λŠ” 트리거 ν•¨μˆ˜ allowToggleHandler도 μž‘μ„±ν•œλ‹€. ν•΄λ‹Ή ν•¨μˆ˜κ°€ 트리거 될 λ•Œλ§ˆλ‹€ setAllowToggle μƒνƒœ μ—…λ°μ΄νŠΈ ν•¨μˆ˜λ‘œ true κ°’μœΌλ‘œ μ—…λ°μ΄νŠΈν•  것이닀. (이 ν•¨μˆ˜λŠ” Toggle 자체의 μƒνƒœ(state)κ°€ μ•„λ‹ˆλΌ Toggle을 μ›€μ§μ΄λŠ” λ²„νŠΌ μžμ²΄μ— λŒ€ν•œ Toggle을 ν™œμ„±ν™”ν•  뿐이닀.)
  • μ—¬κΈ°μ—μ„œ λ¬Έμ œκ°€ λ°œμƒν•  μˆ˜λ„ μžˆλŠ”λ°, μƒˆλ‘œμš΄ λ²„νŠΌμ— allowToggleHandlerλ₯Ό λ°”μΈλ”©ν•˜λŠ” 것 외에도 μ—¬κΈ°μ˜ λ‹€λ₯Έ ν•¨μˆ˜(toggleParagraphHandler)μ—μ„œ allowToggle μƒνƒœ(state) μŠ€λƒ…μƒ·μ„ μ΄μš©ν•΄μ„œ setShowParagraphλ₯Ό μ‚¬μš©ν•  수 μžˆλŠ”μ§€ 확인할 것이기 λ•Œλ¬Έμ΄λ‹€.
const toggleParagraphHandler = useCallback(() => {
  if (allowToggle) {
    setShowParagraph((prevParagraph) => !prevParagraph);
  }
}, []);
  • ν…μŠ€νŠΈλ₯Ό Toggle ν•΄μ£Όμ—ˆλ˜ 트리거 ν•¨μˆ˜μΈ toggleParagraphHandler 둜 λŒμ•„κ°€ allowToggle μƒνƒœ(state) μŠ€λƒ…μƒ·μ— 따라 μ•„λž˜μ˜ λ²„νŠΌμ˜ μƒνƒœ(state)κ°€ μ—…λ°μ΄νŠΈ λ˜λ„λ‘ μž‘μ„±ν•΄μ€€λ‹€. if 문을 μ‚¬μš©ν•΄μ„œ λ§Œμ•½ allowToggle(Toggle λ²„νŠΌμ„ μ‹€ν–‰ν•  수 μžˆλŠ”μ§€λ₯Ό μ²΄ν¬ν•˜λŠ” μƒνƒœ κ°’)이 true 일 λ•Œλ§Œ setShowParagraph μƒνƒœ(state) μ—…λ°μ΄νŠΈ ν•¨μˆ˜κ°€ 싀행될 수 μžˆλ„λ‘ μž‘μ„±ν•΄μ€€λ‹€. μ΄λ ‡κ²Œ 되면, showParagraph μƒνƒœ(state)λŠ” Toggle 이 ν—ˆμš©λ˜λŠ” 경우(allowToggleκ°€ true 일 λ•Œ)만 μ—…λ°μ΄νŠΈν•˜κ²Œ λœλ‹€.

  • μ €μž₯ν•˜κ³  μ½˜μ†”μ°½μ„ ν™•μΈν•΄λ³΄μž. λ°”λ‘œ Toggle Paragraph! λ²„νŠΌμ„ λˆ„λ₯΄κ²Œ 되면 ν…μŠ€νŠΈκ°€ λ³΄μ—¬μ§€κ±°λ‚˜ ν•˜λŠ” λ“±μ˜ μ•‘μ…˜μ΄ μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€. 그리고 Allow Toggling λ²„νŠΌμ„ λˆ„λ₯΄κ³  λ‹€μ‹œ Toggle Paragraph! λ²„νŠΌμ„ 눌러보자. μ½˜μ†”μ—λŠ” λΆ„λͺ… 'App RUNNING' 이 좜λ ₯되고 μžˆμ§€λ§Œ, λ²„νŠΌμ˜ κΈ°λŠ₯은 μž‘λ™λ˜μ§€ μ•ŠλŠ”λ‹€. μš°λ¦¬κ°€ μ˜λ„ν•œ λŒ€λ‘œ μž‘λ™λ˜μ§€ μ•Šκ³  μžˆλŠ” 것이닀. μ™œ 그럴까?

  • μ™œλƒν•˜λ©΄ μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ ν•¨μˆ˜λŠ” ν΄λ‘œμ €μ΄λ©° μš°λ¦¬κ°€ useCallback을 μ œλŒ€λ‘œ μ‚¬μš©ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ΄λ‹€. μœ„μ˜ 이미지λ₯Ό 보면 μ˜μ‘΄μ„± λ°°μ—΄ [] 뢀뢄에 νŽΈμ§‘κΈ°μ—μ„œ μ½”λ“œ μž‘μ„±μ— λ¬Έμ œκ°€ μžˆμŒμ„ ν‘œμ‹œν•΄μ£Όκ³  μžˆλ‹€.

λ²„νŠΌμ„ λˆŒλŸ¬λ„ λ°˜μ‘ν•˜μ§€ μ•ŠλŠ” 이유

  • μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ ν•¨μˆ˜λŠ” ν΄λ‘œμ €μ΄λ‹€. 이 말인 μ¦‰μŠ¨, useCallback μ—μ„œ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜κ°€ μ •μ˜λ˜λ©΄(App μ»΄ν¬λ„ŒνŠΈ ν•¨μˆ˜ 내뢀에 μžˆλŠ” λͺ¨λ“  μ½”λ“œλ“€) 이 ν•¨μˆ˜(useCallback μ—μ„œ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜)κ°€ μ •μ˜λ  λ•Œ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 이 ν•¨μˆ˜ μ•ˆμ—μ„œ μ‚¬μš©λ˜λŠ” λͺ¨λ“  λ³€μˆ˜λ₯Ό 잠그게 λœλ‹€. λ¬Όλ‘  ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œ μ‚¬μš©ν•˜λŠ” λͺ¨λ“  λ³€μˆ˜λΌκ³  ν•΄μ•Ό 쑰금 더 μ •ν™•ν•œ μ„€λͺ…일 것이닀.
const toggleParagraphHandler = useCallback(() => {
  if (allowToggle) {
    setShowParagraph((prevParagraph) => !prevParagraph);
  }
}, []);
  • μ—¬κΈ°μ—μ„œλŠ” allowToggle이 μ•žμ„œ μ„€λͺ…ν•œ κ²½μš°μ— ν•΄λ‹Ήν•˜λŠ”λ° allowToggleλŠ” App μ»΄ν¬λ„ŒνŠΈ ν•¨μˆ˜ 외뢀에 μžˆλŠ” λ³€μˆ˜λ‚˜ μƒμˆ˜μ΄κ³ ,
const [allowToggle, setAllowToggle] = useState(false);
  • 이λ₯Ό useCallback μ—μ„œ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜ μ•ˆμ—μ„œ μ‚¬μš©ν•˜κ³  μžˆλ‹€.
useCallback(() => {
  if (allowToggle) {
    setShowParagraph((prevParagraph) => !prevParagraph);
  }
}, [allowToggle]);
  • λ”°λΌμ„œ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 이 allowToggle에 ν΄λ‘œμ €λ₯Ό λ§Œλ“€κ³ , ν•΄λ‹Ή ν•¨μˆ˜λ₯Ό μ •μ˜ν•  λ•Œ μ‚¬μš©ν•˜κΈ° μœ„ν•΄ λ³€μˆ˜(allowToggle)λ₯Ό μ €μž₯ν•œλ‹€.

  • 그리고 μ΄λ ‡κ²Œ 되면, λ‹€μŒμ— toggleParagraphHandler ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜λ©΄ 이 μ €μž₯된 λ³€μˆ˜(allowToggle)λ₯Ό κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜κ²Œ λœλ‹€. λ”°λΌμ„œ 이 λ³€μˆ˜μ˜ 값은 λ³€μˆ˜κ°€ μ €μž₯된 μ‹œμ (allowToggle의 ν΄λ‘œμ €λ₯Ό λ§Œλ“€ λ•Œ)의 값을 μ‚¬μš©ν•˜κ²Œ 되고, ν•¨μˆ˜ λ°–μ˜ λ³€μˆ˜λ₯Ό ν•¨μˆ˜ μ•ˆμ—μ„œ μ‚¬μš©ν•  수 있으며 μš°λ¦¬κ°€ μ›ν•˜λŠ” μ‹œμ μ— ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  수 있게 λœλ‹€.

λ³€μˆ˜μ˜ 값은 λ³€μˆ˜κ°€ μ €μž₯된 μ‹œμ μ˜ 값을 μ‚¬μš©ν•œλ‹€.

  • allowToggle 의 값은 allowToggle κ°€ μ €μž₯된 μ‹œμ μ˜ 값을 μ‚¬μš©ν•œλ‹€. μ΄λŠ” μ–Έλœ» 보기에 μ™„λ²½ν•œ κΈ°λŠ₯처럼 보인닀. 이런 κΈ°λŠ₯을 μ‚¬μš©ν•˜λ©΄ useCallback μ—μ„œ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜ λ°–μ˜ λ³€μˆ˜λ₯Ό ν•΄λ‹Ή ν•¨μˆ˜ μ•ˆμ—μ„œ μ‚¬μš©ν•  수 있으며 μš°λ¦¬κ°€ μ›ν•˜λŠ” μ‹œμ μ— ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  수 있기 λ•Œλ¬Έμ΄λ‹€.
<Button onClick={toggleParagraphHandler}>Toggle Paragraph!</Button>
  • λ²„νŠΌμ— λ°”μΈλ”©ν•œ toggleParagraphHandler ν•¨μˆ˜μ²˜λŸΌ 말이닀.

useCallback은 ν•¨μˆ˜λ₯Ό μž¬μƒμ„±ν•˜μ§€ λͺ»ν•˜λ„둝 ν•œλ‹€.

  • κ·ΈλŸ¬λ‚˜, μ—¬κΈ°μ„œ λ¬Έμ œκ°€ λ°œμƒν•œλ‹€. μš°λ¦¬λŠ” useCallback을 μ‚¬μš©ν•˜μ—¬ λ¦¬μ•‘νŠΈμ—κ²Œ ν•΄λ‹Ή ν•¨μˆ˜λ₯Ό μ €μž₯ν•˜λΌκ³  μ§€μ‹œν•  수 μžˆλ‹€. 이러면 이 ν•¨μˆ˜λŠ” λ©”λͺ¨λ¦¬ μ–΄λ”˜κ°€μ— μ €μž₯λœλ‹€. App ν•¨μˆ˜κ°€ ν† κΈ€ μƒνƒœκ°€ λ³€κ²½λ˜μ–΄ μž¬ν‰κ°€, μž¬μ‹€ν–‰λ˜λ©΄ λ¦¬μ•‘νŠΈλŠ” 이 ν•¨μˆ˜λ₯Ό μž¬μƒμ„± ν•˜μ§€ μ•Šμ„ 것이닀. μ™œ 그럴까? μ™œλƒν•˜λ©΄ μš°λ¦¬κ°€ useCallback을 톡해 λ¦¬μ•‘νŠΈμ—κ²Œ μ–΄λ–€ ν™˜κ²½μ—μ„œλ“  ν•¨μˆ˜ μž¬μƒμ„±μ„ ν•˜μ§€ μ•Šλ„λ‘ μ˜λ„μ μœΌλ‘œ λ§‰μ•˜κΈ° λ•Œλ¬Έμ΄λ‹€.
useCallback(() => {
  if (allowToggle) {
    setShowParagraph((prevParagraph) => !prevParagraph);
  }
}, []);
  • λ”°λΌμ„œ λ¦¬μ•‘νŠΈκ°€ 이 ν•¨μˆ˜μ— μ‚¬μš©ν•˜κΈ° μœ„ν•΄ μ €μž₯ν•œ allowToggle의 값은 μ΅œμ‹  μŠ€λƒ…μƒ·μ˜ 값이 μ•„λ‹ˆλΌ, App μ»΄ν¬λ„ŒνŠΈκ°€ 처음 μ‹€ν–‰λœ μ‹œμ μ˜ 값을 μ €μž₯ν•˜κ³  μžˆμ„ 뿐이닀. 이전에 κ±°λ‘ ν–ˆλ“―μ΄ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” ν•¨μˆ˜ 생성 μ‹œμ μ˜ allowToggle μƒμˆ˜μ˜ 값을 μ €μž₯ν•˜κ³  있기 λ•Œλ¬Έμ΄λ‹€. 그리고 λ‹Ήμ—°νžˆ 이런 점 λ•Œλ¬Έμ— 였λ₯˜λŠ” λ°œμƒν•œλ‹€. μš°λ¦¬κ°€ μ˜λ„μ μœΌλ‘œ useCallback을 μ‚¬μš©ν•΄μ„œ λ¦¬μ•‘νŠΈμ— ν•¨μˆ˜λ₯Ό μ €μž₯ν•˜λΌκ³  μ§€μ‹œν•˜κ³ , App μ»΄ν¬λ„ŒνŠΈκ°€ λ³€κ²½λ˜μ–΄ μž¬ν‰κ°€, μž¬μ‹€ν–‰λ˜λ„ 더이상 ν•΄λ‹Ή ν•¨μˆ˜κ°€ μž¬μƒμ„±ν•˜μ§€ μ•Šλ„λ‘ ν–ˆκΈ° λ•Œλ¬Έμ΄λ‹€. ν•˜μ§€λ§Œ λ•Œλ•Œλ‘œ μš°λ¦¬λŠ” ν•΄λ‹Ή ν•¨μˆ˜μ˜ μž¬μƒμ„±μ΄ ν•„μš”λ‘œ 할지도 λͺ¨λ₯Έλ‹€. κ·ΈλŸ¬λ‹ˆκΉŒ ν•΄λ‹Ή ν•¨μˆ˜μ—μ„œ μ‚¬μš©ν•˜λŠ” 즉 ν•¨μˆ˜ μ™ΈλΆ€μ—μ„œ μ˜€λŠ” κ°’(allowToggle)이 μ—…λ°μ΄νŠΈ 될지도 λͺ¨λ₯΄λŠ” κ°€λŠ₯성이 μžˆλ‹€λŠ” 이야기닀. μ§€κΈˆμ˜ μ‚¬λ‘€μ²˜λŸΌ 말이닀.
const toggleParagraphHandler = useCallback(() => {
  if (allowToggle) {
    setShowParagraph((prevParagraph) => !prevParagraph);
  }
}, []);

allowToggle 을 쒅속 ν˜•νƒœλ‘œ μΆ”κ°€ν•˜κΈ°

  • μš°λ¦¬λŠ” allowToggle을 useCallback에 쒅속성에 μΆ”κ°€ν•˜λ €κ³  ν•œλ‹€. μ΄λ ‡κ²Œ 되면, useCallback을 톡해 λ¦¬μ•‘νŠΈμ— ν•¨μˆ˜λ₯Ό μ €μž₯ν•˜λΌκ³  μ§€μ‹œν–ˆμ–΄λ„, 쒅속 ν˜•νƒœλ‘œ μΆ”κ°€λœ allowToggle의 값이 μ—…λ°μ΄νŠΈ λ˜κ±°λ‚˜ μƒˆλ‘œμš΄ 값이 듀어왔을 λ•Œ ν•΄λ‹Ή ν•¨μˆ˜λ₯Ό μž¬μƒμ„± ν•˜κ³ , 이 μž¬μƒμ„±λœ ν•¨μˆ˜λ‘œ μ €μž₯ν•  수 있게 λœλ‹€.
const toggleParagraphHandler = useCallback(() => {
  if (allowToggle) {
    setShowParagraph((prevParagraph) => !prevParagraph);
  }
}, [allowToggle]);
  • μ΄λ ‡κ²Œ 되면, allowToggle의 μ΅œμ‹  κ°’λ§Œμ„ μ‚¬μš©ν•  수 μžˆλ‹€. λ˜ν•œ allowToggle이 λ³€κ²½λ˜μ§€λ§Œ μ•ŠλŠ”λ‹€λ©΄ ν•¨μˆ˜λ₯Ό μž¬μƒμ„±ν•˜μ§€ μ•Šκ²Œ λ˜μ—ˆλ‹€. 즉, useCallback을 ν†΅ν•œ λΆˆν•„μš”ν•œ μž¬μƒμ„±μ„ λ°©μ§€ν•˜λŠ” μž₯점과, ν•΄λ‹Ή ν•¨μˆ˜μ—μ„œ μ‚¬μš©ν•˜λŠ” λ³€μˆ˜μ˜ 값을 μ΅œμ‹  κ°’μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλŠ” μž₯점을 λͺ¨λ‘ μ±™κΈΈ 수 있게 λ˜μ—ˆλ‹€.

  • μ €μž₯ν•˜κ³  ν™”λ©΄μœΌλ‘œ λŒμ•„κ°€μ„œ λ‹€μ‹œ "Toggle Paragraph!" λ²„νŠΌμ„ 눌러보자. λ‹Ήμ—°νžˆ μ²˜μŒμ—λŠ” 아무 λ°˜μ‘μ΄ μ—†λ‹€. λ‹€μ‹œ "Allow Toggling" λ²„νŠΌμ„ λˆ„λ₯΄κ³ , "Toggle Paragraph!" 을 λˆ„λ₯΄λ©΄ λ“œλ””μ–΄ μš°λ¦¬κ°€ μ›ν–ˆλ˜ λͺ¨λ“  좜λ ₯듀이 ν‘œμ‹œλœλ‹€. "Toggle Paragraph!" λ²„νŠΌμ„ λˆŒλ €μ„ λ•Œ "Button RUNNING" 이 ν•œ 번만 좜λ ₯λ˜λŠ” 것도 λˆˆμ—¬κ²¨λ΄μ•Ό ν•  뢀뢄이닀. λ‹Ήμ—°νžˆ React.memoκ°€ 두 번째 λ²„νŠΌμ—μ„œλŠ” μž‘λ™ν•˜μ§€ μ•ŠλŠ”λ‹€. μ™œλƒν•˜λ©΄ "Allow Toggling" λ²„νŠΌμ— μ—°κ²°λœ ν•¨μˆ˜μΈ allowToggleHandlerλŠ” useCallback을 μ‚¬μš©ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ΄λ‹€. "Toggle Paragraph!" λ²„νŠΌμ΄ λ‹€μ‹œ λ Œλ”λ§ λœλ‹€λ©΄ 두 번 ν‘œμ‹œλ˜κ² μ§€λ§Œ, useCallback이 ν•΄λ‹Ή ν•¨μˆ˜κ°€ 맀 번 λ‹€μ‹œ λΉŒλ“œλ˜λŠ” 것을 μ˜λ„μ μœΌλ‘œ λ§‰μ•˜κΈ° λ•Œλ¬Έμ— λ‹€λ§Œ μ˜μ‘΄μ„±μœΌλ‘œ μ£Όμž…λœ allowToggle μƒνƒœκ°€ 변경될 λ•Œλ§Œ ν•΄λ‹Ή 문ꡬλ₯Ό λ³Ό 수 μžˆλ‹€.

정리

  • μ§€κΈˆκΉŒμ§€μ˜ κ°œλ…λ“€μ€ λ¦¬μ•‘νŠΈ λ³΄λ‹€λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈμ— κ°€κΉŒμš΄ 것듀이닀. λ‹€λ§Œ, ν΄λ‘œμ €κ°€ μ–΄λ–»κ²Œ μž‘λ™ν•˜λŠ”μ§€λ₯Ό μ΄ν•΄ν•˜κ³  μ›μ‹œκ°’κ³Ό 참쑰값에 λŒ€ν•œ 이해가 λ’·λ°›μΉ¨ λœλ‹€λ©΄ λ¦¬μ•‘νŠΈμ˜ μž‘λ™ 원리λ₯Ό 보닀 μ™„λ²½ν•˜κ²Œ 이해할 수 μžˆμ„ 것이닀.

✦ 좜처


🚨 ν•΄λ‹Ή ν¬μŠ€νŒ…μ€ Udemy의 ⌜React μ™„λ²½ κ°€μ΄λ“œβŒŸ κ°•μ˜λ₯Ό 베이슀둜 ν•œ κΈ°λ‘μž…λ‹ˆλ‹€.
✍🏻 κ°•μ˜ git repo λ°”λ‘œκ°€κΈ°

profile
일단 곡뢀가 '적성'에 λ§žλŠ” 개발자. κ·Όμ„±μžˆμŠ΅λ‹ˆλ‹€.

0개의 λŒ“κΈ€