๐Ÿ”ฅ React: ๋ฆฌ์•กํŠธ useEffect ๋ฌดํ•œ ๋ฃจํ”„ ํƒˆ์ถœํ•˜๊ธฐ

summereuna๐Ÿฅยท2022๋…„ 9์›” 14์ผ
5

React JS

๋ชฉ๋ก ๋ณด๊ธฐ
22/69

๐Ÿ˜‡ ์ด ๊ธ€์€ useEffect๋ฅผ ์‚ฌ์šฉํ•˜๋˜ ์ค‘ ๋ฌดํ•œ ๋ฃจํ”„์— ๋น ์ ธ ๊ณจ๋จธ๋ฆฌ๋ฅผ ์‹ธ๋งค๋ฉฐ ๊ดด๋กœ์›Œ ํ•˜๋˜ ์‚ฌ๋žŒ์ด ํ•œ ๋ธ”๋กœ๊ทธ์˜ ๊ธ€์„ ๋ณด๊ณ  ๊ฐ๋ช… ๋ฐ›์•„ ๋ฒˆ์—ญํ•ด ๊ฒŒ์‹œํ•œ ๊ฒƒ์ž„์„ ์•Œ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค.
๋ ˆ์Šค ๊ธฐ๋ฆฟ-

์™œ useEffect๋ฅผ ์‚ฌ์šฉํ• ๊นŒ?


React์˜ useEffect Hook์€ ์•ฑ์˜ ๋ถ€์ž‘์šฉ(side effects)์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

  • useEffect Hook์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช‡๋ช‡ ๊ธฐ๋Šฅ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ๋‹ค.

    - ๋„คํŠธ์›Œํฌ์—์„œ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ ์˜ค๊ธฐ
    ์ฒซ ๋ฒˆ์งธ ๋งˆ์šดํŠธ์—์„œ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์™€ ์ฑ„์šฐ๊ธฐ
    - UI ์กฐ์ž‘
    ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์ด๋ฒคํŠธ์— ์‘๋‹ตํ•˜๊ธฐ (์˜ˆ: ๋ฉ”๋‰ด ์—ด๊ธฐ)
    - ํƒ€์ด๋จธ ์„ค์ • ๋˜๋Š” ์ข…๋ฃŒ
    ํŠน์ • ๋ณ€์ˆ˜๊ฐ€ ๋ฏธ๋ฆฌ ์ •์˜๋œ ๊ฐ’์— ๋„๋‹ฌํ•˜๋ฉด ๋‚ด์žฅ๋œ ํƒ€์ด๋จธ๊ฐ€ ์ค‘์ง€๋˜๊ฒŒ ํ•˜๊ฑฐ๋‚˜ ์‹œ์ž‘๋˜๊ฒŒ ํ•˜๊ธฐ

UseEffect Hook์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ React ์ƒํƒœ๊ณ„์—์„œ ์ผ๋ฐ˜์ ์ด์ง€๋งŒ ๋งˆ์Šคํ„ฐํ•˜๋Š” ๋ฐ๋Š” ์‹œ๊ฐ„์ด ํ•„์š”ํ•˜๋‹ค. ์ด ๋•Œ๋ฌธ์— ๋งŽ์€ ์ดˆ๋ณด ๊ฐœ๋ฐœ์ž๋Š” ๋ฌดํ•œ ๋ฃจํ”„ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๋Š” ๋ฐฉ์‹์œผ๋กœ useEffect ํ•จ์ˆ˜๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค. ์•…๋ช… ๋†’์€ ๋ฌดํ•œ ๋ฃจํ”„์™€ ๊ทธ๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋ฐฐ์›Œ๋ณด์ž.

๐Ÿ“š ์˜ค๋Š˜ ๋ฐฐ์šธ ๋‚ด์šฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

๋ฌดํ•œ ๋ฃจํ”„์˜ ์›์ธ๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

  • ์ข…์†์„ฑ ๋ฐฐ์—ด์— ์ข…์†์„ฑ์„ ์ „๋‹ฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ
  • ํ•จ์ˆ˜๋ฅผ ์ข…์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ
  • ๋ฐฐ์—ด์„ ์ข…์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ
  • ๊ฐ์ฒด๋ฅผ ์ข…์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ
  • ์ž˜๋ชป๋œ ์ข…์†์„ฑ์„ ์ „๋‹ฌํ•  ๊ฒฝ์šฐ

๋ฌดํ•œ ๋ฃจํ”„์˜ ์›์ธ ๋ฐ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•


1. ์ข…์†์„ฑ ๋ฐฐ์—ด์— ์ข…์†์„ฑ์„ ์ „๋‹ฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ

useEffect ํ•จ์ˆ˜์— ์ข…์†์„ฑ์ด ์—†์œผ๋ฉด ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ

function App() {
  const [count, setCount] = useState(0); //์ดˆ๊ธฐ๊ฐ’์€ 0.
  useEffect(() => {
    setCount((count) => count + 1); //์ด Hook์„ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.
  }); //๋””ํŽœ๋˜์‹œ ์–ด๋ ˆ์ด(์ข…์†์„ฑ ๋ฐฐ์—ด) ์—†์Œ.
  return (
    <div className="App">
      <p> value of count: {count} </p>
    </div>
  );
}

์ข…์†์„ฑ์ด ์—†๋Š” ๊ฒฝ์šฐ ๋ชจ๋“  ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ์— ๊ธฐ๋ณธ์ ์œผ๋กœ ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ์—ฌ๊ธฐ์˜ ์•ฑ์€ ๋ชจ๋“  ๋ Œ๋”์— ๋Œ€ํ•ด setCount ์˜ ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•œ๋‹ค. ์ด๊ฒƒ์ด ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

์ด ๋ฌธ์ œ์˜ ์›์ธ์€ ๋ฌด์—‡์ผ๊นŒ?

๋ฌธ์ œ๋ฅผ ๋‹จ๊ณ„๋ณ„๋กœ ๋‚˜๋ˆ„์–ด ๋ณด์ž.

  1. ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”์—์„œ React๋Š” count ๊ฐ’์„ ํ™•์ธํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ count๊ฐ€ 0 ์ด๋ฏ€๋กœ ํ”„๋กœ๊ทธ๋žจ์€ useEffect ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
  2. ๊ทธ๋Ÿฌ๊ณ  ๋‚˜์„œ useEffect๋Š” setCount ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  count Hook์˜ ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
  3. ๊ทธ๋Ÿฐ ๋‹ค์Œ React๋Š” UI๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜์—ฌ ์—…๋ฐ์ดํŠธ๋œ count ๊ฐ’์„ ํ‘œ์‹œํ•œ๋‹ค.
  4. UI๊ฐ€ ์žฌ๋ Œ๋”๋ง ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, useEffect๋Š” ๋ชจ๋“  ๋ Œ๋” ์‚ฌ์ดํด์—์„œ ์‹คํ–‰๋˜๋ฏ€๋กœ ๋˜ ๋‹ค์‹œ setCount ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. ๋ฐ˜๋ณต ์•ค ๋ฐ˜๋ณตโ€ฆ
  5. ์œ„์˜ ๋‹จ๊ณ„๋Š” ๋ชจ๋“  ๋ Œ๋”์—์„œ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ์•ฑ์ด ์ถฉ๋Œํ•˜๊ฒŒ ๋œ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

์ด ๋ฌธ์ œ๋ฅผ ์™„ํ™”ํ•˜๋ ค๋ฉด ์ข…์†์„ฑ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ํŠน์ • ๊ฐ’์ด ์—…๋ฐ์ดํŠธ๋˜๋Š” ๊ฒฝ์šฐ์—๋งŒ React์—์„œ useEffect๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์ง€์‹œํ•˜๋ฉด ๋œ๋‹ค.

๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ข…์†์„ฑ์œผ๋กœ ๋นˆ ๋ฐฐ์—ด์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

๋ณ€๊ฒฝํ•œ ์ฝ”๋“œ

useEffect(() => {
  setCount((count) => count + 1);
}, []); //๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋นˆ ๋ฐฐ์—ด์„ ์ค€๋‹ค.

๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋นˆ ๋ฐฐ์—ด์„ ์ฃผ๋ฉด, React๋Š” ์ฒซ ๋ฒˆ์งธ ๋งˆ์šดํŠธ์—์„œ๋งŒ setCount ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

2. ํ•จ์ˆ˜๋ฅผ ์ข…์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ

๋ฉ”์„œ๋“œ๋ฅผ useEffect ์ข…์†์„ฑ ๋ฐฐ์—ด์— ์ „๋‹ฌํ•˜๋ฉด React๋Š” ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ์žˆ์Œ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ

function App() {
  const [count, setCount] = useState(0);

  function logResult() {
    return 2 + 2;
  }
  useEffect(() => {
    setCount((count) => count + 1);
  }, [logResult]); //๋””ํŽœ๋˜์‹œ๋กœ logResult ํ•จ์ˆ˜๋ฅผ ์„ค์ •ํ–ˆ๋‹ค.
  return (
    <div className="App">
      <p> value of count: {count} </p> {/*count์˜ ๊ฐ’ ๋ณด์—ฌ์คŒ*/}
    </div>
  );
}

์ด snippet์—์„œ๋Š” logResult ๋ฉ”์„œ๋“œ๋ฅผ useEffect์˜ ์ข…์†์„ฑ ๋ฐฐ์—ด์— ์ „๋‹ฌํ–ˆ๋‹ค.
๋”ฐ๋ผ์„œ ์ด๋ก ์ ์œผ๋กœ๋Š”, React๊ฐ€ ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”์—์„œ๋งŒ count ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚ฌ ๊ฒƒ์ด๋ผ๊ณ  ์˜ˆ์ƒ๋œ๋‹ค.

ํ•˜์ง€๋งŒ! ์ด๋Ÿฐ ์˜ค๋ฅ˜๊ฐ€ ๋œจ๊ฒŒ ๋œ๋‹ค.

โš ๏ธ Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
๊ฒฝ๊ณ : ์ตœ๋Œ€ ์—…๋ฐ์ดํŠธ ๊นŠ์ด๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ useEffect ์•ˆ์— ์žˆ๋Š” setState๋ฅผ ํ˜ธ์ถœํ•˜์ง€๋งŒ useEffect์— ์ข…์†์„ฑ ๋ฐฐ์—ด์ด ์—†๊ฑฐ๋‚˜ ๋ชจ๋“  ๋ Œ๋”์—์„œ ์ข…์†์„ฑ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์˜ ์›์ธ์€ ๋ฌด์—‡์ผ๊นŒ?

  1. ํ•œ ๊ฐ€์ง€ ๊ธฐ์–ตํ•ด์•ผ ํ•  ์ ์€ useEffect๋Š” ์–•์€ ๋น„๊ต(shallow comparison)๋ผ๋Š” ๊ฐœ๋…์„ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋””ํŽœ๋˜์‹œ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  2. ์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๋Š” ๊ฐ ๋ Œ๋” ๋™์•ˆ React๊ฐ€ logResult์˜ ์ฐธ์กฐ๋ฅผ ์žฌ์ •์˜ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
  3. ๋”ฐ๋ผ์„œ ๊ฐ ์‚ฌ์ดํด๋งˆ๋‹ค useEffect ํ•จ์ˆ˜๊ฐ€ ๋‹ค์‹œ ํŠธ๋ฆฌ๊ฑฐ๋œ๋‹ค.
  4. ๋”ฐ๋ผ์„œ React๋Š” ์•ฑ์—์„œ Update Depth ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๊นŒ์ง€ setCount Hook์„ ํ˜ธ์ถœํ•œ๋‹ค. ์ด๊ฒƒ์€ ํ”„๋กœ๊ทธ๋žจ์— ๋ฒ„๊ทธ์™€ ๋ถˆ์•ˆ์ •์„ฑ์„ ๊ฐ€์ ธ์˜จ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

ํ•œ ๊ฐ€์ง€ ํ•ด๊ฒฐ์ฑ…์€ useCallback Hook์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” ์ž์‹ ์˜ ํ•จ์ˆ˜๋ฅผ ๋ฉ”๋ชจํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ์ฐธ์กฐ ๊ฐ’์ด ๋™์ผํ•˜๊ฒŒ ์œ ์ง€๋œ๋‹ค. React๋Š” ์•ˆ์ •์ ์ธ ์ฐธ์กฐ ๊ฐ’์œผ๋กœ ์ธํ•ด UI๋ฅผ ๋ฌดํ•œํžˆ ๋‹ค์‹œ ๋ Œ๋”๋งํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.

๋ณ€๊ฒฝํ•œ ์ฝ”๋“œ

const logResult = useCallback(() => {
  return 2 + 2;
}, []); //์ด์ œ logResult๊ฐ€ ๋ฉ”๋ชจ๋œ๋‹ค.
useEffect(()=> {
  setCount((count)=> count+1);
},[logResult]); //logResult ์ฐธ์กฐ๊ฐ€ ๋™์ผํ•˜๊ฒŒ ์œ ์ง€๋˜๋ฏ€๋กœ ๋ฌดํ•œ ๋ฃจํ”„ ์˜ค๋ฅ˜๊ฐ€ ์—†์–ด์ง„๋‹ค.

3. ๋ฐฐ์—ด์„ ์ข…์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ

๋ฐฐ์—ด ๋ณ€์ˆ˜๋ฅผ ์ข…์†์„ฑ์œผ๋กœ ์ „๋‹ฌํ•˜๋ฉด ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ

const [count, setCount] = useState(0); //์ดˆ๊ธฐ ๊ฐ’์€ 0.
const myArray = ["one", "two", "three"];

useEffect(() => {
  setCount((count) => count + 1); //์ด์ „์ฒ˜๋Ÿผ Count ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.
}, [myArray]); //๋ฐฐ์—ด ๋ณ€์ˆ˜๋ฅผ ๋””ํŽœ๋˜์‹œ๋กœ ์ „๋‹ฌ

์ข…์†์„ฑ ์ธ์ˆ˜๋กœ ๋ฐฐ์—ด์ธ myArray ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ–ˆ๋‹ค.

์ด ๋ฌธ์ œ์˜ ์›์ธ์€ ๋ฌด์—‡์ผ๊นŒ?

myArray์˜ ๊ฐ’์€ ๋ณ€ํ•˜์ง€ ์•Š์•˜๋Š”๋ฐ ์™œ ์ฝ”๋“œ๊ฐ€ useEffect๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ํŠธ๋ฆฌ๊ฑฐํ• ๊นŒ?

  1. React๋Š” ๋””ํŽœ๋˜์‹œ์˜ ์ฐธ์กฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์–•์€ ๋น„๊ต๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์ž.
  2. myArray์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ๊ฐ ๋ Œ๋”์—์„œ ๊ณ„์† ๋ณ€๊ฒฝ๋˜๋ฏ€๋กœ useEffect๋Š” setCount ์ฝœ๋ฐฑ์„ ํŠธ๋ฆฌ๊ฑฐํ•œ๋‹ค.
  3. ๋”ฐ๋ผ์„œ myArray์˜ ๋ถˆ์•ˆ์ •ํ•œ ์ฐธ์กฐ ๊ฐ’์œผ๋กœ ์ธํ•ด React๋Š” ๋ชจ๋“  ๋ Œ๋” ์‚ฌ์ดํด์—์„œ useEffect๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. ๊ฒฐ๊ตญ ์ด๋กœ ์ธํ•ด ์•ฑ์ด ์ค‘๋‹จ๋œ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด, ์šฐ๋ฆฌ๋Š” useRef Hook์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒํ•˜๋ฉด ์ฐธ์กฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋„๋ก ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

๋ณ€๊ฒฝํ•œ ์ฝ”๋“œ

const [count, setCount] = useState(0);

//'current' ์†์„ฑ์„ ์ถ”์ถœํ•˜๊ณ  ๊ฐ’์„ ํ• ๋‹นํ•œ๋‹ค.
const { current: myArray } = useRef(["one", "two", "three"]);

useEffect(() => {
  setCount((count) => count + 1);
}, [myArray]); //์ฐธ์กฐ ๊ฐ’์ด ์•ˆ์ •์ ์ด์–ด์„œ ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

4. ๊ฐ์ฒด(Object)๋ฅผ ์ข…์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ

useEffec์˜ ์ข…์†์„ฑ ๋ฐฐ์—ด์—์„œ ๊ฐ์ฒด๋ฅผ ๋„ฃ์œผ๋ฉด ๋ฌดํ•œ ๋ฃจํ”„ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ

const [count, setCount] = useState(0);
const person = { name: "Rue", age: 17 }; //๊ฐ์ฒด ์ƒ์„ฑ
useEffect(() => {
  //๋งค๋ฒˆ count ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚ด 
  //person'์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•จ
  setCount((count) => count + 1);
}, [person]); //์ข…์† ๋ฐฐ์—ด์€ ๊ฐ์ฒด๋ฅผ ์ธ์ˆ˜๋กœ ํฌํ•จํ•จ
return (
  <div className="App">
    <p> Value of {count} </p>
  </div>
);

์ฝ˜์†”์˜ ๊ฒฐ๊ณผ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ๋ฌดํ•œ ๋ฐ˜๋ณต๋จ์„ ์•Œ๋ ค์ค€๋‹ค.

The 'person' object makes the dependencies of useEffect Hook change on every render. Move it inside the useEffect callback. Alternatively, wrap the initialization of 'person' in its own useMemo() Hook.
'person' ๊ฐ์ฒด๋Š” ๋ชจ๋“  ๋ Œ๋”์—์„œ useEffect Hook์˜ ๋””ํŽœ๋˜์‹œ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค. 'person'๊ฐ์ฒด๋ฅผ useEffect ์ฝœ๋ฐฑ ์•ˆ์œผ๋กœ ์ด๋™ํ•˜์„ธ์š”. ๋˜๋Š” 'person'๊ฐ์ฒด์˜ ์ดˆ๊ธฐํ™”๋ฅผ ์ž์ฒด useMemo() Hook์œผ๋กœ ๋ž˜ํ•‘ํ•˜์„ธ์š”.

์ด ๋ฌธ์ œ์˜ ์›์ธ์€ ๋ฌด์—‡์ผ๊นŒ?

  1. React๋Š” ์ด์ „๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์–•์€ ๋น„๊ต๋ฅผ ํ†ตํ•ด person์˜ ์ฐธ์กฐ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
  2. ๋ Œ๋”๋งํ•  ๋•Œ๋งˆ๋‹ค person ๊ฐ์ฒด์˜ ์ฐธ์กฐ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฏ€๋กœ React๋Š” useEffect๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•œ๋‹ค.
  3. ๋”ฐ๋ผ์„œ ๋ชจ๋“  ์—…๋ฐ์ดํŠธ ์ฃผ๊ธฐ๋งˆ๋‹ค setCount๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

useMemo๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ์ด Hook์€ ๋””ํŽœ๋˜์‹œ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ๋ฉ”๋ชจ๋œ ๊ฐ’์„ ๊ณ„์‚ฐํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฉ”๋ชจ๋œ ๋ณ€์ˆ˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ ๋ Œ๋”๋ง ์ค‘์— ์ƒํƒœ์˜ ์ฐธ์กฐ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋„๋กํ•ด์ค€๋‹ค.

๋ณ€๊ฒฝํ•œ ์ฝ”๋“œ

//useMemo๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด ์ƒ์„ฑ
const person = useMemo(
  () => ({ name: "Rue", age: 17 }),
  [] //๋””ํŽœ๋˜์‹œ๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ฆ‰, useEffect์—์„œ person๊ฐ์ฒด๋ฅผ ๋””ํŽœ๋˜์‹œ๋กœ ์‚ฌ์šฉํ•ด๋„ ์ฐธ์กฐ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์œ ์ง€๊ฐ€ ๋œ๋‹ค๋Š” ๋œป์ด๋‹ค.
);
useEffect(() => {
  setCount((count) => count + 1);
}, [person]);

5. ์ž˜๋ชป๋œ ๋””ํŽœ๋˜์‹œ๋ฅผ ์ „๋‹ฌํ•  ๊ฒฝ์šฐ

useEffect ํ•จ์ˆ˜์— ์ž˜๋ชป๋œ ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋ฉด React๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

์˜ˆ์‹œ ์ฝ”๋“œ

const [count, setCount] = useState(0);

useEffect(() => {
  setCount((count) => count + 1);
}, [count]); //์ข…์†์„ฑ ๋ฐฐ์—ด์— count ์ „๋‹ฌํ•จ

return (
  <div className="App">
    <button onClick={() => setCount((count) => count + 1)}>+</button>
    <p> Value of count{count} </p>
  </div>
);

์ด ๋ฌธ์ œ์˜ ์›์ธ์€ ๋ฌด์—‡์ผ๊นŒ?

  1. ์œ„ ์ฝ”๋“œ์— useEffect ๋ฉ”์†Œ๋“œ ๋‚ด์—์„œ ์นด์šดํŠธ ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•˜๋ผ๊ณ  ์ ์–ด๋‘์—ˆ๋‹ค.
  2. ๊ทธ์— ๋”ํ•ด, count Hook์„ ์˜์กด์„ฑ ๋ฐฐ์—ด์—๋„ ์ „๋‹ฌํ•ด ๋‘์—ˆ๋‹ค.
  3. ์ฆ‰, count ๊ฐ’์ด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ๋งˆ๋‹ค, React๊ฐ€ useEffect๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
  4. ๊ฒฐ๊ณผ์ ์œผ๋กœ useEffect Hook์€ setCount๋ฅผ ํ˜ธ์ถœํ•˜๋ฏ€๋กœ count๋ฅผ ๋‹ค์‹œ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
  5. ์ด ๋•Œ๋ฌธ์— React๋Š” ๋ฌดํ•œ ๋ฃจํ”„์— ๋น ์ง„๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ์ œ๊ฑฐํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋นˆ ์ข…์†์„ฑ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

๋ณ€๊ฒฝํ•œ ์ฝ”๋“œ

const [count, setCount] = useState(0);

//์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ๋งˆ์šดํŠธ๋  ๋•Œ๋งŒ 'count' ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
useEffect(() => {
  setCount((count) => count + 1);
}, []);

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”์—์„œ๋งŒ useEffect๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

๊ฒฐ๋ก 


React Hooks๋Š” ์‰ฌ์šด ๊ฐœ๋…์ด์ง€๋งŒ ํ”„๋กœ์ ํŠธ์— ํ†ตํ•ฉ ํ•  ๋•Œ ๊ธฐ์–ตํ•ด์•ผ ํ•  ๋งŽ์€ ๊ทœ์น™์ด ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒํ•ด์•ผ ์•ฑ์ด ์•ˆ์ •์ (stable)์œผ๋กœ ์œ ์ง€๋˜๊ณ  ์ตœ์ ํ™”(optimized)๋˜๋ฉฐ ํ”„๋กœ๋•์…˜ ์ค‘์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋˜ํ•œ ์ตœ๊ทผ ๋ฆด๋ฆฌ์Šค๋œ Create React App CLI๋Š” ๋Ÿฐํƒ€์ž„ ์ค‘์— ๋ฌดํ•œ ๋ฃจํ”„ ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ๋ณด๊ณ ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ”„๋กœ๋•์…˜ ์„œ๋ฒ„๋กœ ์ „ํ™˜ํ•˜๊ธฐ ์ „์— ๋ฐœ๊ฒฌํ•˜๊ณ  ์™„ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.


๐Ÿ“š ์ฐธ๊ณ : How to solve the React useEffect Hookโ€™s infinite loop patterns | Hussain Arif

profile
Always have hope๐Ÿ€ & constant passion๐Ÿ”ฅ

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