Digital Products

useEffect ์™„๋ฒฝ ๊ฐ€์ด๋“œ

March 9, 2019 โ€ข ๐Ÿฑ๐Ÿฑ๐Ÿฑ๐Ÿฑ 48 min read

์—ฌ๋Ÿฌ๋ถ„์€ Hooks๋กœ(์ดํ•˜ ํ›…) ๋ช‡ ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•ด ๋ดค์„ ๊ฒ๋‹ˆ๋‹ค. ์•„๋งˆ ์ž‘์€ ์•ฑ์—์„œ๋ผ๊ณ  ํ•ด๋„์š”. ์•„๋งˆ ๋Œ€์ฒด์ ์œผ๋กœ ๋งŒ์กฑํ•˜์…จ๊ฒ ์ฃ . API๊ฐ€ ํŽธ๋ฆฌํ•˜๋‹ค๋Š” ๋А๋‚Œ์„ ๋ฐ›๊ณ  ๋ฒŒ์จ ๋ช‡ ๊ฐ€์ง€ ํŠธ๋ฆญ์„ ์ตํžˆ๊ธฐ๋„ ํ–ˆ์„ ๊ฒ๋‹ˆ๋‹ค. ์‹ฌ์ง€์–ด ์ปค์Šคํ…€ ํ›…์„ ์ž‘์„ฑํ•˜์—ฌ ๋ฐ˜๋ณต๋˜๋Š” ๋กœ์ง์„ ์ถ”์ถœํ•ด๋‚ด๊ธฐ๋„ ํ–ˆ์Šต๋‹ˆ๋‹ค(300์ค„์˜ ์ฝ”๋“œ๊ฐ€ ์ค„์–ด๋“ค์—ˆ๋„ค์š”!). ๊ทธ๋ž˜์„œ ๋™๋ฃŒ๋“ค์—๊ฒŒ ๋ณด์—ฌ์ฃผ๋ฉด ๋™๋ฃŒ๋“ค์€ โ€œ๋Œ€๋‹จํ•˜๋„ค์š”โ€ ๋ผ๊ณ  ๋งํ•˜๊ฒ ์ง€์š”.

ํ•˜์ง€๋งŒ ๋•Œ๋•Œ๋กœ useEffect ๋ฅผ ์“ธ ๋•Œ๋งˆ๋‹ค ๋ญ”๊ฐ€ ์ž˜ ๋“ค์–ด๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ญ”๊ฐ€ ๋†“์น˜๊ณ  ์žˆ๋‹ค๋Š” ๊ธฐ๋ถ„์„ ๋А๋ผ๋ฉฐ ๊ดด๋กœ์›€์„ ๋А๋ผ๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ฒ˜์Œ์— ๋ณด๋ฉด ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ ๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์„œ๋“œ์™€ ๋น„์Šทํ•˜๋‹ค๊ณ  ๋А๋‚๋‹ˆ๋‹ค๋งŒโ€ฆ ์ •๋ง ๊ทธ๋Ÿด๊นŒ์š”? ์ ์  ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด์„œ ์Šค์Šค๋กœ์—๊ฒŒ ์•„๋ž˜์™€ ๊ฐ™์€ ์งˆ๋ฌธ์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  • ๐Ÿค” useEffect ๋กœ componentDidMount ๋™์ž‘์„ ํ‰๋‚ด๋‚ด๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•˜์ง€?
  • ๐Ÿค” useEffect ์•ˆ์—์„œ ๋ฐ์ดํ„ฐ ํŽ˜์นญ(Data fetching)์€ ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? ๋‘๋ฒˆ์งธ ์ธ์ž๋กœ ์˜ค๋Š” ๋ฐฐ์—ด([]) ์€ ๋ญ์ง€?
  • ๐Ÿค” ์ดํŽ™ํŠธ๋ฅผ ์ผ์œผํ‚ค๋Š” ์˜์กด์„ฑ ๋ฐฐ์—ด์— ํ•จ์ˆ˜๋ฅผ ๋ช…์‹œํ•ด๋„ ๋˜๋Š”๊ฑธ๊นŒ?
  • ๐Ÿค” ์™œ ๊ฐ€๋”์”ฉ ๋ฐ์ดํ„ฐ ํŽ˜์นญ์ด ๋ฌดํ•œ๋ฃจํ”„์— ๋น ์ง€๋Š”๊ฑธ๊นŒ?
  • ๐Ÿค” ์™œ ๊ฐ€๋”์”ฉ ์ดํŽ™ํŠธ ์•ˆ์—์„œ ์ด์ „ state๋‚˜ prop ๊ฐ’์„ ์ฐธ์กฐํ• ๊นŒ?

์ œ๊ฐ€ ์ฒ˜์Œ ํ›…์„ ์‚ฌ์šฉํ•  ๋•Œ๋„, ์œ„์˜ ์งˆ๋ฌธ์— ๋˜‘๊ฐ™์ด ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๊ธฐ๋ถ„์„ ๋А๊ผˆ์Šต๋‹ˆ๋‹ค. ์‹ฌ์ง€์–ด ์ดˆ๊ธฐ ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด์„œ๋„ ๋‚˜๋Š” ๋ฏธ๋ฌ˜ํ•œ ๋ถ€๋ถ„์— ๋Œ€ํ•ด ์ œ๋Œ€๋กœ ํŒŒ์•…ํ•˜์ง€ ๋ชปํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ช‡ ๋ฒˆ์˜ โ€œ์•„ํ•˜ ๋ชจ๋จผํŠธ(aha moment, ํŠน์ • ์•„์ด๋””์–ด์— ๋Œ€ํ•ด ์˜๊ฐ์„ ์–ป๊ฒŒ ๋˜๋Š” ์ˆœ๊ฐ„ ๋“ฑ)โ€ ๋ฅผ ๊ฒช๊ณ  ๋‚˜์„œ ์—ฌ๋Ÿฌ๋ถ„๋“ค์—๊ฒŒ ์•Œ๊ฒŒ๋œ ์ ์„ ๊ณต์œ ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด ์™„๋ฒฝ ๊ฐ€์ด๋“œ๋ฅผ ํ†ตํ•ด ์œ„์˜ ์งˆ๋ฌธ์— ๋ช…๋ฐฑํ•˜๊ฒŒ ๋‹ตํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‹ต์„ ์–ป๊ธฐ์— ์•ž์„œ ํ•œ ๋ฐœ์ง ๋’ค๋กœ ๋ฌผ๋Ÿฌ๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธ€์˜ ๋ชฉ์ ์€ ๋‹จ์ˆœํžˆ ์š”์•ฝ๋œ ์ •๋ณด๋ฅผ ๋ชฉ๋ก ํ˜•ํƒœ๋กœ ์ œ๊ณตํ•˜๋Š”๊ฒŒ ์•„๋‹™๋‹ˆ๋‹ค. ์ง„์งœ ๋ชฉ์ ์€ ์—ฌ๋Ÿฌ๋ถ„์ด useEffect ๋ฅผ โ€œ์™„์ „ํžˆโ€ ์ดํ•ดํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋Š” ์•Œ์•„์•ผ ํ•  ๊ฒƒ์ด ๊ทธ๋ฆฌ ๋งŽ์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๋Œ€๋ถ€๋ถ„์˜ ์‹œ๊ฐ„์„ ์ด์ „์— ๋ฐฐ์› ๋˜ ๊ฒƒ์„ ์žŠ์–ด๋ฒ„๋ฆฌ๋Š”๋ฐ(unlearning) ํ• ์• ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ œ๊ฐ€ useEffect ํ›…์„ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ ๋ผ์ดํ”„์‚ฌ์ดํด์ด๋ผ๋Š” ์ต์ˆ™ํ•œ ํ”„๋ฆฌ์ฆ˜์„ ํ†ตํ•ด ๋ฐ”๋ผ๋ณด๋Š” ๊ฒƒ์„ ๊ทธ๋งŒ๋‘์ž ๋ชจ๋“  ๊ฒƒ์ด ๋ช…๋ฐฑํ•˜๊ฒŒ ๋‹ค๊ฐ€์™”์Šต๋‹ˆ๋‹ค.

โ€œ์•Œ๊ณ  ์žˆ๋˜ ๊ฒƒ์„ ์ „๋ถ€ ์žŠ์–ด๋ฒ„๋ฆฌ๊ฒŒโ€ - ์š”๋‹ค

์š”๋‹ค๊ฐ€ ๊ณต๊ธฐ๋ฅผ ๋“ค์ด๋งˆ์‹œ๊ณ  ์žˆ๋‹ค.


์ด ๊ธ€์€ ๋…์ž ์—ฌ๋Ÿฌ๋ถ„์ด ์–ด๋А ์ •๋„ useEffect API์— ์ต์ˆ™ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์ „์ œ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ธ€์€ ์•„์ฃผ ๊น๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ์ž‘์€ ์ฑ… ์ˆ˜์ค€์ž…๋‹ˆ๋‹ค. ์ œ๊ฐ€ ๊ฐœ์ธ์ ์œผ๋กœ ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์„œ๋‘˜๋Ÿฌ ์‚ดํŽด๋ณด์‹œ๊ฑฐ๋‚˜ ๊ธด ๊ธ€์€ ์‹ ๊ฒฝ์“ฐ๊ณ  ์‹ถ์ง€ ์•Š์„ ๊ฒฝ์šฐ๋ฅผ ์œ„ํ•ด ๋ฐ”๋กœ ์•„๋ž˜์— ์š”์•ฝ๋ณธ(TLDR)์„ ๋‹ฌ์•„ ๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

๊นŠ์ด ํŒŒ๊ณ ๋“œ๋Š” ๊ธ€์ด ๋ถˆํŽธํ•˜์‹  ๊ฒฝ์šฐ, ์•„๋ž˜์˜ ๋‚ด์šฉ์„ ์ข€ ๋” ์•Œ์•„๋“ฃ๊ธฐ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•˜๋Š” ๋‹ค๋ฅธ ๊ธ€์ด๋‚˜ ๊ฐ•์ขŒ๊ฐ€ ๋‚˜์˜ค๊ธธ ๊ธฐ๋‹ค๋ฆฌ์…”์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ๊ฐ€ 2013๋…„์— ์ฒ˜์Œ ๋‚˜์˜จ ๋’ค ๊ฐœ๋ฐœ์ž๋“ค์ด ๊ธฐ์กด๊ณผ ๋‹ค๋ฅธ ๋ฉ˜ํƒˆ ๋ชจ๋ธ์„ ์ตํžˆ๊ณ  ๋‹ค๋ฅธ ์‚ฌ๋žŒ์—๊ฒŒ ๊ฐ€๋ฅด์น˜๊ธฐ ์‹œ์ž‘ํ•˜๊ธฐ๊นŒ์ง€ ์‹œ๊ฐ„์ด ์ข€ ๊ฑธ๋ ธ๋“ฏ ๋ง์ž…๋‹ˆ๋‹ค.


TLDR (Too Long; Didnโ€™t Read - ์š”์•ฝ)

๊ธ€ ์ „์ฒด๋ฅผ ์ฝ๊ณ  ์‹ถ์ง€ ์•Š์€ ๋ถ„๋“ค์„ ์œ„ํ•ด ์—ฌ๊ธฐ ์š”์•ฝ๋ณธ์„ ๋งˆ๋ จํ•ด ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ์ฝ๋‹ค๊ฐ€ ์–ด๋–ค ๋ถ€๋ถ„์ด ์ž˜ ์ดํ•ด๊ฐ€ ๋˜์ง€ ์•Š์œผ์…จ๋‹ค๋ฉด ์—ฐ๊ด€๋œ ๋ถ€๋ถ„์ด ๋‚˜์˜ฌ ๋•Œ๊นŒ์ง€ ์Šคํฌ๋กค์„ ์•„๋ž˜๋กœ ๋‚ด๋ ค๋ณด์„ธ์š”.

๋งŒ์•ฝ ๊ธ€ ์ „์ฒด๋ฅผ ์ฝ์œผ์‹ค ๊ฑฐ๋ผ๋ฉด ํŽธํ•˜๊ฒŒ ์Šคํ‚ตํ•˜์…”๋„ ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์œผ๋กœ ์ด๋™ํ•˜๋Š” ๋งํฌ๋ฅผ ๊ธ€ ๋์— ๋‹ฌ์•„ ๋‘๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿค” ์งˆ๋ฌธ: useEffect ๋กœ componentDidMount ๋™์ž‘์„ ํ‰๋‚ด๋‚ด๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•˜์ง€?

์™„์ „ํžˆ ๊ฐ™์ง„ ์•Š์ง€๋งŒ useEffect(fn, []) ์œผ๋กœ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. componentDidMount ์™€ ๋‹ฌ๋ฆฌ prop๊ณผ state๋ฅผ ์žก์•„๋‘˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ฝœ๋ฐฑ ์•ˆ์—์„œ๋„ ์ดˆ๊ธฐ prop๊ณผ state๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ โ€œ์ตœ์‹ ์˜โ€ ์ƒํƒœ ๋“ฑ์„ ์›ํ•œ๋‹ค๋ฉด, ref์—๋‹ค ๋‹ด์•„๋‘˜ ์ˆ˜๋Š” ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ณดํ†ต ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ๊ตฌ์กฐํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ตณ์ด ์ด ๋ฐฉ๋ฒ•์„ ์“ธ ํ•„์š”๋„ ์—†์Šต๋‹ˆ๋‹ค. ์ดํŽ™ํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฉ˜ํƒˆ ๋ชจ๋ธ์€ componentDidMount ๋‚˜ ๋‹ค๋ฅธ ๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์„œ๋“œ์™€ ๋‹ค๋ฅด๋‹ค๋Š” ์ ์„ ์ธ์ง€ํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ค ๋ผ์ดํ”„์‚ฌ์ดํด ๋ฉ”์„œ๋“œ์™€ ๋น„์Šทํ•œ ๋™์ž‘์„ ํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ์œผ๋ ค๊ณ  ํ•˜๋ฉด ์˜คํžˆ๋ ค ํ˜ผ๋ž€์„ ๋” ํ‚ค์šธ ๋ฟ์ž…๋‹ˆ๋‹ค. ๋” ์ƒ์‚ฐ์ ์œผ๋กœ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด โ€œ์ดํŽ™ํŠธ ๊ธฐ์ค€์œผ๋กœ ์ƒ๊ฐํ•ด์•ผ(thinking in effects)โ€ ํ•˜๋ฉฐ ์ด ๋ฉ˜ํƒˆ ๋ชจ๋ธ์€ ๋™๊ธฐํ™”๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์— ๊ฐ€๊น์ง€ ๋ผ์ดํ”„์‚ฌ์ดํด ์ด๋ฒคํŠธ์— ์‘๋‹ตํ•˜๋Š” ๊ฒƒ๊ณผ๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

๐Ÿค” ์งˆ๋ฌธ: useEffect ์•ˆ์—์„œ ๋ฐ์ดํ„ฐ ํŽ˜์นญ์€ ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? ๋‘๋ฒˆ์งธ ์ธ์ž๋กœ ์˜ค๋Š” ๋ฐฐ์—ด([]) ์€ ๋ญ์ง€?

์ด ๋งํฌ์˜ ๊ธ€์ด useEffect ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ๋ฒ•์„ ํŒŒ์•…ํ•˜๋Š”๋ฐ ์ข‹์€ ๊ธฐ๋ณธ์„œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๊ธ€์„ ๊ผญ ๋๊นŒ์ง€ ์ฝ์–ด๋ณด์„ธ์š”! ์ง€๊ธˆ ์ฝ๊ณ  ๊ณ„์‹œ๋Š” ๊ธ€์ฒ˜๋Ÿผ ๊ธธ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. [] ๋Š” ์ดํŽ™ํŠธ์— ๋ฆฌ์•กํŠธ ๋ฐ์ดํ„ฐ ํ๋ฆ„์— ๊ด€์—ฌํ•˜๋Š” ์–ด๋– ํ•œ ๊ฐ’๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ฒ ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ํ•œ ๋ฒˆ ์ ์šฉ๋˜์–ด๋„ ์•ˆ์ „ํ•˜๋‹ค๋Š” ๋œป์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋นˆ ๋ฐฐ์—ด์€ ์‹ค์ œ๋กœ ๊ฐ’์ด ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•  ๋•Œ ๋ฒ„๊ทธ๋ฅผ ์ผ์œผํ‚ค๋Š” ์ฃผ๋œ ์›์ธ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์ž˜๋ชป๋œ ๋ฐฉ์‹์œผ๋กœ ์˜์กด์„ฑ ์ฒดํฌ๋ฅผ ์ƒ๋žตํ•˜๋Š” ๊ฒƒ ๋ณด๋‹ค ์˜์กด์„ฑ์„ ํ•„์š”๋กœ ํ•˜๋Š” ์ƒํ™ฉ์„ ์ œ๊ฑฐํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ „๋žต์„(์ฃผ๋กœ useReducer, useCallback) ์ตํ˜€์•ผ ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿค” ์งˆ๋ฌธ: ์ดํŽ™ํŠธ๋ฅผ ์ผ์œผํ‚ค๋Š” ์˜์กด์„ฑ ๋ฐฐ์—ด์— ํ•จ์ˆ˜๋ฅผ ๋ช…์‹œํ•ด๋„ ๋˜๋Š”๊ฑธ๊นŒ?

์ถ”์ฒœํ•˜๋Š” ๋ฐฉ๋ฒ•์€ prop์ด๋‚˜ state๋ฅผ ๋ฐ˜๋“œ์‹œ ์š”๊ตฌํ•˜์ง€ ์•Š๋Š” ํ•จ์ˆ˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋ฐ”๊นฅ์— ์„ ์–ธํ•ด์„œ ํ˜ธ์ด์ŠคํŒ…ํ•˜๊ณ , ์ดํŽ™ํŠธ ์•ˆ์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜๋Š” ์ดํŽ™ํŠธ ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ์„ ์–ธํ•˜๋Š” ๊ฒ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๊ณ  ๋‚˜์„œ ๋งŒ์•ฝ์— ๋žœ๋” ๋ฒ”์œ„ ์•ˆ์— ์žˆ๋Š” ํ•จ์ˆ˜๋ฅผ ์ดํŽ™ํŠธ๊ฐ€ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด (prop์œผ๋กœ ๋‚ด๋ ค์˜ค๋Š” ํ•จ์ˆ˜ ํฌํ•จํ•ด์„œ), ๊ตฌํ˜„๋ถ€๋ฅผ useCallback ์œผ๋กœ ๊ฐ์‹ธ์„ธ์š”. ์™œ ์ด๋Ÿฐ๊ฑธ ์‹ ๊ฒฝ์จ์•ผ ํ• ๊นŒ์š”? ํ•จ์ˆ˜๋Š” prop๊ณผ state๋กœ๋ถ€ํ„ฐ ๊ฐ’์„ โ€œ๋ณผ ์ˆ˜โ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๋ฆฌ์•กํŠธ์˜ ๋ฐ์ดํ„ฐ ํ”Œ๋กœ์šฐ์™€ ์—ฐ๊ด€์ด ์žˆ์ง€์š”. ์ž์„ธํ•œ ๋‹ต๋ณ€์€ ํ›… FAQ ๋ถ€๋ถ„์— ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿค” ์งˆ๋ฌธ: ์™œ ๊ฐ€๋”์”ฉ ๋ฐ์ดํ„ฐ ํŽ˜์นญ์ด ๋ฌดํ•œ๋ฃจํ”„์— ๋น ์ง€๋Š”๊ฑธ๊นŒ?

์ดํŽ™ํŠธ ์•ˆ์—์„œ ๋ฐ์ดํ„ฐ ํŽ˜์นญ์„ ํ•  ๋•Œ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜์ง€ ์•Š์•˜์„ ๋•Œ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ์ด๊ฒŒ ์—†์œผ๋ฉด ์ดํŽ™ํŠธ๋Š” ๋งค ๋žœ๋”๋งˆ๋‹ค ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  state๋ฅผ ์„ค์ •ํ•˜๋Š” ์ผ์€ ๋˜ ๋‹ค์‹œ ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ•˜์ฃ . ์˜์กด์„ฑ ๋ฐฐ์—ด์— ํ•ญ์ƒ ๋ฐ”๋€Œ๋Š” ๊ฐ’์„ ์ง€์ •ํ•ด ๋‘๋Š” ๊ฒฝ์šฐ์—๋„ ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜์”ฉ ์ง€์›Œ๋ณด๋ฉด์„œ ์–ด๋А ๊ฐ’์ด ๋ฌธ์ œ์ธ์ง€ ํ™•์ธํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์˜์กด ๊ฐ’์„ ์ง€์šฐ๋Š” ์ผ์€(์•„๋‹ˆ๋ฉด ๋งน๋ชฉ์ ์œผ๋กœ [] ์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์€) ๋ณดํ†ต ์ž˜๋ชป๋œ ํ•ด๊ฒฐ๋ฒ•์ž…๋‹ˆ๋‹ค. ๊ทธ ๋Œ€์‹  ๋ฌธ์ œ์˜ ๊ทผ์›์„ ํŒŒ์•…ํ•˜์—ฌ ํ•ด๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํ•จ์ˆ˜๊ฐ€ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์ดํŽ™ํŠธ ํ•จ์ˆ˜ ์•ˆ์— ์ง‘์–ด๋„ฃ๊ฑฐ๋‚˜, ํ•จ์ˆ˜๋ฅผ ๊บผ๋‚ด์„œ ํ˜ธ์ด์ŠคํŒ… ํ•˜๊ฑฐ๋‚˜, useCallback ์œผ๋กœ ๊ฐ์‹ธ์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์ฒด๊ฐ€ ์žฌ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ง‰์œผ๋ ค๋ฉด useMemo ๋ฅผ ๋น„์Šทํ•œ ์šฉ๋„๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿค” ์งˆ๋ฌธ: ์™œ ๊ฐ€๋”์”ฉ ์ดํŽ™ํŠธ ์•ˆ์—์„œ ์ด์ „ state๋‚˜ prop ๊ฐ’์„ ์ฐธ์กฐํ• ๊นŒ?

์ดํŽ™ํŠธ๋Š” ์–ธ์ œ๋‚˜ ์ž์‹ ์ด ์ •์˜๋œ ๋ธ”๋ก ์•ˆ์—์„œ ๋žœ๋”๋ง์ด ์ผ์–ด๋‚  ๋•Œ๋งˆ๋‹ค prop๊ณผ state๋ฅผ โ€œ์ง€์ผœ๋ด…๋‹ˆ๋‹คโ€. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฒ„๊ทธ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ์งœ์ฆ๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿด ๋•Œ๋Š” ๋ช…์‹œ์ ์œผ๋กœ ์–ด๋–ค ๊ฐ’์„ ๊ฐ€๋ณ€์„ฑ ref์— ๋„ฃ์–ด์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋งํฌ์— ์žˆ๋Š” ๊ธ€ ๋ง๋ฏธ์— ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค). ํ˜น์‹œ ๊ธฐ๋Œ€ํ•œ ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ ์ด์ „์— ๋žœ๋”๋ง๋  ๋•Œ์˜ prop์ด๋‚˜ state๊ฐ€ ๋ณด์ธ๋‹ค๋ฉด, ์•„๋งˆ๋„ ์˜์กด์„ฑ ๋ฐฐ์—ด์— ๊ฐ’์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์„ ๊นœ๋นกํ–ˆ์„ ๊ฒ๋‹ˆ๋‹ค. ์ด ๋ฆฐํŠธ ๊ทœ์น™์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ทธ ๊ฐ’์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋„๋ก ์—ฐ์Šตํ•ด ๋ณด์„ธ์š”. ๋ฉฐ์น  ์•ˆ์œผ๋กœ ์ž์—ฐ์Šค๋ ˆ ๋ชธ์— ๋ฐธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ FAQ ๋ฌธ์„œ์—์„œ ์ด ๋‹ต๋ณ€ ๋ถ€๋ถ„์„ ์ฝ์–ด๋ณด์„ธ์š”.


์œ„ ์š”์•…๋ณธ์ด ๋„์›€์ด ๋˜์—ˆ์œผ๋ฉด ์ข‹๊ฒ ๋„ค์š”! ๊ทธ๋Ÿผ ๋ณธ๋ก ์œผ๋กœ ๋“ค์–ด๊ฐ€ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


๋ชจ๋“  ๋žœ๋”๋ง์€ ๊ณ ์œ ์˜ Prop๊ณผ State๊ฐ€ ์žˆ๋‹ค

์ดํŽ™ํŠธ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ธฐ ์ „์—, ๋จผ์ € ๋žœ๋”๋ง์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ ์นด์šดํ„ฐ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ด๋ผ์ดํŠธ๋œ ์ค„์„ ์ž์„ธํžˆ ๋ด ์ฃผ์„ธ์š”.

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

  return (
    <div>
      <p>You clicked {count} times</p>      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

์ด๊ฒŒ ๋ฌด์Šจ ๋œป์ผ๊นŒ์š”? count ๊ฐ€ ์–ด์ฐŒ์ €์ฐŒ state์˜ ๋ณ€ํ™”๋ฅผ ๊ด€์ฐฐํ•˜์—ฌ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค๋Š” ๊ฑธ๊นŒ์š”? ์ฒ˜์Œ์— ๋ฆฌ์•กํŠธ๋ฅผ ๋ฐฐ์šฐ๋ฉด์„œ ์ง๊ด€์ ์œผ๋กœ ๋ฐ›์•„๋“ค์ผ ๋•Œ๋Š” ์œ ์šฉํ•œ ์ƒ๊ฐ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ •ํ™•ํ•œ ๋ฉ˜ํƒˆ ๋ชจ๋ธ์€ ์•„๋‹™๋‹ˆ๋‹ค.

์ด ์˜ˆ์ œ์—์„œ count ๋Š” ๊ทธ์ € ์ˆซ์ž์ž…๋‹ˆ๋‹ค. ๋งˆ๋ฒ•์˜ โ€œ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉโ€ ์ด๋‚˜ โ€œ์›Œ์ณโ€ ๋‚˜ โ€œํ”„๋ก์‹œโ€, ํ˜น์€ ๋น„์Šทํ•œ ๊ทธ ์–ด๋–ค ๊ฒƒ๋„ ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋ƒฅ ์•„๋ž˜์™€ ๊ฐ™์ด ๋‹จ์ˆœํ•œ ์ˆซ์ž์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค.

const count = 42;
// ...
<p>You clicked {count} times</p>
// ...

์ฒ˜์Œ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋žœ๋”๋ง๋  ๋•Œ, useState ๋กœ๋ถ€ํ„ฐ ๊ฐ€์ ธ์˜จ count ๋ณ€์ˆ˜๋Š” 0 ์ž…๋‹ˆ๋‹ค. setCount(1) ์„ ํ˜ธ์ถœํ•˜๋ฉด, ๋‹ค์‹œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ . ์ด ๋•Œ count ๋Š” 1 ์ด ๋˜๋Š” ์‹์ž…๋‹ˆ๋‹ค.

// ์ฒ˜์Œ ๋žœ๋”๋ง ์‹œ
function Counter() {
  const count = 0; // useState() ๋กœ๋ถ€ํ„ฐ ๋ฆฌํ„ด  // ...
  <p>You clicked {count} times</p>
  // ...
}

// ํด๋ฆญํ•˜๋ฉด ํ•จ์ˆ˜๊ฐ€ ๋‹ค์‹œ ํ˜ธ์ถœ๋œ๋‹ค
function Counter() {
  const count = 1; // useState() ๋กœ๋ถ€ํ„ฐ ๋ฆฌํ„ด  // ...
  <p>You clicked {count} times</p>
  // ...
}

// ๋˜ ํ•œ๋ฒˆ ํด๋ฆญํ•˜๋ฉด, ๋‹ค์‹œ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค
function Counter() {
  const count = 2; // useState() ๋กœ๋ถ€ํ„ฐ ๋ฆฌํ„ด  // ...
  <p>You clicked {count} times</p>
  // ...
}

state๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๋•Œ๋งˆ๋‹ค, ๋ฆฌ์•กํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ๋งค ๋žœ๋” ๊ฒฐ๊ณผ๋ฌผ์€ ๊ณ ์œ ์˜ counter ์ƒํƒœ ๊ฐ’์„ โ€œ์‚ดํŽด๋ด…๋‹ˆ๋‹คโ€. ๊ทธ๋ฆฌ๊ณ  ์ด ๊ฐ’์€ ํ•จ์ˆ˜ ์•ˆ์— ์ƒ์ˆ˜๋กœ ์กด์žฌํ•˜๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์œ„์— ํ‘œ์‹œํ•œ ์ค„์€ ์–ด๋– ํ•œ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

<p>You clicked {count} times</p>

์ด๊ฑด ๋žœ๋”๋ง ๊ฒฐ๊ณผ๋ฌผ์— ์ˆซ์ž ๊ฐ’์„ ๋‚ด์žฅํ•˜๋Š” ๊ฒƒ์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค. ์ด ์ˆซ์ž ๊ฐ’์€ ๋ฆฌ์•กํŠธ๋ฅผ ํ†ตํ—ค ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. setCount ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ, ๋ฆฌ์•กํŠธ๋Š” ๋‹ค๋ฅธ count ๊ฐ’๊ณผ ํ•จ๊ป˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์‹œ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋ฆฌ์•กํŠธ๋Š” ๊ฐ€์žฅ ์ตœ์‹ ์˜ ๋žœ๋”๋ง ๊ฒฐ๊ณผ๋ฌผ๊ณผ ์ผ์น˜ํ•˜๋„๋ก DOM์„ ์—…๋ฐ์ดํŠธ ํ•ฉ๋‹ˆ๋‹ค.

๋ช…์‹ฌํ•˜์…”์•ผ ํ•  ์ ์€ ์—ฌ๋А ํŠน์ • ๋žœ๋”๋ง ์‹œ ๊ทธ ์•ˆ์— ์žˆ๋Š” count ์ƒ์ˆ˜๋Š” ์‹œ๊ฐ„์ด ์ง€๋‚œ๋‹ค๊ณ  ๋ฐ”๋€Œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹ค์‹œ ํ˜ธ์ถœ๋˜๊ณ , ๊ฐ๊ฐ์˜ ๋žœ๋”๋ง๋งˆ๋‹ค ๊ฒฉ๋ฆฌ๋œ ๊ณ ์œ ์˜ count ๊ฐ’์„ โ€œ๋ณด๋Š”โ€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

(์ด ๊ณผ์ •์„ ์ž์„ธํžˆ ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด, ์ œ๊ฐ€ ์“ด ๋‹ค๋ฅธ ๊ธ€ UI ๋Ÿฐํƒ€์ž„์œผ๋กœ์„œ์˜ React๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.)

๋ชจ๋“  ๋žœ๋”๋ง์€ ๊ณ ์œ ์˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๊ฐ€์ง„๋‹ค

์—ฌ๊ธฐ๊นŒ์ง„ ํ• ๋งŒํ•˜๋„ค์š”. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ๊ฒฝ์šฐ๋Š” ์–ด๋–จ๊นŒ์š”?

์•„๋ž˜์˜ ์˜ˆ์ œ๋ฅผ ๋ด ์ฃผ์„ธ์š”. ์ด ์ปดํฌ๋„ŒํŠธ๋Š” 3์ดˆ ๋’ค์— count ๊ฐ’๊ณผ ํ•จ๊ป˜ ์–ผ๋Ÿฟ(alert)์„ ๋„์›Œ์ค๋‹ˆ๋‹ค.

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

  function handleAlertClick() {    setTimeout(() => {      alert('You clicked on: ' + count);    }, 3000);  }  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
      <button onClick={handleAlertClick}>
        Show alert      </button>    </div>  );
}

์ œ๊ฐ€ ๋‹จ๊ณ„๋ณ„๋กœ ์ด๋Ÿฐ ๊ณผ์ •์„ ์‹คํ–‰ํ•ด๋ณธ๋‹ค๊ณ  ํ•˜์ฃ .

  • ์นด์šดํ„ฐ๋ฅผ 3์œผ๋กœ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค
  • โ€œShow alertโ€ ์„ ๋ˆ„๋ฅธ๋‹ค
  • ํƒ€์ž„์•„์›ƒ์ด ์‹คํ–‰๋˜๊ธฐ ์ „์— ์นด์šดํ„ฐ๋ฅผ 5๋กœ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค

์นด์šดํ„ฐ ๋ฐ๋ชจ

์ด๋Ÿด ๋•Œ ์–ผ๋Ÿฟ์—๋Š” ์–ด๋–ค ๊ฐ’์ด ๋‚˜ํƒ€๋‚ ๊นŒ์š”? ์–ผ๋Ÿฟ์ด ๋“ฑ์žฅํ•  ๋•Œ์˜ ๊ฐ’์ธ 5๊ฐ€ ๋‚˜์˜ฌ๊นŒ์š”? ์•„๋‹ˆ๋ฉด ์ œ๊ฐ€ โ€œShow alertโ€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•  ๋‹น์‹œ์˜ ๊ฐ’์ธ 3์ด ๋‚˜์˜ฌ๊นŒ์š”?


์Šคํฌ ๋ฐฉ์ง€


ํ•œ๋ฒˆ ์ง์ ‘ ํ•ด ๋ณด์„ธ์š”!

๋งŒ์•ฝ์— ์‹คํ–‰ํ•ด ๋ณธ ๊ฒฐ๊ณผ๊ฐ€ ์ž˜ ๋‚ฉ๋“์ด ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์กฐ๊ธˆ ๋” ์‹ค์งˆ์ ์ธ ์˜ˆ๋ฅผ ์ƒ์ƒํ•ด ๋ณด์„ธ์š”. ์ฑ„ํŒ… ์•ฑ์—์„œ state์— ํ˜„์žฌ ์ˆ˜์‹ ์ž ID๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ƒํƒœ์—์„œ ์ „์†ก ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธ ๊ฒƒ์ด๋‚˜ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์™œ ๊ฒฐ๊ณผ๊ฐ’์œผ๋กœ 3์ด ๋‚˜์™”๋Š”์ง€ ์ด ๊ธ€์ด ์ž์„ธํžˆ ์„ค๋ช…ํ•ด ์ค๋‹ˆ๋‹ค.

์–ผ๋Ÿฟ์€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•  ๋•Œ์˜ state๋ฅผ ์žก์•„๋‘˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

(๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์Šต๋‹ˆ๋‹ค๋งŒ ์ง€๊ธˆ์€ ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ๋ฅผ ์ง‘์ค‘ํ•ด์„œ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฉ˜ํƒˆ ๋ชจ๋ธ์„ ํ˜•์„ฑํ•  ๋•Œ ์ค‘์š”ํ•œ ๊ฒƒ์€ โ€œ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•โ€๊ณผ ๊ธด๊ธ‰ ํ”ผ๋‚œ ํ•ด์น˜๋ฅผ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.)


๊ทธ๋Ÿฐ๋ฐ ์™œ ์ด๋ ‡๊ฒŒ ๋™์ž‘ํ• ๊นŒ์š”?

์•ž์„œ ์šฐ๋ฆฌ๋Š” count ๊ฐ’์ด ๋งค๋ฒˆ ๋ณ„๊ฐœ์˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ๋งˆ๋‹ค ์กด์žฌํ•˜๋Š” ์ƒ์ˆ˜๊ฐ’์ด๋ผ๋Š” ์ด์•ผ๊ธฐ๋ฅผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฑธ ํŠนํžˆ ๊ฐ•์กฐํ•˜๊ณ  ์‹ถ์€๋ฐ, ์šฐ๋ฆฌ์˜ ํ•จ์ˆ˜๋Š” ์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœ๋˜์ง€๋งŒ(๋žœ๋”๋ง๋งˆ๋‹ค ํ•œ ๋ฒˆ์”ฉ), ๊ฐ๊ฐ์˜ ๋žœ๋”๋ง์—์„œ ํ•จ์ˆ˜ ์•ˆ์˜ count ๊ฐ’์€ ์ƒ์ˆ˜์ด์ž ๋…๋ฆฝ์ ์ธ ๊ฐ’(ํŠน์ • ๋žœ๋”๋ง ์‹œ์˜ ์ƒํƒœ)์œผ๋กœ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ๋งŒ ํŠน๋ณ„์ด ์ด๋ ‡๊ฒŒ ๋™์ž‘ํ•˜๋Š”๊ฒŒ ์•„๋‹™๋‹ˆ๋‹ค. ๋ณดํ†ต์˜ ํ•จ์ˆ˜๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

function sayHi(person) {
  const name = person.name;  setTimeout(() => {
    alert('Hello, ' + name);
  }, 3000);
}

let someone = {name: 'Dan'};
sayHi(someone);

someone = {name: 'Yuzhi'};
sayHi(someone);

someone = {name: 'Dominic'};
sayHi(someone);

์ด ์˜ˆ์ œ์—์„œ, ์™ธ๋ถ€์˜ someone ๋ณ€์ˆ˜๋Š” ์—ฌ๋Ÿฌ ๋ฒˆ ์žฌํ• ๋‹น๋ฉ๋‹ˆ๋‹ค. (๋ฆฌ์•กํŠธ ์–ด๋”˜๊ฐ€์—์„œ ํ˜„์žฌ์˜ ์ปดํฌ๋„ŒํŠธ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”.) ํ•˜์ง€๋งŒ sayHi ๋‚ด๋ถ€์—์„œ, ํŠน์ • ํ˜ธ์ถœ๋งˆ๋‹ค person ๊ณผ ์—ฎ์—ฌ์žˆ๋Š” name ์ด๋ผ๋Š” ์ง€์—ญ ์ƒ์ˆ˜๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ด ์ƒ์ˆ˜๋Š” ์ง€์—ญ ์ƒ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ๊ฐ์˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค! ๊ฒฐ๊ณผ์ ์œผ๋กœ ํƒ€์ž„์•„์›ƒ ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค ๊ฐ์ž์˜ ์–ผ๋Ÿฟ์€ ๊ณ ์œ ์˜ name ์„ ๊ธฐ์–ตํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด ์„ค๋ช…์„ ํ†ตํ•ด ํด๋ฆญ ์‹œ ์šฐ๋ฆฌ์˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ count ๊ฐ’์„ ์žก์•„๋‘์—ˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋˜ ํ•œ๋ฒˆ ์•„๋ž˜์™€ ๊ฐ™์ด ์น˜ํ™˜ํ•ด๋ณด๋ฉด, ๋งค ๋žœ๋”๋ง ๋งˆ๋‹ค ๊ฐ๊ฐ์˜ count ๊ฐ’์„ โ€œ๋ณด๋Š”โ€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

// ์ฒ˜์Œ ๋žœ๋”๋ง ์‹œ
function Counter() {
  const count = 0; // useState() ๋กœ๋ถ€ํ„ฐ ๋ฆฌํ„ด  // ...
  function handleAlertClick() {
    setTimeout(() => {
      alert('You clicked on: ' + count);
    }, 3000);
  }
  // ...
}

// ํด๋ฆญํ•˜๋ฉด ํ•จ์ˆ˜๊ฐ€ ๋‹ค์‹œ ํ˜ธ์ถœ๋œ๋‹ค
function Counter() {
  const count = 1; // useState() ๋กœ๋ถ€ํ„ฐ ๋ฆฌํ„ด  // ...
  function handleAlertClick() {
    setTimeout(() => {
      alert('You clicked on: ' + count);
    }, 3000);
  }
  // ...
}

// ๋˜ ํ•œ๋ฒˆ ํด๋ฆญํ•˜๋ฉด, ๋‹ค์‹œ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค
function Counter() {
  const count = 2; // useState() ๋กœ๋ถ€ํ„ฐ ๋ฆฌํ„ด  // ...
  function handleAlertClick() {
    setTimeout(() => {
      alert('You clicked on: ' + count);
    }, 3000);
  }
  // ...
}

๋”ฐ๋ผ์„œ ํšจ๊ณผ์ ์œผ๋กœ, ๊ฐ๊ฐ์˜ ๋žœ๋”๋ง์€ ๊ณ ์œ ํ•œ โ€œ๋ฒ„์ „โ€์˜ handleAlertClick ์„ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ๊ฐ์˜ ๋ฒ„์ „์€ ๊ณ ์œ ์˜ count ๋ฅผ โ€œ๊ธฐ์–ตํ•ฉ๋‹ˆ๋‹คโ€.

// ์ฒ˜์Œ ๋žœ๋”๋ง ์‹œ
function Counter() {
  // ...
  function handleAlertClick() {
    setTimeout(() => {
      alert('You clicked on: ' + 0);    }, 3000);
  }
  // ...
  <button onClick={handleAlertClick} /> // 0์ด ์•ˆ์— ๋“ค์–ด์žˆ์Œ  // ...
}

// ํด๋ฆญํ•˜๋ฉด ํ•จ์ˆ˜๊ฐ€ ๋‹ค์‹œ ํ˜ธ์ถœ๋œ๋‹ค
function Counter() {
  // ...
  function handleAlertClick() {
    setTimeout(() => {
      alert('You clicked on: ' + 1);    }, 3000);
  }
  // ...
  <button onClick={handleAlertClick} /> // 1์ด ์•ˆ์— ๋“ค์–ด์žˆ์Œ  // ...
}

// ๋˜ ํ•œ๋ฒˆ ํด๋ฆญํ•˜๋ฉด, ๋‹ค์‹œ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค
function Counter() {
  // ...
  function handleAlertClick() {
    setTimeout(() => {
      alert('You clicked on: ' + 2);    }, 3000);
  }
  // ...
  <button onClick={handleAlertClick} /> // 2๊ฐ€ ์•ˆ์— ๋“ค์–ด์žˆ์Œ  // ...
}

๊ทธ๋ž˜์„œ ์ด ๋ฐ๋ชจ์—์„œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ํŠน์ • ๋žœ๋”๋ง์— โ€œ์†ํ•ด ์žˆ์œผ๋ฉฐโ€, ์–ผ๋Ÿฟ ํ‘œ์‹œ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•  ๋•Œ ๊ทธ ๋žœ๋”๋ง ์‹œ์ ์˜ counter state๋ฅผ ์œ ์ง€ํ•œ ์ฑ„๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํŠน์ • ๋žœ๋”๋ง ์‹œ ๊ทธ ๋‚ด๋ถ€์—์„œ props์™€ state๋Š” ์˜์›ํžˆ ๊ฐ™์€ ์ƒํƒœ๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. props์™€ state๊ฐ€ ๋žœ๋”๋ง์œผ๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๋‹ค๋ฉด, ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์–ด๋– ํ•œ ๊ฐ’(์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํฌํ•จํ•˜์—ฌ)๋„ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋“ค๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํŠน์ • ๋žœ๋”๋ง์— โ€œ์†ํ•ด ์žˆ์Šต๋‹ˆ๋‹คโ€. ๋”ฐ๋ผ์„œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋‚ด๋ถ€์˜ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ผ ํ• ์ง€๋ผ๋„ ๊ฐ™์€ count ๊ฐ’์„ โ€œ๋ณด๊ฒŒโ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฐธ๊ณ  ๋…ธํŠธ: ์ €๋Š” ์œ„์˜ ์˜ˆ์ œ์—์„œ handleAlertClick ํ•จ์ˆ˜ ์•ˆ์— ์ง์ ‘ ๊ตฌ์ฒด์ ์ธ count ๊ฐ’์„ ๋„ฃ์–ด์„œ ํ‘œ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์น˜ํ™˜ํ•˜์—ฌ ๋ณด๋Š” ๊ฒƒ์€ ์•ˆ์ „ํ•œ๋ฐ, count ๋Š” ๊ฐ๊ฐ์˜ ๋žœ๋”๋ง ๋‚ด๋ถ€์—์„œ ๋ณ€ํ•  ์ˆ˜ ์—†๋Š” ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. const ๋กœ ์„ ์–ธ๋˜์–ด์žˆ๋Š” ์ˆซ์ž ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์ด์ฃ . ๊ฐ์ฒด์™€ ๊ฐ™์ด ๋‹ค๋ฅธ ๊ฐ’์— ๋Œ€ํ•ด์„œ๋„ ๊ฐ™์€ ์ƒ๊ฐ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค๋งŒ, ์˜ค๋กœ์ง€ ๋ถˆ๋ณ€ ๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์ „์ œ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. setSomething(newObj) ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ๊ฐ์ฒด๋ฅผ ๋ณ€ํ˜•ํ•˜์ง€ ์•Š๊ณ  ์ƒˆ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์€ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ์ด์ „ ๋žœ๋”๋ง์— ์†ํ•ด ์žˆ๋Š” state๋Š” ์†์ƒ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋ชจ๋“  ๋žœ๋”๋ง์€ ๊ณ ์œ ์˜ ์ดํŽ™ํŠธ๋ฅผ ๊ฐ€์ง„๋‹ค

์ด ๊ธ€์€ ๋ถ„๋ช… ์ดํŽ™ํŠธ์— ๋Œ€ํ•ด ๋‹ค๋ฃจ๋Š” ๊ธ€์ธ๋ฐ ์•„์ง๊นŒ์ง€ ์ดํŽ™ํŠธ ์ด์•ผ๊ธฐ๋ฅผ ํ•˜์ง€ ์•Š์•˜์ฃ ! ๋“œ๋””์–ด ์ดํŽ™ํŠธ๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์ดํŽ™ํŠธ๋ผ๊ณ  ๊ทธ๋‹ค์ง€ ๋‹ค๋ฅด์ง„ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์„œ์— ์žˆ๋Š” ์˜ˆ์ œ๋กœ ๋Œ์•„๊ฐ€ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

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

  useEffect(() => {    document.title = `You clicked ${count} times`;  });  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

์—ฌ๊ธฐ์„œ ํ•˜๋‚˜ ์งˆ๋ฌธ์„ ๋“œ๋ฆฌ์ฃ . ์–ด๋–ป๊ฒŒ ์ดํŽ™ํŠธ๊ฐ€ ์ตœ์‹ ์˜ count ์ƒํƒœ๋ฅผ ์ฝ์–ด ๋“ค์ผ๊นŒ์š”?

์•„๋งˆ๋„ ๋ญ”๊ฐ€ โ€œ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉโ€ ์ด๋ผ๋˜๊ฐ€ โ€œ์˜ต์ €๋ฒ„โ€ ๋ผ๋˜๊ฐ€ ํ•˜๋Š”๊ฒŒ ์ดํŽ™ํŠธ ํ•จ์ˆ˜ ์•ˆ์—์„œ count ์˜ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฐ˜์˜ํ• ๊นŒ์š”? ์•„๋‹ˆ๋ฉด count ๋Š” ๊ฐ€๋ณ€๊ฐ’์ด๋ผ์„œ ๋ฆฌ์•กํŠธ๊ฐ€ ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ๊ฐ’์„ ์ง€์ •ํ•ด์ฃผ๊ณ  ์ดํŽ™ํŠธ๊ฐ€ ํ•ญ์ƒ ์ตœ์‹  ๊ฐ’์„ ๋ฐ”๋ผ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ฃผ๋Š” ๊ฑธ๊นŒ์š”?

์•„๋‹™๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ด๋ฏธ count ๋Š” ํŠน์ • ์ปดํฌ๋„ŒํŠธ ๋žœ๋”๋ง์— ํฌํ•จ๋˜๋Š” ์ƒ์ˆ˜๋ผ๊ณ  ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋Š” ๊ทธ ๋žœ๋”๋ง์— โ€œ์†ํ•œโ€ count ์ƒํƒœ๋ฅผ โ€œ๋ด…๋‹ˆ๋‹คโ€. count ๋Š” ํŠน์ • ๋ฒ”์œ„ ์•ˆ์— ์†ํ•˜๋Š” ๋ณ€์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ดํŽ™ํŠธ์—๋„ ๋˜‘๊ฐ™์€ ๊ฐœ๋…์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค!

โ€œ๋ณ€ํ™”ํ•˜์ง€ ์•Š๋Š”โ€ ์ดํŽ™ํŠธ ์•ˆ์—์„œ count ๋ณ€์ˆ˜๊ฐ€ ์ž„์˜๋กœ ๋ฐ”๋€๋‹ค๋Š” ๋œป์ด ์•„๋‹™๋‹ˆ๋‹ค. ์ดํŽ™ํŠธ ํ•จ์ˆ˜ ์ž์ฒด๊ฐ€ ๋งค ๋žœ๋”๋ง๋งˆ๋‹ค ๋ณ„๋„๋กœ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

๊ฐ๊ฐ์˜ ์ดํŽ™ํŠธ ๋ฒ„์ „์€ ๋งค๋ฒˆ ๋žœ๋”๋ง์— โ€œ์†ํ•œโ€ count ๊ฐ’์„ โ€œ๋ด…๋‹ˆ๋‹คโ€.

// ์ตœ์ดˆ ๋žœ๋”๋ง ์‹œ
function Counter() {
  // ...
  useEffect(
    // ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ์ดํŽ™ํŠธ ํ•จ์ˆ˜    () => {      document.title = `You clicked ${0} times`;    }  );
  // ...
}

// ํด๋ฆญํ•˜๋ฉด ํ•จ์ˆ˜๊ฐ€ ๋‹ค์‹œ ํ˜ธ์ถœ๋œ๋‹ค
function Counter() {
  // ...
  useEffect(
    // ๋‘ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ์ดํŽ™ํŠธ ํ•จ์ˆ˜    () => {      document.title = `You clicked ${1} times`;    }  );
  // ...
}

// ๋˜ ํ•œ๋ฒˆ ํด๋ฆญํ•˜๋ฉด, ๋‹ค์‹œ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค
function Counter() {
  // ...
  useEffect(
    // ์„ธ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ์ดํŽ™ํŠธ ํ•จ์ˆ˜    () => {      document.title = `You clicked ${2} times`;    }  );
  // ..
}

๋ฆฌ์•กํŠธ๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด ์ œ๊ณตํ•œ ์ดํŽ™ํŠธ ํ•จ์ˆ˜๋ฅผ ๊ธฐ์–ตํ•ด ๋†จ๋‹ค๊ฐ€ DOM์˜ ๋ณ€ํ™”๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์Šคํฌ๋ฆฐ์— ๊ทธ๋ฆฌ๊ณ  ๋‚œ ๋’ค ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋น„๋ก ์šฐ๋ฆฌ๊ฐ€ ํ•˜๋‚˜์˜ ๊ฐœ๋…์œผ๋กœ ์ดํŽ™ํŠธ๋ฅผ ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ์ง€๋งŒ(๋„ํ๋จผํŠธ์˜ ํƒ€์ดํ‹€์„ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ๋™์ž‘), ์‚ฌ์‹ค ๋งค ๋žœ๋”๋ง ๋งˆ๋‹ค ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ผ๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ๊ฐ์˜ ์ดํŽ™ํŠธ ํ•จ์ˆ˜๋Š” ๊ทธ ๋žœ๋”๋ง์— โ€œ์†ํ•œโ€ props์™€ state๋ฅผ โ€œ๋ด…๋‹ˆ๋‹คโ€.

๊ฐœ๋…์ ์œผ๋กœ, ์ดํŽ™ํŠธ๋Š” ๋žœ๋”๋ง ๊ฒฐ๊ณผ์˜ ์ผ๋ถ€๋ผ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—„๊ฒฉํ•˜๊ฒŒ ์ด์•ผ๊ธฐํ•˜์ž๋ฉด ๊ทธ๋ ‡์ง„ ์•Š์Šต๋‹ˆ๋‹ค๋งŒ(๋ณผํ’ˆ ์—†๋Š” ๋ฌธ๋ฒ•์ด๋‚˜ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„ํ—ค๋“œ ์—†์ด ํ›…์˜ ์กฐํ•ฉ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด), ์šฐ๋ฆฌ๊ฐ€ ํ˜•์„ฑํ•˜๊ณ  ์žˆ๋Š” ๋ฉ˜ํƒˆ ๋ชจ๋ธ ์†์—์„œ ์ดํŽ™ํŠธ ํ•จ์ˆ˜๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์ฒ˜๋Ÿผ ํŠน์ • ๋žœ๋”๋ง์— ์†ํ•˜๋Š” ํ•จ์ˆ˜๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.


๋” ์ž์„ธํ•˜๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก, ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง์„ ๋˜์งš์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ๋ฆฌ์•กํŠธ: state๊ฐ€ 0 ์ผ ๋•Œ์˜ UI๋ฅผ ๋ณด์—ฌ์ค˜.
  • ์ปดํฌ๋„ŒํŠธ

    • ์—ฌ๊ธฐ ๋žœ๋”๋ง ๊ฒฐ๊ณผ๋ฌผ๋กœ <p>You clicked 0 times</p> ๊ฐ€ ์žˆ์–ด.
    • ๊ทธ๋ฆฌ๊ณ  ๋ชจ๋“  ์ฒ˜๋ฆฌ๊ฐ€ ๋๋‚˜๊ณ  ์ด ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ: () => { document.title = 'You clicked 0 times' }.
  • ๋ฆฌ์•กํŠธ: ์ข‹์•„. UI๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๊ฒ ์–ด. ์ด๋ด ๋ธŒ๋ผ์šฐ์ €, ๋‚˜ DOM์— ๋ญ˜ ์ข€ ์ถ”๊ฐ€ํ•˜๋ ค๊ณ  ํ•ด.
  • ๋ธŒ๋ผ์šฐ์ €: ์ข‹์•„, ํ™”๋ฉด์— ๊ทธ๋ ค์ค„๊ฒŒ.
  • ๋ฆฌ์•กํŠธ: ์ข‹์•„ ์ด์ œ ์ปดํฌ๋„ŒํŠธ ๋„ค๊ฐ€ ์ค€ ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ• ๊ฑฐ์•ผ.

    • () => { document.title = 'You clicked 0 times' } ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์ค‘.

๊ทธ๋Ÿผ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์–ด๋–ค ์ผ์ด ๋ฒŒ์–ด์ง€๋Š”์ง€ ๋ณต์Šตํ•ด ๋ณด์‹œ์ฃ .

  • ์ปดํฌ๋„ŒํŠธ: ์ด๋ด ๋ฆฌ์•กํŠธ, ๋‚ด ์ƒํƒœ๋ฅผ 1 ๋กœ ๋ณ€๊ฒฝํ•ด์ค˜.
  • ๋ฆฌ์•กํŠธ: ์ƒํƒœ๊ฐ€ 1 ์ผ๋•Œ์˜ UI๋ฅผ ์ค˜.
  • ์ปดํฌ๋„ŒํŠธ

    • ์—ฌ๊ธฐ ๋žœ๋”๋ง ๊ฒฐ๊ณผ๋ฌผ๋กœ <p>You clicked 1 times</p> ๊ฐ€ ์žˆ์–ด.
    • ๊ทธ๋ฆฌ๊ณ  ๋ชจ๋“  ์ฒ˜๋ฆฌ๊ฐ€ ๋๋‚˜๊ณ  ์ด ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ: () => { document.title = 'You clicked 1 times' }.
  • ๋ฆฌ์•กํŠธ: ์ข‹์•„. UI๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๊ฒ ์–ด. ์ด๋ด ๋ธŒ๋ผ์šฐ์ €, ๋‚˜ DOM์— ๋ญ˜ ์ข€ ์ถ”๊ฐ€ํ•˜๋ ค๊ณ  ํ•ด.
  • ๋ธŒ๋ผ์šฐ์ €: ์ข‹์•„, ํ™”๋ฉด์— ๊ทธ๋ ค์ค„๊ฒŒ.
  • ๋ฆฌ์•กํŠธ: ์ข‹์•„ ์ด์ œ ์ปดํฌ๋„ŒํŠธ ๋„ค๊ฐ€ ์ค€ ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ• ๊ฑฐ์•ผ.

    • () => { document.title = 'You clicked 1 times' } ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์ค‘.

๋ชจ๋“  ๋žœ๋”๋ง์€ ๊ณ ์œ ์˜โ€ฆ ๋ชจ๋“  ๊ฒƒ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค

์ด์ œ ์ดํŽ™ํŠธ๋Š” ๋งค ๋žœ๋”๋ง ํ›„ ์‹คํ–‰๋˜๋ฉฐ, ๊ทธ๋ฆฌ๊ณ  ๊ฐœ๋…์ ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ ๊ฒฐ๊ณผ๋ฌผ์˜ ์ผ๋ถ€๋กœ์„œ ํŠน์ • ๋žœ๋”๋ง ์‹œ์ ์˜ prop๊ณผ state๋ฅผ โ€œ๋ณธ๋‹ค๋Š”โ€ ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค.

์ƒ๊ฐ์ด ๋งž๋Š”์ง€ ์‹คํ—˜์„ ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ๋ณด์‹œ์ฃ .

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

  useEffect(() => {    setTimeout(() => {      console.log(`You clicked ${count} times`);    }, 3000);  });  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

์ œ๊ฐ€ ์•ฝ๊ฐ„ ๋œธ์„ ๋“ค์ด๋ฉฐ ๋ฒ„ํŠผ์„ ์—ฌ๋Ÿฌ๋ฒˆ ๋ˆ„๋ฅธ๋‹ค๋ฉด ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚ ๊นŒ์š”?


์Šคํฌ ์ฃผ์˜


์•„๋งˆ ์ด ๋ฌธ์ œ๋Š” ์ผ์ข…์˜ ํ•จ์ •์ด๊ณ  ๊ฒฐ๊ณผ๋ฌผ์€ ์ผ๊ด€๋˜์ง€ ์•Š์œผ๋ฆฌ๋ผ ์ƒ๊ฐํ•˜์…จ๊ฒ ์ง€๋งŒ, ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค! ๋กœ๊ทธ๋Š” ์ˆœ์„œ๋Œ€๋กœ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ ํƒ€์ด๋จธ๋Š” ํŠน์ • ๋žœ๋”๋ง์— ์†ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ์‹œ์ ์˜ count ๊ฐ’์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ์ง์ ‘ ์‹คํ—˜ํ•ด๋ณด์„ธ์š”.

1, 2, 3, 4, 5๊ฐ€ ์ˆœ์„œ๋Œ€๋กœ ๋กœ๋”ฉ๋˜๋Š” ํ™”๋ฉด ๋…นํ™”

์•„๋งˆ โ€œ๋‹น์—ฐํžˆ ์ด๋ ‡๊ฒŒ ๋™์ž‘ํ•˜๊ฒ ์ง€! ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๊ฒ ์–ด?โ€ ๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธ€์Ž„์š”. ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋กœ ๋งŒ๋“ค๋ฉด ์ด๋ ‡๊ฒŒ ๋™์ž‘ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด ๋งํฌ์˜ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋„ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์™€ ๊ฐ™์€ ๋™์ž‘์„ ํ•˜๋ฆฌ๋ผ๊ณ  ์ฐฉ๊ฐํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

componentDidUpdate() {
  setTimeout(() => {
     console.log(`You clicked ${this.state.count} times`);
  }, 3000);
}

ํ•˜์ง€๋งŒ this.state.count ๊ฐ’์€ ํŠน์ • ๋žœ๋”๋ง ์‹œ์ ์˜ ๊ฐ’์ด ์•„๋‹ˆ๋ผ ์–ธ์ œ๋‚˜ ์ตœ์‹ ์˜ ๊ฐ’์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋งค๋ฒˆ 5๊ฐ€ ์ฐํ˜€์žˆ๋Š” ๋กœ๊ทธ๋ฅผ ๋ณด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

5, 5, 5, 5, 5๊ฐ€ ์ˆœ์„œ๋Œ€๋กœ ๋กœ๊น…๋˜๋Š” ํ™”๋ฉด ๋…นํ™”

์ €๋Š” ํ›…์ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํด๋กœ์ €์— ์•„์ฃผ ๋งŽ์ด ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค๋Š”๊ฒŒ ์•„์ด๋Ÿฌ๋‹ˆํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด์— ๋ฐ˜ํ•ด ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋Š” ์ „ํ†ต์ ์œผ๋กœ ํƒ€์ž„์•„์›ƒ์—์„œ ์ž˜๋ชป๋œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฌธ์ œ์— ์‹œ๋‹ฌ๋ฆฌ๊ณ  ์žˆ๋Š”๋ฐ ์ด ๋ฌธ์ œ๋Š” ์ฃผ๋กœ ํด๋กœ์ €์™€ ์—ฐ๊ด€์ด ์žˆ์ง€์š”. ์™œ๋ƒ๋ฉด ์ด ์˜ˆ์‹œ์—์„œ ๋ฐœ์ƒํ•œ ์ง„์งœ ๋ฌธ์ œ์˜ ๊ทผ์›์€ ํด๋กœ์ € ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ๊ฐ€๋ณ€๊ฐ’ ๋ณ€๊ฒฝ(mutation)์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(๋ฆฌ์•กํŠธ๋Š” this.state ๊ฐ€ ์ตœ์‹  ์ƒํƒœ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค).

ํด๋กœ์ €๋Š” ์ ‘๊ทผํ•˜๋ ค๋Š” ๊ฐ’์ด ์ ˆ๋Œ€ ๋ฐ”๋€Œ์ง€ ์•Š์„ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋“œ์‹œ ์ƒ์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ๊ฐ์„ ํ•˜๊ธฐ ์‰ฝ๋„๋ก ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์œ„์—์„œ ๋…ผ์˜ํ•œ ๋Œ€๋กœ props์™€ state๋Š” ํŠน์ • ๋žœ๋”๋ง ์•ˆ์—์„œ ์ ˆ๋Œ€ ๋ฐ”๋€Œ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋‚˜์ €๋‚˜ ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์œ„์˜ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ ์˜ˆ์ œ๋ฅผ ๊ณ ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹คโ€ฆ ํด๋กœ์ €๋ฅผ ์ด์šฉํ•ด์„œ์š”.

ํ๋ฆ„์„ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€๊ธฐ

์ด ์‹œ์ ์—์„œ ๋‹ค์‹œ ํ•œ๋ฒˆ ํฌ๊ฒŒ ๋’ค์˜ ๊ตฌ์ ˆ์„ ์Š์–ด๋ณด๋Š”๊ฒŒ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. โ€œ์ปดํฌ๋„ŒํŠธ์˜ ๋žœ๋”๋ง ์•ˆ์— ์žˆ๋Š” ๋ชจ๋“  ํ•จ์ˆ˜๋Š” (์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ, ์ดํŽ™ํŠธ, ํƒ€์ž„์•„์›ƒ์ด๋‚˜ ๊ทธ ์•ˆ์—์„œ ํ˜ธ์ถœ๋˜๋Š” API ๋“ฑ) ๋žœ๋”(render)๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ์ •์˜๋œ props์™€ state ๊ฐ’์„ ์žก์•„๋‘”๋‹ค.โ€

๋”ฐ๋ผ์„œ ์•„๋ž˜์˜ ๋‘ ์˜ˆ์ œ๋Š” ๊ฐ™์Šต๋‹ˆ๋‹ค.

function Example(props) {
  useEffect(() => {
    setTimeout(() => {
      console.log(props.counter);    }, 1000);
  });
  // ...
}
function Example(props) {
  const counter = props.counter;  useEffect(() => {
    setTimeout(() => {
      console.log(counter);    }, 1000);
  });
  // ...
}

props๋‚˜ state๋ฅผ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ์ผ์ฐ ์ฝ์–ด ๋“ค์˜€๋Š”์ง€ ์•„๋‹Œ์ง€๋Š” ์ƒ๊ด€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ฐ’๋“ค์€ ๋ฐ”๋€Œ์ง€ ์•Š์„ํ…Œ๋‹ˆ๊นŒ์š”! ํ•˜๋‚˜์˜ ๋žœ๋”๋ง ์Šค์ฝ”ํ”„ ์•ˆ์—์„œ props์™€ state๋Š” ๋ณ€ํ•˜์ง€ ์•Š์€ ๊ฐ’์œผ๋กœ ๋‚จ์•„์žˆ์Šต๋‹ˆ๋‹ค. (๊ฐ’๋“ค์„ ๋ถ„ํ•ด ํ• ๋‹นํ•˜๋ฉด ๋” ํ™•์‹คํ•ด์ง‘๋‹ˆ๋‹ค.)

๋ฌผ๋ก  ๋•Œ๋•Œ๋กœ ์ดํŽ™ํŠธ ์•ˆ์— ์ •์˜ํ•ด๋‘” ์ฝœ๋ฐฑ์—์„œ ์‚ฌ์ „์— ์žก์•„๋‘” ๊ฐ’์„ ์“ฐ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ตœ์‹ ์˜ ๊ฐ’์„ ์ด์šฉํ•˜๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ œ์ผ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ref๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ธ๋ฐ ๋งํฌ์˜ ๊ธ€ ๋งˆ์ง€๋ง‰ ๋‹จ๋ฝ์— ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ณผ๊ฑฐ์˜ ๋žœ๋”๋ง ์‹œ์ ์—์„œ ๋ฏธ๋ž˜์˜ props๋‚˜ state๋ฅผ ์กฐํšŒํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ ์ฃผ์˜ํ•˜์…”์•ผ ํ•˜๋Š”๊ฒŒ, ์ด๋Ÿฐ ๋ฐฉ์‹์€ ํ๋ฆ„์„ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€๋Š” ์ผ์ž…๋‹ˆ๋‹ค. ์ž˜๋ชป ๋˜์ง„ ์•Š์•˜์ง€๋งŒ (์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•˜๊ณ ์š”) ํŒจ๋Ÿฌ๋‹ค์ž„์—์„œ ๋ฒ—์–ด๋‚˜๋Š”๊ฒŒ ๋œ โ€œ๊นจ๋—ํ•ดโ€ ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” ์˜๋„์ ์ธ ๊ฒฐ๊ณผ์ธ๋ฐ ํ•˜์ด๋ผ์ดํŠธ ์ณ๋‘” ์ฝ”๋“œ๋Š” ํƒ€์ด๋ฐ์— ๋ฏผ๊ฐํ•˜๊ณ  ๋‹ค๋ฃจ๊ธฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋ผ๋ฉด ์–ธ์ œ ๊ฐ’์„ ์กฐํšŒํ•˜๋Š”์ง€ ๋œ ๋ช…ํ™•ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋กœ ์ผ์œผ์ผฐ๋˜ ๋™์ž‘์„ ๋”ฐ๋ผํ•ด๋ณธ ๋ฒ„์ „์˜ ์นด์šดํ„ฐ ์˜ˆ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

function Example() {
  const [count, setCount] = useState(0);
  const latestCount = useRef(count);  useEffect(() => {
    // ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๊ฐ’์„ ์ตœ์‹ ์œผ๋กœ ์„ค์ •ํ•œ๋‹ค
    latestCount.current = count;    setTimeout(() => {      // ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ์ตœ์‹ ์˜ ๊ฐ’์„ ์ฝ์–ด ๋“ค์ธ๋‹ค
      console.log(`You clicked ${latestCount.current} times`);    }, 3000);  });
  // ...

5, 5, 5, 5, 5๊ฐ€ ์ˆœ์„œ๋Œ€๋กœ ๋กœ๊น…๋˜๋Š” ํ™”๋ฉด ๋…นํ™”

๋ฆฌ์•กํŠธ๋กœ ์–ด๋– ํ•œ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ๊บผ๋ฆผ์น™ํ•ด ๋ณด์ž…๋‹ˆ๋‹ค๋งŒ, ๋ฆฌ์•กํŠธ์˜ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋Š” ์ •ํ™•ํ•˜๊ฒŒ ์ด๋Ÿฐ ์‹์œผ๋กœ this.state ๋ฅผ ์žฌํ• ๋‹นํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฏธ๋ฆฌ ์žก์•„๋‘” props ๋ฐ state์™€๋Š” ๋‹ฌ๋ฆฌ ํŠน์ • ์ฝœ๋ฐฑ์—์„œ latestCount.current ์˜ ๊ฐ’์„ ์ฝ์–ด ๋“ค์ผ ๋•Œ ์–ธ์ œ๋‚˜ ๊ฐ™์€ ๊ฐ’์„ ๋ณด์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ •์˜๋œ ๋ฐ”์— ๋”ฐ๋ผ ์ด ๊ฐ’์€ ์–ธ์ œ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฐ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ๊ธฐ๋ณธ ๋™์ž‘์ด ์•„๋‹ˆ๋ฉฐ, ์—ฌ๋Ÿฌ๋ถ„์ด ์ง์ ‘ ๊ฐ€์ ธ๋‹ค ์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ํด๋ฆฐ์—…(cleanup)์€ ๋ญ์ง€?

๋ฌธ์„œ์—์„œ ์„ค๋ช…ํ•œ ๋Œ€๋กœ, ์–ด๋–ค ์ดํŽ™ํŠธ๋Š” ํด๋ฆฐ์—… ๋‹จ๊ณ„๋ฅผ ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณธ์งˆ์ ์œผ๋กœ ํด๋ฆฐ์—…์˜ ๋ชฉ์ ์€ ๊ตฌ๋…๊ณผ ๊ฐ™์€ ์ดํŽ™ํŠธ๋ฅผ โ€œ๋˜๋Œ๋ฆฌ๋Š”โ€ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ๋ณด์‹œ์ฃ .

useEffect(() => {
  ChatAPI.subscribeToFriendStatus(props.id, handleStatusChange);
  return () => {
    ChatAPI.unsubscribeFromFriendStatus(props.id, handleStatusChange);
  };
});

์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง์—์„œ prop ์ด {id: 10} ์ด๊ณ , ๋‘ ๋ฒˆ์งธ ๋žœ๋”๋ง์—์„œ {id: 20} ์ด๋ผ๊ณ  ํ•ด ๋ด…์‹œ๋‹ค. ์•„๋งˆ๋„ ์•„๋ž˜์™€ ๊ฐ™์€ ํ๋ฆ„๋Œ€๋กœ ํ˜๋Ÿฌ๊ฐ€๋ฆฌ๋ผ ์ƒ๊ฐํ•˜์‹ค๊ฒ๋‹ˆ๋‹ค.

  • ๋ฆฌ์•กํŠธ๊ฐ€ {id: 10} ์„ ๋‹ค๋ฃจ๋Š” ์ดํŽ™ํŠธ๋ฅผ ํด๋ฆฐ์—…ํ•œ๋‹ค.
  • ๋ฆฌ์•กํŠธ๊ฐ€ {id: 20} ์„ ๊ฐ€์ง€๊ณ  UI๋ฅผ ๋žœ๋”๋งํ•œ๋‹ค.
  • ๋ฆฌ์•กํŠธ๊ฐ€ {id: 20} ์œผ๋กœ ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

(์‹ค์ œ๋Š” ์กฐ๊ธˆ ๋‹ค๋ฆ…๋‹ˆ๋‹ค)

์œ„์˜ ๋ฉ˜ํƒˆ ๋ชจ๋ธ๋Œ€๋กœ๋ผ๋ฉด, ํด๋ฆฐ์—…์ด ๋ฆฌ๋žœ๋”๋ง ๋˜๊ธฐ ์ „์— ์‹คํ–‰๋˜๊ณ  ์ด์ „์˜ prop์„ โ€œ๋ณด๊ณ โ€, ๊ทธ ๋‹ค์Œ ์ƒˆ ์ดํŽ™ํŠธ๊ฐ€ ๋ฆฌ๋žœ๋”๋ง ์ดํ›„ ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ prop์„ โ€œ๋ณธ๋‹ค๊ณ โ€ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฉ˜ํƒˆ ๋ชจ๋ธ์€ ํด๋ž˜์Šค์˜ ๋ผ์ดํ”„์‚ฌ์ดํด์„ ๊ทธ๋Œ€๋กœ ์˜ฎ๊ฒจ ๋†“์€ ๊ฒƒ๊ณผ ๊ฐ™๊ณ , ์—ฌ๊ธฐ์„œ๋Š” ์ž˜๋ชป๋œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. ์™œ ๊ทธ๋Ÿฐ์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.

๋ฆฌ์•กํŠธ๋Š” ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํŽ˜์ธํŠธ ํ•˜๊ณ  ๋‚œ ๋’ค์—์•ผ ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜์—ฌ ๋Œ€๋ถ€๋ถ„์˜ ์ดํŽ™ํŠธ๊ฐ€ ์Šคํฌ๋ฆฐ ์—…๋ฐ์ดํŠธ๋ฅผ ๊ฐ€๋กœ๋ง‰์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์•ฑ์„ ๋น ๋ฅด๊ฒŒ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ดํŽ™ํŠธ์˜ ํด๋ฆฐ์—…๋„ ๋ฏธ๋ค„์ง‘๋‹ˆ๋‹ค. ์ด์ „ ์ดํŽ™ํŠธ๋Š” ์ƒˆ prop๊ณผ ํ•จ๊ป˜ ๋ฆฌ๋žœ๋”๋ง ๋˜๊ณ  ๋‚œ ๋’ค์— ํด๋ฆฐ์—…๋ฉ๋‹ˆ๋‹ค.

  • ๋ฆฌ์•กํŠธ๊ฐ€ {id: 20} ์„ ๊ฐ€์ง€๊ณ  UI๋ฅผ ๋žœ๋”๋งํ•œ๋‹ค.
  • ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์‹ค์ œ ๊ทธ๋ฆฌ๊ธฐ๋ฅผ ํ•œ๋‹ค. ํ™”๋ฉด ์ƒ์—์„œ {id: 20} ์ด ๋ฐ˜์˜๋œ UI๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฆฌ์•กํŠธ๋Š” {id: 10} ์— ๋Œ€ํ•œ ์ดํŽ™ํŠธ๋ฅผ ํด๋ฆฐ์—…ํ•œ๋‹ค.
  • ๋ฆฌ์•กํŠธ๊ฐ€ {id: 20} ์— ๋Œ€ํ•œ ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

์ด์ƒํ•˜๊ฒŒ ๋А๋‚„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์–ด๋–ป๊ฒŒ prop์ด {id: 20} ์œผ๋กœ ๋ฐ”๋€Œ๊ณ  ๋‚˜์„œ๋„ ์ด์ „ ์ดํŽ™ํŠธ์˜ ํด๋ฆฐ์—…์ด ์—ฌ์ „ํžˆ ์˜ˆ์ „ ๊ฐ’์ธ {id: 10} ์„ โ€œ๋ณด๋Š”โ€ ๊ฑธ๊นŒ์š”?

์ „์—๋„ ๊ฒช์–ด ๋ณธ ๊ฒƒ ๊ฐ™๊ตฐ์š”โ€ฆ ๐Ÿค”

๋ฐ์ž๋ทฐ (์˜ํ™” ๋งคํŠธ๋ฆญ์Šค์˜ ๊ณ ์–‘์ด ๋“ฑ์žฅ ์”ฌ)

์ด์ „ ๋‹จ๋ฝ์„ ์ธ์šฉํ•ด ๋ณด์ž๋ฉด

์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋žœ๋”๋ง ์•ˆ์— ์žˆ๋Š” ๋ชจ๋“  ํ•จ์ˆ˜๋Š” (์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ, ์ดํŽ™ํŠธ, ํƒ€์ž„์•„์›ƒ์ด๋‚˜ ๊ทธ ์•ˆ์—์„œ ํ˜ธ์ถœ๋˜๋Š” API ๋“ฑ) ๋žœ๋”๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ์ •์˜๋œ props์™€ state ๊ฐ’์„ ์žก์•„๋‘”๋‹ค.

์ด์ œ ๋‹ต์ด ๋ช…ํ™•ํ•ด์กŒ๋„ค์š”! ์–ด์ฐŒ๋˜์—ˆ๊ฑด ์ดํŽ™ํŠธ์˜ ํด๋ฆฐ์—…์€ โ€œ์ตœ์‹ โ€ prop์„ ์ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํด๋ฆฐ์—…์ด ์ •์˜๋œ ์‹œ์ ์˜ ๋žœ๋”๋ง์— ์žˆ๋˜ ๊ฐ’์„ ์ฝ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

// ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง, props๋Š” {id: 10}
function Example() {
  // ...
  useEffect(
    // ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ์ดํŽ™ํŠธ
    () => {
      ChatAPI.subscribeToFriendStatus(10, handleStatusChange);
      // ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ํด๋ฆฐ์—…      return () => {        ChatAPI.unsubscribeFromFriendStatus(10, handleStatusChange);      };    }
  );
  // ...
}

// ๋‹ค์Œ ๋žœ๋”๋ง, props๋Š” {id: 20}
function Example() {
  // ...
  useEffect(
    // ๋‘ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ์ดํŽ™ํŠธ
    () => {
      ChatAPI.subscribeToFriendStatus(20, handleStatusChange);
      // ๋‘ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ํด๋ฆฐ์—…
      return () => {
        ChatAPI.unsubscribeFromFriendStatus(20, handleStatusChange);
      };
    }
  );
  // ...
}

์™•๊ตญ์€ ํฅ๋ง์„ฑ์‡ ๋ฅผ ๊ฑฐ์น˜๊ณ , ํ•ด๋Š” ์ˆ˜๋ช…์„ ๋‹คํ•˜์—ฌ ๋ฐฑ์ƒ‰ ์™œ์„ฑ์œผ๋กœ ๋ณ€ํ•  ๊ฒƒ์ด๋ฉฐ, ๋งˆ์ง€๋ง‰ ๋ฌธ๋ช…์€ ์ข…๋ง์„ ๋งž์ดํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ์–ด๋– ํ•œ ๊ฒƒ๋„ ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ํด๋ฆฐ์—…์ด ๋ฐ”๋ผ๋ณด๋Š” ๊ฐ’์„ {id: 10} ์ด์™ธ์˜ ๊ฒƒ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋ฆฌ์•กํŠธ๋Š” ํŽ˜์ธํŒ… ์ดํ›„ ์ดํŽ™ํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š”๊ฒŒ ๊ธฐ๋ณธ์ด๋ฉฐ ๊ทธ ๊ฒฐ๊ณผ ์•ฑ์„ ๋น ๋ฅด๊ฒŒ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. ์ด์ „ props๋Š” ์šฐ๋ฆฌ์˜ ์ฝ”๋“œ๊ฐ€ ์›ํ•œ๋‹ค๋ฉด ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ผ์ดํ”„์‚ฌ์ดํด์ด ์•„๋‹ˆ๋ผ ๋™๊ธฐํ™”

์ œ๊ฐ€ ๋ฆฌ์•กํŠธ์—์„œ ์ œ์ผ ์ข‹์•„ํ•˜๋Š” ๊ฒƒ ์ค‘ ํ•˜๋‚˜๋Š” ์ฒ˜์Œ ๋žœ๋”๋ง ๊ฒฐ๊ณผ๋ฌผ๊ณผ ๊ทธ ์—…๋ฐ์ดํŠธ๋ฅผ ํ†ตํ•ฉํ•˜์—ฌ ํ‘œํ˜„ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ๊ทธ๋žจ์˜ ์—”ํŠธ๋กœํ”ผ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ๋‹ค๊ณ  ํ•ด ๋ณด์ฃ .

function Greeting({ name }) {
  return (
    <h1 className="Greeting">
      Hello, {name}
    </h1>
  );
}

์ œ๊ฐ€ <Greeting name="Dan" /> ์„ ๋žœ๋”๋ง ํ•œ ๋‹ค์Œ์— <Greeting name="Yuzhi" /> ๋ฅผ ๋žœ๋”๋งํ•˜๋˜์ง€, ์•„์˜ˆ <Greeting name="Yuzhi" /> ๋งŒ ๋žœ๋”๋งํ•˜๋˜์ง€ ๋ชจ๋“  ๊ฒฝ์šฐ์˜ ๊ฒฐ๊ณผ๋Š” โ€œHello, Yuzhiโ€ ๋กœ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฐ ๋ง์ด ์žˆ์Šต๋‹ˆ๋‹ค. โ€œ๋ชจ๋“  ๊ฒƒ์€ ์—ฌ์ •์— ๋‹ฌ๋ ธ์ง€ ๋ชฉ์ ์ง€์— ๋‹ฌ๋ฆฐ ๊ฒƒ์ด ์•„๋‹ˆ๋ผโ€ ๊ณ ์š”. ๋ฆฌ์•กํŠธ์— ์žˆ์–ด์„œ๋Š” ์ • ๋ฐ˜๋Œ€๋กœ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์€ ๋ชฉ์ ์ง€์— ๋‹ฌ๋ ธ์ง€ ์—ฌ์ •์— ๋‹ฌ๋ฆฐ๊ฒŒ ์•„๋‹ˆ๋‹ค. ์ด๊ฒŒ jQuery ์ฝ”๋“œ์—์„œ $.addClass, $.removeClass ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ๊ณผ(โ€œ์—ฌ์ •โ€) ๋ฆฌ์•กํŠธ ์ฝ”๋“œ์—์„œ ์–ด๋–ค CSSํด๋ž˜์Šค๊ฐ€ ์žˆ์–ด์•ผ ํ•˜๋Š”์ง€ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์˜ ์ฐจ์ด์ž…๋‹ˆ๋‹ค(โ€œ๋ชฉ์ ์ง€โ€).

๋ฆฌ์•กํŠธ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ง€์ •ํ•œ props์™€ state์— ๋”ฐ๋ผ DOM๊ณผ ๋™๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. ๋žœ๋”๋ง ์‹œ โ€œ๋งˆ์šดํŠธโ€ ์™€ โ€œ์—…๋ฐ์ดํŠธโ€ ์˜ ๊ตฌ๋ถ„์ด ์—†์Šต๋‹ˆ๋‹ค.

์ดํŽ™ํŠธ๋„ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ์ƒ๊ฐํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค. useEffect ๋Š” ๋ฆฌ์•กํŠธ ํŠธ๋ฆฌ ๋ฐ”๊นฅ์— ์žˆ๋Š” ๊ฒƒ๋“ค์„ props์™€ state์— ๋”ฐ๋ผ ๋™๊ธฐํ™” ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

function Greeting({ name }) {
  useEffect(() => {    document.title = 'Hello, ' + name;  });  return (
    <h1 className="Greeting">
      Hello, {name}
    </h1>
  );
}

์œ„ ์ฝ”๋“œ๋Š” ์นœ์ˆ™ํ•œ ๋งˆ์šดํŠธ/์—…๋ฐ์ดํŠธ/์–ธ๋งˆ์šดํŠธ ๋ฉ˜ํƒˆ ๋ชจ๋ธ๊ณผ๋Š” ๋ฌ˜ํ•˜๊ฒŒ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์„ ๋งˆ์Œ์†์— ๋‹ด์•„๋‘๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒซ ๋ฒˆ์งธ๋กœ ๋žœ๋”๋งํ•  ๋•Œ์™€ ๊ทธ ํ›„์— ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š” ์ดํŽ™ํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋ ค๊ณ  ํ•˜์‹ ๋‹ค๋ฉด, ํ๋ฆ„์„ ๊ฑฐ์Šค๋ฅด๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค! ๋žœ๋”๋ง ๊ฒฐ๊ณผ๋ฌผ์ด โ€œ๋ชฉ์ ์ง€โ€ ์— ๋”ฐ๋ผ๊ฐ€๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ โ€œ์—ฌ์ •โ€ ์— ๋”ฐ๋ฅธ๋‹ค๋ฉด ๋™๊ธฐํ™”์— ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ๋ฅผ prop A, B, C ์ˆœ์„œ๋กœ ๋žœ๋”๋งํ•˜๋˜์ง€, ๋ฐ”๋กœ C๋กœ ๋žœ๋”๋งํ•˜๋˜์ง€ ๋ณ„๋กœ ์‹ ๊ฒฝ์“ฐ์ด์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž ๊น ์ฐจ์ด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ(์˜ˆ: ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ), ๊ฒฐ๊ตญ ๋งˆ์ง€๋ง‰ ๊ฒฐ๊ณผ๋ฌผ์€ ๊ฐ™์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹น์—ฐํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ชจ๋“  ์ดํŽ™ํŠธ๋ฅผ ๋งค๋ฒˆ ๋žœ๋”๋ง๋งˆ๋‹ค ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์€ ํšจ์œจ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (๊ทธ๋ฆฌ๊ณ  ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ๋ฌดํ•œ๋ฃจํ”„๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์ง€์š”.)

๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

๋ฆฌ์•กํŠธ์—๊ฒŒ ์ดํŽ™ํŠธ๋ฅผ ๋น„๊ตํ•˜๋Š” ๋ฒ•์„ ๊ฐ€๋ฅด์น˜๊ธฐ

์šฐ๋ฆฌ๋Š” ์ด๋ฏธ DOM ๊ทธ ์ž์ฒด์— ๋Œ€ํ•ด์„œ๋Š” ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ๋งค๋ฒˆ์˜ ๋ฆฌ๋žœ๋”๋ง๋งˆ๋‹ค DOM ์ „์ฒด๋ฅผ ์ƒˆ๋กœ ๊ทธ๋ฆฌ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋ฆฌ์•กํŠธ๊ฐ€ ์‹ค์ œ๋กœ ๋ฐ”๋€ ๋ถ€๋ถ„๋งŒ DOM์„ ์—…๋ฐ์ดํŠธ ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ

<h1 className="Greeting">
  Hello, Dan
</h1>

์ด๋ ‡๊ฒŒ ๋ฐ”๊พผ๋‹ค๋ฉด

<h1 className="Greeting">
  Hello, Yuzhi
</h1>

๋ฆฌ์•กํŠธ๋Š” ๋‘ ๊ฐ์ฒด๋ฅผ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.

const oldProps = {className: 'Greeting', children: 'Hello, Dan'};
const newProps = {className: 'Greeting', children: 'Hello, Yuzhi'};

๊ฐ๊ฐ์˜ prop์„ ์งš์–ด๋ณด๊ณ  children ์ด ๋ฐ”๋€Œ์–ด์„œ DOM ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๊ณ  ํŒŒ์•…ํ–ˆ์ง€๋งŒ className ์€ ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ทธ์ € ์•„๋ž˜์˜ ์ฝ”๋“œ๋งŒ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

domNode.innerText = 'Hello, Yuzhi';
// domNode.className ์€ ๊ฑด๋“œ๋ฆด ํ•„์š”๊ฐ€ ์—†๋‹ค

์ดํŽ™ํŠธ์—๋„ ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? ์ดํŽ™ํŠธ๋ฅผ ์ ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด ๋‹ค์‹œ ์‹คํ–‰ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์„ํ…๋ฐ์š”.

์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋งˆ ์•„๋ž˜์˜ ์ปดํฌ๋„ŒํŠธ๋Š” ์ƒํƒœ ๋ณ€ํ™” ๋•Œ๋ฌธ์— ๋‹ค์‹œ ๋žœ๋”๋ง ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

function Greeting({ name }) {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    document.title = 'Hello, ' + name;
  });

  return (
    <h1 className="Greeting">
      Hello, {name}
      <button onClick={() => setCounter(count + 1)}>        Increment      </button>    </h1>
  );
}

ํ•˜์ง€๋งŒ ์ดํŽ™ํŠธ๋Š” counter ์ƒํƒœ๊ฐ’์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ดํŽ™ํŠธ๋Š” document.title ๊ณผ name prop์„ ๋™๊ธฐํ™”ํ•˜์ง€๋งŒ, name prop์€ ๊ฐ™์Šต๋‹ˆ๋‹ค. document.title ์„ ๋งค๋ฒˆ ์นด์šดํ„ฐ ๊ฐ’์ด ๋ฐ”๋€”๋•Œ๋งˆ๋‹ค ์žฌํ• ๋‹นํ•˜๋Š” ๊ฒƒ์€ ๊ทธ๋‹ค์ง€ ์ด์ƒ์ ์œผ๋กœ ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ข‹์•„์š”, ๊ทธ๋ ‡๋‹ค๋ฉดโ€ฆ ๋ฆฌ์•กํŠธ๊ฐ€ ๊ทธ๋ƒฅ ์ดํŽ™ํŠธ๋ฅผ ๋น„๊ตํ•˜๋ฉด ์•ˆ ๋ ๊นŒ์š”?

let oldEffect = () => { document.title = 'Hello, Dan'; };
let newEffect = () => { document.title = 'Hello, Dan'; };
// ๋ฆฌ์•กํŠธ๊ฐ€ ์ด ๋ฐฐ์—ด์„ ๊ฐ™์€ ๋ฐฐ์—ด์ด๋ผ๊ณ  ์ธ์‹ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

๊ทธ๋ ‡๊ฒŒ๋Š” ์•ˆ๋˜๊ฒ ๋„ค์š”. ๋ฆฌ์•กํŠธ๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด๋ณด์ง€ ์•Š๊ณ  ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ค ์ผ์„ ํ•˜๋Š”์ง€ ์•Œ์•„๋‚ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. (์ € ์ฝ”๋“œ๋Š” ํŠน์ •ํ•œ ๊ฐ’์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ name prop์— ์žˆ๋Š” ๊ฒƒ์„ ๋‹ด์•„์™”์„ ๋ฟ์ž…๋‹ˆ๋‹ค.)

๊ทธ๋ž˜์„œ ํŠน์ •ํ•œ ์ดํŽ™ํŠธ๊ฐ€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋‹ค์‹œ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์˜์กด์„ฑ ๋ฐฐ์—ด์„(โ€œdepsโ€ ๋ผ๊ณ  ์•Œ๋ ค์ง„ ๋…€์„์ด์ฃ ) useEffect ์˜ ์ธ์ž๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

useEffect(() => {
  document.title = 'Hello, ' + name;
}, [name]); // ์šฐ๋ฆฌ์˜ ์˜์กด์„ฑ

์ด๊ฑด ๋งˆ์น˜ ์šฐ๋ฆฌ๊ฐ€ ๋ฆฌ์•กํŠธ์—๊ฒŒ โ€œ์ด๋ด, ๋„ค๊ฐ€ ์ด ํ•จ์ˆ˜์˜ ์•ˆ์„ ๋ณผ ์ˆ˜ ์—†๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ, ๋žœ๋”๋ง ์Šค์ฝ”ํ”„์—์„œ name ์™ธ์˜ ๊ฐ’์€ ์“ฐ์ง€ ์•Š๋Š”๋‹ค๊ณ  ์•ฝ์†ํ• ๊ฒŒ.โ€ ๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ์™€ ์ด์ „ ์ดํŽ™ํŠธ ๋ฐœ๋™ ์‹œ ์ด ๊ฐ’๋“ค์ด ๊ฐ™๋‹ค๋ฉด ๋™๊ธฐํ™”ํ•  ๊ฒƒ์€ ์—†์œผ๋‹ˆ ๋ฆฌ์•กํŠธ๋Š” ์ดํŽ™ํŠธ๋ฅผ ์Šคํ‚ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const oldEffect = () => { document.title = 'Hello, Dan'; };
const oldDeps = ['Dan'];

const newEffect = () => { document.title = 'Hello, Dan'; };
const newDeps = ['Dan'];

// ๋ฆฌ์•กํŠธ๋Š” ํ•จ์ˆ˜ ์•ˆ์„ ์‚ดํŽด๋ณผ ์ˆ˜ ์—†์ง€๋งŒ, deps๋ฅผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค.
// ๋ชจ๋“  deps๊ฐ€ ๊ฐ™์œผ๋ฏ€๋กœ, ์ƒˆ ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

๋žœ๋”๋ง ์‚ฌ์ด์— ์˜์กด์„ฑ ๋ฐฐ์—ด ์•ˆ์— ์žˆ๋Š” ๊ฐ’์ด ํ•˜๋‚˜๋ผ๋„ ๋‹ค๋ฅด๋‹ค๋ฉด ์ดํŽ™ํŠธ๋ฅผ ์Šคํ‚ตํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์„ ๋™๊ธฐํ™”ํ•ด์•ผ์ฃ !

๋ฆฌ์•กํŠธ์—๊ฒŒ ์˜์กด์„ฑ์œผ๋กœ ๊ฑฐ์ง“๋งํ•˜์ง€ ๋งˆ๋ผ

์˜์กด์„ฑ์— ๋Œ€ํ•ด ๋ฆฌ์•กํŠธ์—๊ฒŒ ๊ฑฐ์ง“๋ง์„ ํ•  ๊ฒฝ์šฐ ์ข‹์ง€ ์•Š์€ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์ง๊ด€์ ์œผ๋กœ ์ด๊ฒŒ ๋ง์€ ๋ฉ๋‹ˆ๋‹ค๋งŒ, ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์— ์ต์ˆ™ํ•œ ๋ฉ˜ํƒˆ ๋ชจ๋ธ์„ ๊ฐ€์ง„ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์ด useEffect ์„ ์“ธ ๋•Œ ๊ทธ ๊ทœ์น™์„ ์–ด๊ธฐ๋ ค๋Š” ๋ชจ์Šต์„ ๋ดค์Šต๋‹ˆ๋‹ค. (์‹ฌ์ง€์–ด ์ €๋„ ์ฒ˜์Œ์—๋Š” ๊ทธ๋žฌ์–ด์š”!)

function SearchResults() {
  async function fetchData() {
    // ...
  }

  useEffect(() => {
    fetchData();
  }, []); // ์ด๊ฒŒ ๋งž์„๊นŒ์š”? ํ•ญ์ƒ ๊ทธ๋ ‡์ง„ ์•Š์ง€์š”. ๊ทธ๋ฆฌ๊ณ  ๋” ๋‚˜์€ ๋ฐฉ์‹์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  // ...
}

(Hooks FAQ์—์„œ ๊ทธ ๋Œ€์‹  ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ•˜๋Š”์ง€ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ๋Š” ์•„๋žซ๋ถ€๋ถ„์—์„œ ๋‹ค์‹œ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค.)

โ€œํ•˜์ง€๋งŒ ์ €๋Š” ๋งˆ์šดํŠธ ๋  ๋•Œ๋งŒ ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๊ณ ์š”!โ€ ๋ผ๊ณ  ํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋‹จ ์ง€๊ธˆ์€ deps๋ฅผ ์ง€์ •ํ•œ๋‹ค๋ฉด, ์ปดํฌ๋„ŒํŠธ์— ์žˆ๋Š” ๋ชจ๋“  ๊ฐ’ ์ค‘ ๊ทธ ์ดํŽ™ํŠธ์— ์‚ฌ์šฉ๋  ๊ฐ’์€ ๋ฐ˜๋“œ์‹œ ๊ฑฐ๊ธฐ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•ด ๋‘์„ธ์š”. props, state, ํ•จ์ˆ˜๋“ค ๋“ฑ ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ์žˆ๋Š” ๋ชจ๋“  ๊ฒƒ ๋ง์ž…๋‹ˆ๋‹ค.

๊ฐ€๋”์€ ์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ํ•˜๋ฉด ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋กœ์ง์ด ๋ฌดํ•œ ๋ฃจํ”„์— ๋น ์งˆ ์ˆ˜๋„ ์žˆ๊ณ , ์†Œ์ผ“์ด ๋„ˆ๋ฌด ์ž์ฃผ ๋ฐ˜์‘ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๊ณง ๊ทธ ํ•ด๊ฒฐ์ฑ…์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ํ•ด๊ฒฐ์ฑ…์œผ๋กœ ๋„˜์–ด๊ฐ€๊ธฐ ์ „์—, ์ด ๋ฌธ์ œ์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์•Œ์•„๋ด…์‹œ๋‹ค.

์˜์กด์„ฑ์œผ๋กœ ๊ฑฐ์ง“๋ง์„ ํ•˜๋ฉด ์ƒ๊ธฐ๋Š” ์ผ

๋งŒ์•ฝ deps๊ฐ€ ์ดํŽ™ํŠธ์— ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ๋ฆฌ์•กํŠธ๋Š” ์–ธ์ œ ๋‹ค์‹œ ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•  ์ง€ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

useEffect(() => {
  document.title = 'Hello, ' + name;
}, [name]);

์ดํŽ™ํŠธ๊ฐ€ ํ•˜๋‚˜๋ฅผ ๋‹ค๋ฅธ ๊ฒƒ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๋‹ค์ด์–ด๊ทธ๋žจ (์˜์กด์„ฑ์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ดํŽ™ํŠธ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•œ๋‹ค.)

ํ•˜์ง€๋งŒ ๋งŒ์•ฝ ์ดํŽ™ํŠธ์— [] ๋ฅผ ๋„˜๊ฒจ์ฃผ์—ˆ๋‹ค๋ฉด, ์ƒˆ ์ดํŽ™ํŠธ ํ•จ์ˆ˜๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

useEffect(() => {
  document.title = 'Hello, ' + name;
}, []); // ํ‹€๋ ธ์Œ: deps์— name์ด ์—†๋‹ค

์ดํŽ™ํŠธ๊ฐ€ ํ•˜๋‚˜๋ฅผ ๋‹ค๋ฅธ ๊ฒƒ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๋‹ค์ด์–ด๊ทธ๋žจ (์˜์กด์„ฑ์ด ๊ฐ™์œผ๋ฏ€๋กœ ์ดํŽ™ํŠธ๋Š” ์Šคํ‚ตํ•œ๋‹ค.)

์ด ๊ฒฝ์šฐ์—๋Š” ๋ฌธ์ œ๊ฐ€ ๋ช…ํ™•ํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ๊ฒฝ์šฐ์— ํด๋ž˜์Šค ์Šคํƒ€์ผ์˜ ํ•ด๊ฒฐ์ฑ…์ด ๊ธฐ์–ต์†์—์„œ ํŠ€์–ด๋‚˜์˜ค๋ฉด ์ด๋Ÿฐ ์ง๊ด€์ด ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋งค ์ดˆ๋งˆ๋‹ค ์ˆซ์ž๊ฐ€ ์˜ฌ๋ผ๊ฐ€๋Š” ์นด์šดํ„ฐ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๊ณ  ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ ๊ฐœ๋…์„ ์ ์šฉํ–ˆ์„ ๋•Œ ์šฐ๋ฆฌ์˜ ์ง๊ด€์€ โ€œ์ธํ„ฐ๋ฒŒ์„ ํ•œ ๋ฒˆ๋งŒ ์„ค์ •ํ•˜๊ณ , ํ•œ ๋ฒˆ๋งŒ ์ œ๊ฑฐํ•˜์žโ€ ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ ์ƒ๊ฐ์„ ์ฝ”๋“œ๋กœ ์˜ฎ๊ธฐ๋ฉด ์ด๋Ÿฐ ์˜ˆ์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ฉ˜ํƒˆ ๋ชจ๋ธ์„ ๊ฐ€์ง€๊ณ  useEffect ๋ฅผ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜ํ•˜๊ฒŒ ๋˜๋ฉด, ์ง๊ด€์ ์œผ๋กœ deps์— [] ๋ฅผ ๋„ฃ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. โ€œ์ด๊ฒŒ ํ•œ๋ฒˆ๋งŒ ์‹คํ–‰๋์œผ๋ฉด ์ข‹๊ฒ ์–ด.โ€ ๋ผ๊ณ ์š”. ๊ทธ๋ ‡์ฃ ?

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

  useEffect(() => {
    const id = setInterval(() => {
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(id);
  }, []);  return <h1>{count}</h1>;
}

ํ•˜์ง€๋งŒ ์ด ์˜ˆ์ œ๋Š” ์ˆซ์ž๊ฐ€ ์˜ค๋กœ์ง€ ํ•œ ๋ฒˆ๋งŒ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์–ด์ด์ฟ .

๋งŒ์•ฝ ์—ฌ๋Ÿฌ๋ถ„์˜ ๋ฉ˜ํƒˆ ๋ชจ๋ธ์ด โ€œ์˜์กด์„ฑ ๋ฐฐ์—ด์€ ๋‚ด๊ฐ€ ์–ธ์ œ ์ดํŽ™ํŠธ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•ด์•ผ ํ• ์ง€ ์ง€์ •ํ•  ๋•Œ ์“ฐ์ธ๋‹ค.โ€ ๋ผ๋ฉด, ์œ„ ์˜ˆ์ œ๋ฅผ ๋ณผ ๋•Œ ์ž๊ฐ€๋‹น์ฐฉ์— ๋น ์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฑด ์ธํ„ฐ๋ฒŒ์ด๋‹ˆ๊นŒ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์ฃ . ๊ทธ๋Ÿฐ๋ฐ ์™œ ์ด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์ผ์–ด๋‚ฌ์„๊นŒ์š”?

ํ•˜์ง€๋งŒ ์˜์กด์„ฑ ๋ฐฐ์—ด์ด ๋ฆฌ์•กํŠธ์—๊ฒŒ ์–ด๋–ค ๋žœ๋”๋ง ์Šค์ฝ”ํ”„์—์„œ ๋‚˜์˜จ ๊ฐ’ ์ค‘ ์ดํŽ™ํŠธ์— ์“ฐ์ด๋Š” ๊ฒƒ ์ „๋ถ€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ํžŒํŠธ๋ผ๊ณ  ์ธ์‹ํ•œ๋‹ค๋ฉด ๋ง์ด ๋ฉ๋‹ˆ๋‹ค. count ๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ deps ๋ฅผ [] ๋ผ๊ณ  ์ •์˜ํ•˜๋ฉด์„œ ๊ฑฐ์ง“๋ง์„ ํ–ˆ์ง€์š”. ์ด ๊ฑฐ์ง“๋ง ๋•Œ๋ฌธ์— ๋ฒ„๊ทธ๊ฐ€ ํ„ฐ์ง€๋Š” ๊ฒƒ์€ ์‹œ๊ฐ„ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค!

์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง์—์„œ count ๋Š” 0 ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ์ดํŽ™ํŠธ์—์„œ setCount(count + 1) ๋Š” setCount(0 + 1) ์ด๋ผ๋Š” ๋œป์ด ๋ฉ๋‹ˆ๋‹ค. deps ๋ฅผ [] ๋ผ๊ณ  ์ •์˜ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ดํŽ™ํŠธ๋ฅผ ์ ˆ๋Œ€ ๋‹ค์‹œ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ , ๊ฒฐ๊ตญ ๊ทธ๋กœ ์ธํ•ด ๋งค ์ดˆ๋งˆ๋‹ค setCount(0 + 1) ์„ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

// ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง, state๋Š” 0
function Counter() {
  // ...
  useEffect(
    // ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ์ดํŽ™ํŠธ
    () => {
      const id = setInterval(() => {
        setCount(0 + 1); // ์–ธ์ œ๋‚˜ setCount(1)      }, 1000);
      return () => clearInterval(id);
    },
    [] // ์ ˆ๋Œ€ ๋‹ค์‹œ ์‹คํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค  );
  // ...
}

// ๋งค๋ฒˆ ๋‹ค์Œ ๋žœ๋”๋ง๋งˆ๋‹ค state๋Š” 1์ด๋‹ค
function Counter() {
  // ...
  useEffect(
    // ์ด ์ดํŽ™ํŠธ๋Š” ์–ธ์ œ๋‚˜ ๋ฌด์‹œ๋  ๊ฒƒ    // ์™œ๋ƒ๋ฉด ๋ฆฌ์•กํŠธ์—๊ฒŒ ๋นˆ deps๋ฅผ ๋„˜๊ฒจ์ฃผ๋Š” ๊ฑฐ์ง“๋ง์„ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ    () => {
      const id = setInterval(() => {
        setCount(1 + 1);
      }, 1000);
      return () => clearInterval(id);
    },
    []
  );
  // ...
}

์šฐ๋ฆฌ๋Š” ๋ฆฌ์•กํŠธ์—๊ฒŒ ์ด ์ดํŽ™ํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ์žˆ๋Š” ๊ฐ’์„ ์“ฐ์ง€ ์•Š๋Š”๋‹ค๊ณ  ๊ฑฐ์ง“๋ง์„ ํ–ˆ์Šต๋‹ˆ๋‹ค, ์‹ค์ œ๋กœ๋Š” ์“ฐ๋Š”๋ฐ๋„ ๋ง์ด์ฃ !

์ดํŽ™ํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ์žˆ๋Š” ๊ฐ’์ธ(ํ•˜์ง€๋งŒ ์ดํŽ™ํŠธ ๋ฐ”๊นฅ์— ์žˆ๋Š”) count ๊ฐ’์„ ์“ฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

const count = // ...
useEffect(() => {
  const id = setInterval(() => {
    setCount(count + 1);  }, 1000);
  return () => clearInterval(id);
}, []);

๋”ฐ๋ผ์„œ [] ์„ ์˜์กด์„ฑ ๋ฐฐ์—ด๋กœ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์€ ๋ฒ„๊ทธ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ๋Š” ๋ฐฐ์—ด์„ ๋น„๊ตํ•˜๊ณ , ์ด ์ดํŽ™ํŠธ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ž˜๋ชป๋œ ์ธํ„ฐ๋ฒŒ ํด๋กœ์ €์˜ ๋‹ค์ด์–ด๊ทธ๋žจ (์˜์กด์„ฑ์ด ๊ฐ™์œผ๋ฏ€๋กœ ์ดํŽ™ํŠธ๋Š” ์Šคํ‚ตํ•œ๋‹ค.)

์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ์ด์Šˆ๋Š” ํ•ด๊ฒฐ์ฑ…์„ ๋– ์˜ฌ๋ฆฌ๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ €๋Š” ์—ฌ๋Ÿฌ๋ถ„๋“ค๊ป˜ ์–ธ์ œ๋‚˜ ์ดํŽ™ํŠธ์— ์˜์กด์„ฑ์„ ์†”์งํ•˜๊ฒŒ ์ „๋ถ€ ๋ช…์‹œํ•˜๋Š” ๊ฒƒ์„ ์ค‘์š”ํ•œ ๊ทœ์น™์œผ๋กœ ๋ฐ›์•„๋“ค์—ฌ์•ผ ํ•œ๋‹ค๊ณ  ๊ถŒํ•ฉ๋‹ˆ๋‹ค. (์ €ํฌ๋Š” ์—ฌ๋Ÿฌ๋ถ„๋“ค์˜ ํŒ€์ด ์ด ๊ทœ์น™์„ ๊ฐ•์ œํ•˜๊ธธ ์›ํ•  ๋•Œ ์“ธ ์ˆ˜ ์žˆ๋Š” ๋ฆฐํŠธ ๊ทœ์น™์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.)

์˜์กด์„ฑ์„ ์†”์งํ•˜๊ฒŒ ์ ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•

์˜์กด์„ฑ์„ ์†”์งํ•˜๊ฒŒ ์ ๋Š”๋ฐ ๋‘ ๊ฐ€์ง€ ์ „๋žต์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด ๋ณด์‹œ๊ณ , ํ•„์š”ํ•˜๋‹ค๋ฉด ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ์žˆ์œผ๋ฉด์„œ ์ดํŽ™ํŠธ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“  ๊ฐ’์ด ์˜์กด์„ฑ ๋ฐฐ์—ด ์•ˆ์— ํฌํ•จ๋˜๋„๋ก ๊ณ ์น˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. count ๋ฅผ deps์— ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

useEffect(() => {
  const id = setInterval(() => {
    setCount(count + 1);  }, 1000);
  return () => clearInterval(id);
}, [count]);

์ด๋ ‡๊ฒŒ ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ƒ์ ์ด์ง€ ์•Š์„ ์ˆ˜ ์žˆ์ง€๋งŒ ์šฐ๋ฆฌ๊ฐ€ ๊ณ ์ณ์•ผ ํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ œ count ๊ฐ’์€ ์ดํŽ™ํŠธ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๊ณ  ๋งค๋ฒˆ ๋‹ค์Œ ์ธํ„ฐ๋ฒŒ์—์„œ setCount(count + 1) ๋ถ€๋ถ„์€ ํ•ด๋‹น ๋žœ๋”๋ง ์‹œ์ ์˜ count ๊ฐ’์„ ์‚ฌ์šฉํ•  ๊ฒ๋‹ˆ๋‹ค.

// ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง, state๋Š” 0
function Counter() {
  // ...
  useEffect(
    // ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ์ดํŽ™ํŠธ
    () => {
      const id = setInterval(() => {
        setCount(0 + 1); // setCount(count + 1)      }, 1000);
      return () => clearInterval(id);
    },
    [0] // [count]  );
  // ...
}

// ๋‘ ๋ฒˆ์งธ ๋žœ๋”๋ง, state๋Š” 1
function Counter() {
  // ...
  useEffect(
    // ๋‘ ๋ฒˆ์งธ ๋žœ๋”๋ง์˜ ์ดํŽ™ํŠธ
    () => {
      const id = setInterval(() => {
        setCount(1 + 1); // setCount(count + 1)      }, 1000);
      return () => clearInterval(id);
    },
    [1] // [count]  );
  // ...
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ฒ ์ง€๋งŒ count ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ์ธํ„ฐ๋ฒŒ์€ ํ•ด์ œ๋˜๊ณ  ๋‹ค์‹œ ์„ค์ •๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋งˆ ์›ํ•˜์ง€ ์•Š๋˜ ๋™์ž‘์ด๊ฒ ์ฃ .

์žฌ๊ตฌ๋…ํ•˜๋Š” ์ธํ„ฐ๋ฒŒ์˜ ๋‹ค์ด์–ด๊ทธ๋žจ (์˜์กด์„ฑ์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ดํŽ™ํŠธ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•œ๋‹ค)


๋‘ ๋ฒˆ์งธ ์ „๋žต์€ ์ดํŽ™ํŠธ์˜ ์ฝ”๋“œ๋ฅผ ๋ฐ”๊ฟ”์„œ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋˜ ๊ฒƒ ๋ณด๋‹ค ์ž์ฃผ ๋ฐ”๋€Œ๋Š” ๊ฐ’์„ ์š”๊ตฌํ•˜์ง€ ์•Š๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜์กด์„ฑ์— ๋Œ€ํ•ด ๊ฑฐ์ง“๋ง์„ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ƒฅ ์˜์กด์„ฑ์„ ๋” ์ ๊ฒŒ ๋„˜๊ฒจ์ฃผ๋„๋ก ๋ฐ”๊พธ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ๊ณตํ†ต์ ์ธ ๊ธฐ์ˆ ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


์ดํŽ™ํŠธ๊ฐ€ ์ž๊ธ‰์ž์กฑ ํ•˜๋„๋ก ๋งŒ๋“ค๊ธฐ

์šฐ๋ฆฌ๋Š” ์ดํŽ™ํŠธ์˜ ์˜์กด์„ฑ์—์„œ count ๋ฅผ ์ œ๊ฑฐํ•˜๋„๋ก ๋งŒ๋“ค๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

useEffect(() => {
  const id = setInterval(() => {
    setCount(count + 1);  }, 1000);
  return () => clearInterval(id);
}, [count]);

๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋จผ์ € ์ž์‹ ์—๊ฒŒ ์งˆ๋ฌธ์„ ํ•ด ๋ด…์‹œ๋‹ค. ๋ฌด์—‡ ๋•Œ๋ฌธ์— count ๋ฅผ ์“ฐ๊ณ  ์žˆ๋‚˜์š”? ์˜ค๋กœ์ง€ setCount ๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ์— ์Šค์ฝ”ํ”„ ์•ˆ์—์„œ count ๋ฅผ ์“ธ ํ•„์š”๊ฐ€ ์ „ํ˜€ ์—†์Šต๋‹ˆ๋‹ค. ์ด์ „ ์ƒํƒœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ƒํƒœ ๊ฐ’์„ ์—…๋ฐ์ดํŠธ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋Š”, setState ์— ํ•จ์ˆ˜ ํ˜•ํƒœ์˜ ์—…๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

useEffect(() => {
  const id = setInterval(() => {
    setCount(c => c + 1);  }, 1000);
  return () => clearInterval(id);
}, []);

์ €๋Š” ์ด๋Ÿฐ ๊ฒฝ์šฐ๋ฅผ โ€œ์ž˜๋ชป๋œ ์˜์กด๊ด€๊ณ„โ€ ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ๋„ค, count ๋Š” ์šฐ๋ฆฌ๊ฐ€ setCount(count + 1) ์ด๋ผ๊ณ  ์ผ๊ธฐ ๋•Œ๋ฌธ์— ์ดํŽ™ํŠธ ์•ˆ์—์„œ ํ•„์š”ํ•œ ์˜์กด์„ฑ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ง„์งœ๋กœ ์šฐ๋ฆฌ๋Š” count ๋ฅผ count + 1 ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฆฌ์•กํŠธ์—๊ฒŒ โ€œ๋Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•ดโ€ ์›ํ–ˆ์„ ๋ฟ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฆฌ์•กํŠธ๋Š” ํ˜„์žฌ์˜ count ๋ฅผ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๋ฆฌ์•กํŠธ์—๊ฒŒ ์•Œ๋ ค์ค˜์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์ง€๊ธˆ ๊ฐ’์ด ๋ญ๋“  ๊ฐ„์— ์ƒํƒœ ๊ฐ’์„ ํ•˜๋‚˜ ๋”ํ•˜๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒŒ ์ •ํ™•ํžˆ setCount(c => c +1) ์ด ์˜๋„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ์—๊ฒŒ ์ƒํƒœ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ฐ”๋€Œ์–ด์•ผ ํ•˜๋Š”์ง€ โ€œ์ง€์นจ์„ ๋ณด๋‚ด๋Š” ๊ฒƒโ€ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด โ€œ์—…๋ฐ์ดํ„ฐ ํ˜•ํƒœโ€ ๋˜ํ•œ ๋‹ค๋ฅธ ์ผ€์ด์Šค์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์—…๋ฐ์ดํŠธ๋ฅผ ๋ฌถ์–ด์„œ ์ฒ˜๋ฆฌํ•  ๋•Œ์ฒ˜๋Ÿผ์š”.

*์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜์ง€ ์•Š๊ณ ๋„ ์‹ค์ œ๋กœ *๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„๋‘์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ผผ์ˆ˜๋ฅผ ์“ฐ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ดํŽ™ํŠธ๋Š” ๋” ์ด์ƒ ๋žœ๋”๋ง ์Šค์ฝ”ํ”„์—์„œ count ๊ฐ’์„ ์ฝ์–ด ๋“ค์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š” ์ธํ„ฐ๋ฒŒ์˜ ๋‹ค์ด์–ด๊ทธ๋žจ (์˜์กด์„ฑ์€ ๊ฐ™์œผ๋ฏ€๋กœ ์ดํŽ™ํŠธ๋Š” ์Šคํ‚ตํ•œ๋‹ค.)

์—ฌ๊ธฐ์„œ ์‹คํ—˜ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ดํŽ™ํŠธ๊ฐ€ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜์—ˆ๋‹ค ํ•˜๋”๋ผ๋„, ์ฒซ ๋ฒˆ์งธ ๋žœ๋”๋ง์— ํฌํ•จ๋˜๋Š” ์ธํ„ฐ๋ฒŒ ์ฝœ๋ฐฑ์€ ์ธํ„ฐ๋ฒŒ์ด ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค c => c + 1 ์ด๋ผ๋Š” ์—…๋ฐ์ดํŠธ ์ง€์นจ์„ ์ „๋‹ฌํ•˜๋Š”๋ฐ ์™„๋ฒฝํ•˜๊ฒŒ ๋“ค์–ด๋งž์Šต๋‹ˆ๋‹ค. ๋” ์ด์ƒ ํ˜„์žฌ์˜ count ์ƒํƒœ๋ฅผ ์•Œ๊ณ  ์žˆ์„ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ๊ฐ€ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ์œผ๋‹ˆ๊นŒ์š”.

ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ์™€ ๊ตฌ๊ธ€ ๋‹ฅ์Šค(Google Docs)

์–ด๋–ป๊ฒŒ ๋™๊ธฐํ™”๊ฐ€ ์ดํŽ™ํŠธ์˜ ๋ฉ˜ํƒˆ ๋ชจ๋ธ์ด ๋˜๋Š”์ง€ ์„ค๋ช…ํ–ˆ๋Š”์ง€ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? ๋™๊ธฐํ™”์— ๋Œ€ํ•ด ์ƒ๊ฐํ•  ๋•Œ ํฅ๋ฏธ๋กœ์šด ๋ถ€๋ถ„์€ ์ข…์ข… ์‹œ์Šคํ…œ๊ฐ„์˜ โ€œ๋ฉ”์„ธ์ง€โ€๋ฅผ ์ƒํƒœ์™€ ์—ฎ์ด์ง€ ์•Š์€ ์ฑ„๋กœ ์œ ์ง€ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ตฌ๊ธ€ ๋‹ฅ์Šค์—์„œ ๋ฌธ์„œ๋ฅผ ํŽธ์ง‘ํ•˜๋Š” ๊ฒƒ์€ ์‹ค์ œ๋กœ ์„œ๋ฒ„๋กœ ์ „์ฒด ํŽ˜์ด์ง€๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๊ต‰์žฅํžˆ ๋น„ํšจ์œจ์ ์ด๊ฒ ์ฃ . ๊ทธ ๋Œ€์‹  ์‚ฌ์šฉ์ž๊ฐ€ ๋ฌด์—‡์„ ํ•˜๊ณ ์ž ํ–ˆ๋Š”์ง€ ํ‘œํ˜„ํ•œ ๊ฒƒ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋‹ค๋ฅด๊ฒ ์ง€๋งŒ ์ดํŽ™ํŠธ์—๋„ ๊ฐ™์€ ์ฒ ํ•™์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜ค๋กœ์ง€ ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ์ •๋ณด๋ฅผ ์ดํŽ™ํŠธ ์•ˆ์—์„œ ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌํ•˜๋Š”๊ฒŒ ์ตœ์ ํ™”์— ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. setCount(c => c + 1) ๊ฐ™์€ ์—…๋ฐ์ดํ„ฐ ํ˜•ํƒœ๋Š” setCount(count + 1) ๋ณด๋‹ค ๋ช…๋ฐฑํžˆ ์ ์€ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ์˜ ์นด์šดํŠธ ๊ฐ’์— โ€œ์˜ค์—ผ๋˜์ง€โ€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ์ € ํ–‰์œ„(โ€œ์ฆ๊ฐ€โ€)๋ฅผ ํ‘œํ˜„ํ•  ๋ฟ์ž…๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ๋กœ ์ƒ๊ฐํ•˜๊ธฐ ๋ฌธ์„œ์— ์ตœ์†Œํ•œ์˜ ์ƒํƒœ๋ฅผ ์ฐพ์œผ๋ผ๋Š” ๋‚ด์šฉ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋ฌธ์„œ์— ์“ฐ์ธ ๊ฒƒ๊ณผ ๊ฐ™์€ ์›์น™์ด์ง€๋งŒ ์—…๋ฐ์ดํŠธ์— ํ•ด๋‹น๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์„ธ์š”.

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

ํ•˜์ง€๋งŒ setCount(c => c + 1) ์กฐ์ฐจ๋„ ๊ทธ๋ฆฌ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ์•„๋‹™๋‹ˆ๋‹ค. ์ข€ ์ด์ƒํ•ด ๋ณด์ด๊ธฐ๋„ ํ•˜๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์ด ๊ต‰์žฅํžˆ ์ œํ•œ์ ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์„œ๋กœ์—๊ฒŒ ์˜์กดํ•˜๋Š” ๋‘ ์ƒํƒœ ๊ฐ’์ด ์žˆ๊ฑฐ๋‚˜ prop ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์Œ ์ƒํƒœ๋ฅผ ๊ณ„์‚ฐํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ๋Š” ๋„์›€์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹คํ–‰ํžˆ๋„ setCount(c => c + 1) ์€ ๋” ๊ฐ•๋ ฅํ•œ ์ž๋งค ํŒจํ„ด์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ useReducer ์ž…๋‹ˆ๋‹ค.

์•ก์…˜์„ ์—…๋ฐ์ดํŠธ๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌํ•˜๊ธฐ

์ด์ „์˜ ์˜ˆ์ œ๋ฅผ count ์™€ step ๋‘ ๊ฐ€์ง€ ์ƒํƒœ ๋ณ€์ˆ˜๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์œผ๋กœ ๋ฐ”๊ฟ”๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ธํ„ฐ๋ฒŒ์€ step ์ž…๋ ฅ๊ฐ’์— ๋”ฐ๋ผ count ๊ฐ’์„ ๋”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

function Counter() {
  const [count, setCount] = useState(0);
  const [step, setStep] = useState(1);

  useEffect(() => {
    const id = setInterval(() => {
      setCount(c => c + step);    }, 1000);
    return () => clearInterval(id);
  }, [step]);  return (
    <>
      <h1>{count}</h1>
      <input value={step} onChange={e => setStep(Number(e.target.value))} />
    </>
  );
}

(์—ฌ๊ธฐ ๋ฐ๋ชจ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.)

์ด๊ฑด ๊ผผ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ ์•Œ์•„๋‘์„ธ์š”. ์ œ๊ฐ€ step ์„ ์ดํŽ™ํŠธ ์•ˆ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜์กด์„ฑ ๋ฐฐ์—ด์— ์ถ”๊ฐ€ํ•ด ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ฝ”๋“œ๋Š” ์ •ํ™•ํ•˜๊ฒŒ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค.

์ด ์˜ˆ์ œ์˜ ํ˜„์žฌ ๋™์ž‘์€ step ์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์ธํ„ฐ๋ฒŒ์„ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์™œ๋ƒ๋ฉด ์˜์กด์„ฑ์œผ๋กœ ์ •์˜๋˜์–ด ์žˆ์œผ๋‹ˆ๊นŒ์š”. ๊ทธ๋ฆฌ๊ณ  ๋งŽ์€ ๊ฒฝ์šฐ์— ์ด๊ฒŒ ์ •ํ™•ํžˆ ์—ฌ๋Ÿฌ๋ถ„์ด ์›ํ•˜๋˜ ๋™์ž‘์ผ ๊ฒ๋‹ˆ๋‹ค! ์ดํŽ™ํŠธ๋ฅผ ๋ถ„ํ•ดํ•˜๊ณ  ์ƒˆ๋กœ ์„ค์ •ํ•˜๋Š”๋ฐ๋Š” ์•„๋ฌด ๋ฌธ์ œ๊ฐ€ ์—†๊ณ , ํŠน๋ณ„ํžˆ ์ข‹์€ ์ด์œ ๊ฐ€ ์žˆ์ง€ ์•Š๋‹ค๋ฉด ๋ถ„ํ•ดํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜์ง€ ๋ง์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ step ์ด ๋ฐ”๋€๋‹ค๊ณ  ์ธํ„ฐ๋ฒŒ ์‹œ๊ณ„๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ์›ํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? ์ดํŽ™ํŠธ์˜ ์˜์กด์„ฑ ๋ฐฐ์—ด์—์„œ step ์„ ์ œ๊ฑฐํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ์š”?

์–ด๋–ค ์ƒํƒœ ๋ณ€์ˆ˜๊ฐ€ ๋‹ค๋ฅธ ์ƒํƒœ ๋ณ€์ˆ˜์˜ ํ˜„์žฌ ๊ฐ’์— ์—ฐ๊ด€๋˜๋„๋ก ์„ค์ •ํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด, ๋‘ ์ƒํƒœ ๋ณ€์ˆ˜ ๋ชจ๋‘ useReducer ๋กœ ๊ต์ฒดํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

setSomething(something => ...) ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ๋Œ€์‹  ๋ฆฌ๋“€์„œ๋ฅผ ์จ๋ณด๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜๊ธฐ ์ข‹์€ ํƒ€์ด๋ฐ์ž…๋‹ˆ๋‹ค. ๋ฆฌ๋“€์„œ๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ ์ผ์–ด๋‚˜๋Š” โ€œ์•ก์…˜โ€์˜ ํ‘œํ˜„๊ณผ ๊ทธ ๋ฐ˜์‘์œผ๋กœ ์ƒํƒœ๊ฐ€ ์–ด๋–ป๊ฒŒ ์—…๋ฐ์ดํŠธ๋˜์–ด์•ผ ํ• ์ง€๋ฅผ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์ดํŽ™ํŠธ ์•ˆ์—์„œ step ์˜์กด์„ฑ์„ dispatch ๋กœ ๋ฐ”๊พธ์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

const [state, dispatch] = useReducer(reducer, initialState);const { count, step } = state;

useEffect(() => {
  const id = setInterval(() => {
    dispatch({ type: 'tick' }); // setCount(c => c + step) ๋Œ€์‹ ์—  }, 1000);
  return () => clearInterval(id);
}, [dispatch]);

(๋ฐ๋ชจ๋ฅผ ๋ณด์„ธ์š”.)

์•„๋งˆ โ€œ์ด๊ฒŒ ๋ญ๊ฐ€ ๋” ์ข‹์•„์š”?โ€ ๋ผ๊ณ  ๋ฌผ์–ด๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์œ ์ง€๋˜๋Š” ํ•œ dispatch ํ•จ์ˆ˜๊ฐ€ ํ•ญ์ƒ ๊ฐ™๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์œ„์˜ ์˜ˆ์ œ์—์„œ ์ธํ„ฐ๋ฒŒ์„ ๋‹ค์‹œ ๊ตฌ๋…ํ•  ํ•„์š”์กฐ์ฐจ ์—†์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋๋„ค์š”!

(๋ฆฌ์•กํŠธ๊ฐ€ dispatch, setState, useRef ์ปจํ…Œ์ด๋„ˆ ๊ฐ’์ด ํ•ญ์ƒ ๊ณ ์ •๋˜์–ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๋‹ˆ๊นŒ ์˜์กด์„ฑ ๋ฐฐ์—ด์—์„œ ๋บ„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ช…์‹œํ•œ๋‹ค๊ณ  ํ•ด์„œ ๋‚˜์  ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค.)

์ดํŽ™ํŠธ ์•ˆ์—์„œ ์ƒํƒœ๋ฅผ ์ฝ๋Š” ๋Œ€์‹  ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚ฌ๋Š”์ง€ ์•Œ๋ ค์ฃผ๋Š” ์ •๋ณด๋ฅผ ์ธ์ฝ”๋”ฉํ•˜๋Š” ์•ก์…˜์„ ๋””์ŠคํŒจ์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜์—ฌ ์ดํŽ™ํŠธ๋Š” step ์ƒํƒœ๋กœ๋ถ€ํ„ฐ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ดํŽ™ํŠธ๋Š” ์–ด๋–ป๊ฒŒ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ ํ• ์ง€ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š๊ณ , ๋‹จ์ง€ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚ฌ๋Š”์ง€ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฆฌ๋“€์„œ๊ฐ€ ์—…๋ฐ์ดํŠธ ๋กœ์ง์„ ๋ชจ์•„๋‘ก๋‹ˆ๋‹ค.

const initialState = {
  count: 0,
  step: 1,
};

function reducer(state, action) {
  const { count, step } = state;
  if (action.type === 'tick') {    return { count: count + step, step };  } else if (action.type === 'step') {
    return { count, step: action.step };
  } else {
    throw new Error();
  }
}

(์œ„์—์„œ ๋†“์ณค๋‹ค๋ฉด ์—ฌ๊ธฐ ๋ฐ๋ชจ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.)

์™œ useReducer๊ฐ€ Hooks์˜ ์น˜ํŠธ ๋ชจ๋“œ์ธ๊ฐ€

์šฐ๋ฆฌ๋Š” ์ดํŽ™ํŠธ๊ฐ€ ์ด์ „ ์ƒํƒœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ƒํƒœ๋ฅผ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ ์–ด๋–ป๊ฒŒ ์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜๋Š”์ง€ ์‚ดํŽด๋ดค์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค์Œ ์ƒํƒœ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š”๋ฐ props ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด ์–ด๋–จ๊นŒ์š”? ์˜ˆ๋ฅผ ๋“ค์–ด API๊ฐ€ <Count step={1} /> ์ธ๊ฑฐ์ฃ . ๋‹น์—ฐํ•˜์ง€๋งŒ ์ด๋Ÿด ๋•Œ ์˜์กด์„ฑ์œผ๋กœ props.step ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•  ์ˆœ ์—†๊ฒ ์ฃ ?

์‚ฌ์‹ค์€ ํ”ผํ•  ์ˆ˜ ์žˆ์–ด์š”! ๋ฆฌ๋“€์„œ ๊ทธ ์ž์ฒด๋ฅผ ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ์ •์˜ํ•˜์—ฌ props๋ฅผ ์ฝ๋„๋ก ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

function Counter({ step }) {  const [count, dispatch] = useReducer(reducer, 0);

  function reducer(state, action) {
    if (action.type === 'tick') {
      return state + step;    } else {
      throw new Error();
    }
  }

  useEffect(() => {
    const id = setInterval(() => {
      dispatch({ type: 'tick' });
    }, 1000);
    return () => clearInterval(id);
  }, [dispatch]);

  return <h1>{count}</h1>;
}

์ด ํŒจํ„ด์€ ๋ช‡ ๊ฐ€์ง€ ์ตœ์ ํ™”๋ฅผ ๋ฌดํšจํ™”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋””์„œ๋‚˜ ์“ฐ์ง„ ๋งˆ์„ธ์š”. ํ•˜์ง€๋งŒ ํ•„์š”ํ•˜๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ๋ฆฌ๋“€์„œ ์•ˆ์—์„œ props์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์—ฌ๊ธฐ ๋ฐ๋ชจ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.)

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

์•„๋งˆ ์ด๋ ‡๊ฒŒ ์ƒ๊ฐํ•˜์‹ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. โ€œ์ด๊ฒŒ ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ•˜์ง€? ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ ๋žœ๋”๋ง์— ํฌํ•จ๋œ ์ดํŽ™ํŠธ ์•ˆ์—์„œ ํ˜ธ์ถœ๋œ ๋ฆฌ๋“€์„œ๊ฐ€ props๋ฅผ โ€œ์•Œ๊ณ โ€ ์žˆ์ง€?โ€ ๋‹ต์€ dispatch ๋ฅผ ํ•  ๋•Œ์— ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ๋Š” ๊ทธ์ € ์•ก์…˜์„ ๊ธฐ์–ตํ•ด ๋†“์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค์Œ ๋žœ๋”๋ง ์ค‘์— ๋ฆฌ๋“€์„œ๋ฅผ ํ˜ธ์ถœํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์‹œ์ ์—์„œ ์ƒˆ props๊ฐ€ ์Šค์ฝ”ํ”„ ์•ˆ์œผ๋กœ ๋“ค์–ด์˜ค๊ณ  ์ดํŽ™ํŠธ ๋‚ด๋ถ€์™€๋Š” ์ƒ๊ด€์ด ์—†๊ฒŒ ๋˜์ฃ .

์ด๋ž˜์„œ ์ œ๊ฐ€ useReducer ๋ฅผ Hooks์˜ โ€œ์น˜ํŠธ ๋ชจ๋“œโ€ ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—…๋ฐ์ดํŠธ ๋กœ์ง๊ณผ ๊ทธ๋กœ ์ธํ•ด ๋ฌด์—‡์ด ์ผ์–ด๋‚˜๋Š”์ง€ ์„œ์ˆ ํ•˜๋Š” ๊ฒƒ์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ์€ ์ดํŽ™ํŠธ์˜ ๋ถˆํ•„์š”ํ•œ ์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜์—ฌ ํ•„์š”ํ•  ๋•Œ๋ณด๋‹ค ๋” ์ž์ฃผ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

ํ•จ์ˆ˜๋ฅผ ์ดํŽ™ํŠธ ์•ˆ์œผ๋กœ ์˜ฎ๊ธฐ๊ธฐ

ํ”ํ•œ ์‹ค์ˆ˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ ํ•จ์ˆ˜๋Š” ์˜์กด์„ฑ์— ํฌํ•จ๋˜๋ฉด ์•ˆ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ด ์ฝ”๋“œ๋Š” ๋™์ž‘ํ•˜๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

function SearchResults() {
  const [data, setData] = useState({ hits: [] });

  async function fetchData() {
    const result = await axios(
      'https://hn.algolia.com/api/v1/search?query=react',
    );
    setData(result.data);
  }

  useEffect(() => {
    fetchData();
  }, []); // ์ด๊ฑฐ ๊ดœ์ฐฎ์€๊ฐ€?  // ...

(์ด ์˜ˆ์ œ๋Š” Robin Wieruch์˜ ๋ฉ‹์ง„ ๊ธ€์—์„œ ์ฐจ์šฉํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‚ดํŽด๋ณด์„ธ์š”!)

์ผ๋‹จ ์ด ์ฝ”๋“œ๋Š” ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ„๋‹จํžˆ ๋กœ์ปฌ ํ•จ์ˆ˜๋ฅผ ์˜์กด์„ฑ์—์„œ ์ œ์™ธํ•˜๋Š” ํ•ด๊ฒฐ์ฑ…์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ปค์ง€๋ฉด์„œ ๋ชจ๋“  ๊ฒฝ์šฐ๋ฅผ ๋‹ค๋ฃจ๊ณ  ์žˆ๋Š”์ง€ ๋ณด์žฅํ•˜๊ธฐ ์•„์ฃผ ํž˜๋“ค๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค!

๊ฐ ํ•จ์ˆ˜๊ฐ€ 5๋ฐฐ์ •๋„๋Š” ์ปค์ ธ์„œ ์ฝ”๋“œ๋ฅผ ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๋‚˜๋ˆ„์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ด…์‹œ๋‹ค.

function SearchResults() {
  // ์ด ํ•จ์ˆ˜๊ฐ€ ๊ธธ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ด…์‹œ๋‹ค
  function getFetchUrl() {
    return 'https://hn.algolia.com/api/v1/search?query=react';
  }

  // ์ด ํ•จ์ˆ˜๋„ ๊ธธ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ด…์‹œ๋‹ค
  async function fetchData() {
    const result = await axios(getFetchUrl());
    setData(result.data);
  }

  useEffect(() => {
    fetchData();
  }, []);

  // ...
}

์ด์ œ ๋‚˜์ค‘์— ์ด ํ•จ์ˆ˜๋“ค ์ค‘์— ํ•˜๋‚˜๊ฐ€ state๋‚˜ prop์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ด…์‹œ๋‹ค.

function SearchResults() {
  const [query, setQuery] = useState('react');

  // ์ด ํ•จ์ˆ˜๊ฐ€ ๊ธธ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ด…์‹œ๋‹ค
  function getFetchUrl() {
    return 'https://hn.algolia.com/api/v1/search?query=' + query;  }

  // ์ด ํ•จ์ˆ˜๊ฐ€ ๊ธธ๋‹ค๊ณ  ์ƒ์ƒํ•ด ๋ด…์‹œ๋‹ค
  async function fetchData() {
    const result = await axios(getFetchUrl());
    setData(result.data);
  }

  useEffect(() => {
    fetchData();
  }, []);

  // ...
}

๋งŒ์•ฝ ์ด๋Ÿฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์–ด๋– ํ•œ ์ดํŽ™ํŠธ์—๋„ deps๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์„ ๊นœ๋นกํ–ˆ๋‹ค๋ฉด(์•„๋งˆ๋„ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ์š”!), ์ดํŽ™ํŠธ๋Š” prop๊ณผ state์˜ ๋ณ€ํ™”์— ๋™๊ธฐํ™”ํ•˜๋Š”๋ฐ ์‹คํŒจํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋‹ค์ง€ ์ข‹์ง€ ์•Š๋„ค์š”.

๋‹คํ–‰ํžˆ๋„, ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์‰ฌ์šด ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋– ํ•œ ํ•จ์ˆ˜๋ฅผ ์ดํŽ™ํŠธ ์•ˆ์—์„œ๋งŒ ์“ด๋‹ค๋ฉด, ๊ทธ ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ์ดํŽ™ํŠธ ์•ˆ์œผ๋กœ ์˜ฎ๊ธฐ์„ธ์š”.

function SearchResults() {
  // ...
  useEffect(() => {
    // ์•„๊นŒ์˜ ํ•จ์ˆ˜๋“ค์„ ์•ˆ์œผ๋กœ ์˜ฎ๊ฒผ์–ด์š”!    function getFetchUrl() {      return 'https://hn.algolia.com/api/v1/search?query=react';    }    async function fetchData() {      const result = await axios(getFetchUrl());      setData(result.data);    }    fetchData();
  }, []); // โœ… Deps๋Š” OK
  // ...
}

(์—ฌ๊ธฐ ๋ฐ๋ชจ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.)

์ด๋Ÿฌ๋ฉด ๋ญ๊ฐ€ ์ข‹์•„์ง€๋ƒ๊ตฌ์š”? ์šฐ๋ฆฌ๋Š” ๋” ์ด์ƒ โ€œ์˜ฎ๊ฒจ์ง€๋Š” ์˜์กด์„ฑโ€ ์— ์‹ ๊ฒฝ ์“ธ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์˜์กด์„ฑ ๋ฐฐ์—ด์€ ๋” ์ด์ƒ ๊ฑฐ์ง“๋ง ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ง„์งœ๋กœ ์ดํŽ™ํŠธ ์•ˆ์—์„œ ์ปดํฌ๋„ŒํŠธ์˜ ๋ฒ”์œ„ ๋ฐ”๊นฅ์— ์žˆ๋Š” ๊ทธ ์–ด๋– ํ•œ ๊ฒƒ๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜์ค‘์— getFetchUrl ์„ ์ˆ˜์ •ํ•˜๊ณ  query state๋ฅผ ์จ์•ผํ•œ๋‹ค๊ณ  ํ•˜๋ฉด, ์ดํŽ™ํŠธ ์•ˆ์— ์žˆ๋Š” ํ•จ์ˆ˜๋งŒ ๊ณ ์น˜๋ฉด ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์‰ฌ์ด ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฑฐ๊ธฐ์— ๋”ํ•ด query ๋ฅผ ์ดํŽ™ํŠธ์˜ ์˜์กด์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•ด์•ผ๊ฒ ์ง€์š”.

function SearchResults() {
  const [query, setQuery] = useState('react');

  useEffect(() => {
    function getFetchUrl() {
      return 'https://hn.algolia.com/api/v1/search?query=' + query;    }

    async function fetchData() {
      const result = await axios(getFetchUrl());
      setData(result.data);
    }

    fetchData();
  }, [query]); // โœ… Deps๋Š” OK  // ...
}

(์—ฌ๊ธฐ ๋ฐ๋ชจ์ž…๋‹ˆ๋‹ค.)

์ด ์˜์กด์„ฑ์„ ๋”ํ•˜๋Š” ๊ฒƒ์ด ๋‹จ์ˆœํžˆ โ€œ๋ฆฌ์•กํŠธ๋ฅผ ๋‹ฌ๋ž˜๋Š”โ€ ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. query ๊ฐ€ ๋ฐ”๋€” ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ํŽ˜์นญํ•˜๋Š” ๊ฒƒ์ด ๋ง์ด ๋ฉ๋‹ˆ๋‹ค. useEffect ์˜ ๋””์ž์ธ์€ ์‚ฌ์šฉ์ž๊ฐ€ ์ œํ’ˆ์„ ์‚ฌ์šฉํ•˜๋‹ค ๊ฒช์„ ๋•Œ๊นŒ์ง€ ๋ฌด์‹œํ•˜๋Š” ๋Œ€์‹ , ๋ฐ์ดํ„ฐ ํ๋ฆ„์˜ ๋ณ€ํ™”๋ฅผ ์•Œ์•„์ฐจ๋ฆฌ๊ณ  ์ดํŽ™ํŠธ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™๊ธฐํ™”ํ•ด์•ผํ• ์ง€ ์„ ํƒํ•˜๋„๋ก ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.

eslint-plugin-react-hooks ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ exhaustive-deps ๋ฆฐํŠธ ๋ฃฐ ๋•๋ถ„์—, ์—๋””ํ„ฐ์—์„œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด์„œ ์ดํŽ™ํŠธ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์–ด๋–ค ์˜์กด์„ฑ์ด ๋น ์ ธ ์žˆ๋Š”์ง€ ์ œ์•ˆ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅด๊ฒŒ ์ด์•ผ๊ธฐํ•˜์ž๋ฉด ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ์–ด๋–ค ๋ฐ์ดํ„ฐ ํ๋ฆ„์˜ ๋ณ€ํ™”๊ฐ€ ์ œ๋Œ€๋กœ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๊ณ  ์žˆ๋Š”์ง€ ์ปดํ“จํ„ฐ๊ฐ€ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋‹ค๋Š”๊ฑฐ์ฃ .

๋ฆฐํŠธ ๊ทœ์น™ gif

๊ฝค ์ข‹์ง€์š”.

ํ•˜์ง€๋งŒ ์ €๋Š” ์ด ํ•จ์ˆ˜๋ฅผ ์ดํŽ™ํŠธ ์•ˆ์— ๋„ฃ์„ ์ˆ˜ ์—†์–ด์š”

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

์ด๋Ÿฐ ํ•จ์ˆ˜๋ฅผ ์ดํŽ™ํŠธ์˜ ์˜์กด์„ฑ์œผ๋กœ ์ •์˜ํ•˜์ง€ ๋ง์•„์•ผ ํ• ๊นŒ์š”? ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋งํ•˜์ž๋ฉด, ์ดํŽ™ํŠธ๋Š” ์ž์‹ ์˜ ์˜์กด์„ฑ์— ๋Œ€ํ•ด ๊ฑฐ์ง“๋ง์„ ํ•˜๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค. ๋ณดํ†ต์€ ๋” ๋‚˜์€ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ”ํ•œ ์˜คํ•ด ์ค‘ ํ•˜๋‚˜๊ฐ€ โ€œํ•จ์ˆ˜๋Š” ์ ˆ๋Œ€ ๋ฐ”๋€Œ์ง€ ์•Š๋Š”๋‹คโ€ ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๊ธ€์„ ํ†ตํ•ด ๋ฐฐ์› ๋“ฏ, ๊ทธ ๋ง์ด ์ง„์‹ค๋กœ๋ถ€ํ„ฐ ์–ผ๋งˆ๋‚˜ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค์€, ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ์ •์˜๋œ ํ•จ์ˆ˜๋Š” ๋งค ๋žœ๋”๋ง๋งˆ๋‹ค ๋ฐ”๋€๋‹ˆ๋‹ค!

ํ•˜์ง€๋งŒ ๊ทธ๋กœ ์ธํ•ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋‘ ์ดํŽ™ํŠธ๊ฐ€ getFetchUrl ์„ ํ˜ธ์ถœํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ด…์‹œ๋‹ค.

function SearchResults() {
  function getFetchUrl(query) {
    return 'https://hn.algolia.com/api/v1/search?query=' + query;
  }

  useEffect(() => {
    const url = getFetchUrl('react');
    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•œ๋‹ค ...
  }, []); // ๐Ÿ”ด ๋น ์ง„ dep: getFetchUrl

  useEffect(() => {
    const url = getFetchUrl('redux');
    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•œ๋‹ค ...
  }, []); // ๐Ÿ”ด ๋น ์ง„ dep: getFetchUrl

  // ...
}

์ด ๊ฒฝ์šฐ getFetchUrl ์„ ๊ฐ๊ฐ์˜ ์ดํŽ™ํŠธ ์•ˆ์œผ๋กœ ์˜ฎ๊ธฐ๊ฒŒ ๋˜๋ฉด ๋กœ์ง์„ ๊ณต์œ ํ•  ์ˆ˜ ์—†์œผ๋‹ˆ ๊ทธ๋‹ค์ง€ ๋‹ฌ๊ฐ‘์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‘ ์ดํŽ™ํŠธ ๋ชจ๋‘ (๋งค ๋žœ๋”๋ง๋งˆ๋‹ค ๋ฐ”๋€Œ๋Š”) getFetchUrl ์— ๊ธฐ๋Œ€๊ณ  ์žˆ์œผ๋‹ˆ, ์˜์กด์„ฑ ๋ฐฐ์—ด๋„ ์“ธ๋ชจ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

function SearchResults() {
  // ๐Ÿ”ด ๋งค๋ฒˆ ๋žœ๋”๋ง๋งˆ๋‹ค ๋ชจ๋“  ์ดํŽ™ํŠธ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•œ๋‹ค  function getFetchUrl(query) {    return 'https://hn.algolia.com/api/v1/search?query=' + query;  }  useEffect(() => {
    const url = getFetchUrl('react');
    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•œ๋‹ค ...
  }, [getFetchUrl]); // ๐Ÿšง Deps๋Š” ๋งž์ง€๋งŒ ๋„ˆ๋ฌด ์ž์ฃผ ๋ฐ”๋€๋‹ค

  useEffect(() => {
    const url = getFetchUrl('redux');
    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•œ๋‹ค ...
  }, [getFetchUrl]); // ๐Ÿšง Deps๋Š” ๋งž์ง€๋งŒ ๋„ˆ๋ฌด ์ž์ฃผ ๋ฐ”๋€๋‹ค

  // ...
}

๊ตฌ๋ฏธ๊ฐ€ ๋‹น๊ธฐ๋Š” ํ•ด๊ฒฐ์ฑ…์€ ๊ทธ๋ƒฅ getFetchUrl ํ•จ์ˆ˜๋ฅผ ์˜์กด์„ฑ ๋ฐฐ์—ด์—์„œ ๋นผ ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ €๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ผ ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์šฐ๋ฆฌ๊ฐ€ ์–ธ์ œ ์ดํŽ™ํŠธ์— ์˜ํ•ด ๋‹ค๋ฃจ์–ด์งˆ ํ•„์š”๊ฐ€ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ํ๋ฆ„์— ๋ณ€ํ™”๋ฅผ ๋”ํ•ด์•ผ ํ• ์ง€ ์•Œ์•„์ฐจ๋ฆฌ๊ธฐ ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค.

๋Œ€์‹  ๋” ๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ์ฑ…์ด ๋‘ ๊ฐœ ์žˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ €, ํ•จ์ˆ˜๊ฐ€ ์ปดํฌ๋„ŒํŠธ ์Šค์ฝ”ํ”„ ์•ˆ์˜ ์–ด๋– ํ•œ ๊ฒƒ๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€๋กœ ๋Œ์–ด์˜ฌ๋ ค๋‘๊ณ  ์ดํŽ™ํŠธ ์•ˆ์—์„œ ์ž์œ ๋กญ๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

// โœ… ๋ฐ์ดํ„ฐ ํ๋ฆ„์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š”๋‹คfunction getFetchUrl(query) {  return 'https://hn.algolia.com/api/v1/search?query=' + query;}function SearchResults() {
  useEffect(() => {
    const url = getFetchUrl('react');
    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•œ๋‹ค ...
  }, []); // โœ… Deps๋Š” OK

  useEffect(() => {
    const url = getFetchUrl('redux');
    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•œ๋‹ค ...
  }, []); // โœ… Deps๋Š” OK

  // ...
}

์ € ํ•จ์ˆ˜๋Š” ๋žœ๋”๋ง ์Šค์ฝ”ํ”„์— ํฌํ•จ๋˜์–ด์žˆ์ง€ ์•Š์œผ๋ฉฐ ๋ฐ์ดํ„ฐ ํ๋ฆ„์— ์˜ํ–ฅ์„ ๋ฐ›์„ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— deps์— ๋ช…์‹œํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์šฐ์—ฐํžˆ๋ผ๋„ props๋‚˜ state๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ˜น์€ useCallback ํ›…์œผ๋กœ ๊ฐ์Œ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function SearchResults() {
  // โœ… ์—ฌ๊ธฐ ์ •์˜๋œ deps๊ฐ€ ๊ฐ™๋‹ค๋ฉด ํ•ญ๋“ฑ์„ฑ์„ ์œ ์ง€ํ•œ๋‹ค  const getFetchUrl = useCallback((query) => {    return 'https://hn.algolia.com/api/v1/search?query=' + query;  }, []);  // โœ… ์ฝœ๋ฐฑ์˜ deps๋Š” OK  useEffect(() => {
    const url = getFetchUrl('react');
    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•œ๋‹ค ...
  }, [getFetchUrl]); // โœ… ์ดํŽ™ํŠธ์˜ deps๋Š” OK

  useEffect(() => {
    const url = getFetchUrl('redux');
    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•œ๋‹ค ...
  }, [getFetchUrl]); // โœ… ์ดํŽ™ํŠธ์˜ deps๋Š” OK

  // ...
}

useCallback ์€ ์˜์กด์„ฑ ์ฒดํฌ์— ๋ ˆ์ด์–ด๋ฅผ ํ•˜๋‚˜ ๋” ๋”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹ฌ๋ฆฌ ๋งํ•ด ๋ฌธ์ œ๋ฅผ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐํ•˜๋Š”๋ฐ, ํ•จ์ˆ˜์˜ ์˜์กด์„ฑ์„ ํ”ผํ•˜๊ธฐ๋ณด๋‹ค ํ•จ์ˆ˜ ์ž์ฒด๊ฐ€ ํ•„์š”ํ•  ๋•Œ๋งŒ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์ ‘๊ทผ๋ฐฉ์‹์ด ์™œ ์œ ์šฉํ•œ์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์•„๊นŒ ์˜ˆ์ œ๋Š” 'react', 'redux' ๋ผ๋Š” ๋‘ ๊ฐ€์ง€ ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ž…๋ ฅ์„ ๋ฐ›๋Š” ๋ถ€๋ถ„์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ž„์˜์˜ query ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•ด ๋ด…์‹œ๋‹ค. ๊ทธ๋ž˜์„œ query ๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ๋Œ€์‹ , getFetchUrl ์ด ์ง€์—ญ ์ƒํƒœ๋กœ๋ถ€ํ„ฐ ์ด๋ฅผ ์ฝ์–ด๋“ค์ž…๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ฒŒ ์ˆ˜์ •ํ•˜๋ฉด ์ฆ‰์‹œ query ์˜์กด์„ฑ์ด ๋น ์ ธ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ํŒŒ์•…ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

function SearchResults() {
  const [query, setQuery] = useState('react');
  const getFetchUrl = useCallback(() => { // No query argument
    return 'https://hn.algolia.com/api/v1/search?query=' + query;
  }, []); // ๐Ÿ”ด ๋น ์ง„ ์˜์กด์„ฑ: query  // ...
}

์ œ๊ฐ€ useCallback ์˜ deps์— query ๋ฅผ ํฌํ•จํ•˜๋„๋ก ๊ณ ์น˜๋ฉด, getFetchUrl ์„ ์‚ฌ์šฉํ•˜๋Š” ์–ด๋– ํ•œ ์ดํŽ™ํŠธ๋ผ๋„ query ๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๋‹ค์‹œ ์‹คํ–‰๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

function SearchResults() {
  const [query, setQuery] = useState('react');

  // โœ… query๊ฐ€ ๋ฐ”๋€” ๋•Œ๊นŒ์ง€ ํ•ญ๋“ฑ์„ฑ์„ ์œ ์ง€ํ•œ๋‹ค  const getFetchUrl = useCallback(() => {    return 'https://hn.algolia.com/api/v1/search?query=' + query;  }, [query]);  // โœ… ์ฝœ๋ฐฑ deps๋Š” OK  useEffect(() => {
    const url = getFetchUrl();
    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•œ๋‹ค ...
  }, [getFetchUrl]); // โœ… ์ดํŽ™ํŠธ์˜ deps๋Š” OK

  // ...
}

useCallback ๋•๋ถ„์— query ๊ฐ€ ๊ฐ™๋‹ค๋ฉด, getFetchUrl ๋˜ํ•œ ๊ฐ™์„ ๊ฒƒ์ด๋ฉฐ, ์ดํŽ™ํŠธ๋Š” ๋‹ค์‹œ ์‹คํ–‰๋˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋งŒ์•ฝ query ๊ฐ€ ๋ฐ”๋€๋‹ค๋ฉด, getFetchUrl ๋˜ํ•œ ๋ฐ”๋€Œ๋ฉฐ, ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ํŽ˜์นญํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋งˆ์น˜ ์—‘์…€ ์Šคํ”„๋ ˆ๋“œ์‹œํŠธ์—์„œ ์–ด๋–ค ์…€์„ ๋ฐ”๊พธ๋ฉด ๋‹ค๋ฅธ ์…€์ด ์ž๋™์œผ๋กœ ๋‹ค์‹œ ๊ณ„์‚ฐ๋˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๊ทธ์ € ๋ฐ์ดํ„ฐ ํ๋ฆ„๊ณผ ๋™๊ธฐํ™”์— ๋Œ€ํ•œ ๊ฐœ๋…์„ ๋ฐ›์•„๋“ค์ธ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ํ•จ์ˆ˜ prop์„ ๋‚ด๋ ค๋ณด๋‚ด๋Š” ๊ฒƒ ๋˜ํ•œ ๊ฐ™์€ ํ•ด๊ฒฐ์ฑ…์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

function Parent() {
  const [query, setQuery] = useState('react');

  // โœ… query๊ฐ€ ๋ฐ”๋€” ๋•Œ๊นŒ์ง€ ํ•ญ๋“ฑ์„ฑ์„ ์œ ์ง€ํ•œ๋‹ค  const fetchData = useCallback(() => {    const url = 'https://hn.algolia.com/api/v1/search?query=' + query;    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฆฌํ„ดํ•œ๋‹ค ...  }, [query]);  // โœ… ์ฝœ๋ฐฑ deps๋Š” OK  return <Child fetchData={fetchData} />
}

function Child({ fetchData }) {
  let [data, setData] = useState(null);

  useEffect(() => {
    fetchData().then(setData);
  }, [fetchData]); // โœ… ์ดํŽ™ํŠธ deps๋Š” OK

  // ...
}

fetchData ๋Š” ์˜ค๋กœ์ง€ Parent ์˜ query ์ƒํƒœ๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งŒ ๋ณ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, Child ์ปดํฌ๋„ŒํŠธ๋Š” ์•ฑ์— ๊ผญ ํ•„์š”ํ•  ๋•Œ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ํŽ˜์นญํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•จ์ˆ˜๋„ ๋ฐ์ดํ„ฐ ํ๋ฆ„์˜ ์ผ๋ถ€์ธ๊ฐ€?

ํฅ๋ฏธ๋กญ๊ฒŒ๋„ ์ด ํŒจํ„ด์€ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋ฉด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋ฐ, ์ด๊ฒŒ ์ดํŽ™ํŠธ์™€ ๋ผ์ดํ”„์‚ฌ์ดํด ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ๊ฒฐ์ •์ ์ธ ์ฐจ์ด๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์œ„์˜ ์ฝ”๋“œ๋ฅผ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋กœ ์น˜ํ™˜ํ•ด๋ดค๋‹ค๊ณ  ์นฉ์‹œ๋‹ค.

class Parent extends Component {
  state = {
    query: 'react'
  };
  fetchData = () => {    const url = 'https://hn.algolia.com/api/v1/search?query=' + this.state.query;    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•œ๋‹ค ...  };  render() {
    return <Child fetchData={this.fetchData} />;
  }
}

class Child extends Component {
  state = {
    data: null
  };
  componentDidMount() {    this.props.fetchData();  }  render() {
    // ...
  }
}

์•„๋งˆ๋„ ์ด๋Ÿฐ ์ƒ๊ฐ์„ ํ•˜์‹ค๊ฒ๋‹ˆ๋‹ค. โ€œ์ด๋ด์š” ๋Œ„, ์ด์ œ ์šฐ๋ฆฌ ๋ชจ๋‘ useEffect ๋Š” componentDidMount ์™€ componentDidUpdate ๊ฐ€ ์„ž์ธ ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ๊ณ„์† ๋’ท๋ถ์„ ์น  ํ•„์š”๋Š” ์—†๋‹ค๊ตฌ์š”!โ€ ํ•˜์ง€๋งŒ ์ด ๋กœ์ง์€ componentDidUpdate ์—์„  ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

class Child extends Component {
  state = {
    data: null
  };
  componentDidMount() {
    this.props.fetchData();
  }
  componentDidUpdate(prevProps) {    // ๐Ÿ”ด ์ด ์กฐ๊ฑด๋ฌธ์€ ์ ˆ๋Œ€ ์ฐธ์ด ๋  ์ˆ˜ ์—†๋‹ค    if (this.props.fetchData !== prevProps.fetchData) {      this.props.fetchData();    }  }  render() {
    // ...
  }
}

๋‹น์—ฐํžˆ๋„ fetchData ๋Š” ํด๋ž˜์Šค ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค! (์•„๋‹ˆ๋ฉด ํด๋ž˜์Šค ์†์„ฑ์ด๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋”ฑํžˆ ๋‹ฌ๋ผ์ง€๋Š” ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค.) state๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋‹ค๊ณ  ์ € ๋ฉ”์„œ๋“œ๊ฐ€ ๋‹ฌ๋ผ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ this.props.fetchData ๋Š” prevProps.fetchData ์™€ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ์ ˆ๋Œ€ ๋‹ค์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ํŽ˜์นญํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์•„๊นŒ ์กฐ๊ฑด๋ฌธ์„ ์ œ๊ฑฐํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

componentDidUpdate(prevProps) {
  this.props.fetchData();
}

์–ด ์ž ๊น๋งŒ์š”, ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋งค๋ฒˆ ๋‹ค์‹œ ๋žœ๋”๋ง ํ•  ๋•Œ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌํ…๋ฐ์š”. (์œ„์˜ ๋‚ด์šฉ์„ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ์— ๋„ฃ๊ณ  ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๊ฝค ์žฌ๋ฐŒ์„ ๊ฒ๋‹ˆ๋‹ค.) ํ˜น์‹œ ํŠน์ •ํ•œ query ๋ฅผ ๋ฐ”์ธ๋”ฉํ•ด๋‘๋ฉด ์–ด๋–จ๊นŒ์š”?

render() {
  return <Child fetchData={this.fetchData.bind(this, this.state.query)} />;
}

ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด query ๊ฐ€ ๋ฐ”๋€Œ์ง€ ์•Š์•˜๋Š”๋ฐ๋„ this.props.fetchData !== prevProps.fetchData ๋Š” ์–ธ์ œ๋‚˜ true ๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค! ๊ฒฐ๊ตญ ๋งค๋ฒˆ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ํŽ˜์นญํ•˜๊ฒ ์ฃ .

์ง„์งœ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋กœ ์ด ์ˆ˜์ˆ˜๊ป˜๋ผ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ด ๊ฝ‰ ๊นจ๋ฌผ๊ณ  query ์ž์ฒด๋ฅผ Child ์ปดํฌ๋„ŒํŠธ์— ๋„˜๊ธฐ๋Š” ๊ฒƒ ๋ฟ์ž…๋‹ˆ๋‹ค. Child ์ปดํฌ๋„ŒํŠธ๊ฐ€ query ๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  query ๊ฐ€ ๋ฐ”๋€” ๋•Œ ๋‹ค์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋กœ์ง์€ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class Parent extends Component {
  state = {
    query: 'react'
  };
  fetchData = () => {
    const url = 'https://hn.algolia.com/api/v1/search?query=' + this.state.query;
    // ... ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•œ๋‹ค ...
  };
  render() {
    return <Child fetchData={this.fetchData} query={this.state.query} />;  }
}

class Child extends Component {
  state = {
    data: null
  };
  componentDidMount() {
    this.props.fetchData();
  }
  componentDidUpdate(prevProps) {
    if (this.props.query !== prevProps.query) {      this.props.fetchData();    }  }
  render() {
    // ...
  }
}

์ˆ˜ ๋…„๋™์•ˆ ๋ฆฌ์•กํŠธ์˜ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค๋ค„ ์˜ค๋ฉด์„œ, ๋ถˆํ•„์š”ํ•œ prop์„ ๋‚ด๋ ค๋ณด๋‚ด๋ฉด์„œ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์˜ ์บก์Аํ™”๋ฅผ ๊นจํŠธ๋ฆฌ๋Š” ์ผ์— ์ต์ˆ™ํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค ์ง€๋‚œ ์ฃผ๊ฐ€ ๋˜์–ด์„œ์•ผ ์™œ ๊ทธ๋ž˜์•ผ ํ–ˆ๋Š”์ง€ ๊นจ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค.

ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์—์„œ, ํ•จ์ˆ˜ prop ์ž์ฒด๋Š” ์‹ค์ œ๋กœ ๋ฐ์ดํ„ฐ ํ๋ฆ„์—์„œ ์ฐจ์ง€ํ•˜๋Š” ๋ถ€๋ถ„์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ฉ”์†Œ๋“œ๋Š” ๊ฐ€๋ณ€์„ฑ์ด ์žˆ๋Š” this ๋ณ€์ˆ˜์— ๋ฌถ์—ฌ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜์˜ ์ผ๊ด€์„ฑ์„ ๋‹ด๋ณดํ•  ์ˆ˜ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์šฐ๋ฆฌ๊ฐ€ ํ•จ์ˆ˜๋งŒ ํ•„์š”ํ•  ๋•Œ๋„ โ€œ์ฐจ์ดโ€ ๋ฅผ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•ด ์˜จ๊ฐ– ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ๋ถ€ํ„ฐ ๋‚ด๋ ค์˜จ this.props.fetchData ๊ฐ€ ์–ด๋–ค ์ƒํƒœ์— ๊ธฐ๋Œ€๊ณ  ์žˆ๋Š”์ง€, ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ๊ธฐ๋งŒ ํ•œ ๊ฒƒ์ธ์ง€ ์•Œ ์ˆ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

useCallback ์„ ์‚ฌ์šฉํ•˜๋ฉด, ํ•จ์ˆ˜๋Š” ๋ช…๋ฐฑํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ ํ๋ฆ„์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ํ•จ์ˆ˜์˜ ์ž…๋ ฅ๊ฐ’์ด ๋ฐ”๋€Œ๋ฉด ํ•จ์ˆ˜ ์ž์ฒด๊ฐ€ ๋ฐ”๋€Œ๊ณ , ๋งŒ์•ฝ ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ๊ฐ™์€ ํ•จ์ˆ˜๋กœ ๋‚จ์•„์žˆ๋‹ค๊ณ  ๋ง ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ๊ณต๋˜๋Š” useCallback ๋•๋ถ„์— props.fetchData ๊ฐ™์€ props ๋ณ€ํ™”๋Š” ์ž๋™์ ์œผ๋กœ ํ•˜์œ„ ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

๋น„์Šทํ•˜๊ฒŒ, useMemo ๋˜ํ•œ ๋ณต์žกํ•œ ๊ฐ์ฒด์— ๋Œ€ํ•ด ๊ฐ™์€ ๋ฐฉ์‹์˜ ํ•ด๊ฒฐ์ฑ…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

function ColorPicker() {
  // color๊ฐ€ ์ง„์งœ๋กœ ๋ฐ”๋€Œ์ง€ ์•Š๋Š” ํ•œ
  // Child์˜ ์–•์€ props ๋น„๊ต๋ฅผ ๊นจํŠธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค
  const [color, setColor] = useState('pink');
  const style = useMemo(() => ({ color }), [color]);
  return <Child style={style} />;
}

๊ทธ๋ ‡๋‹ค๊ณ  useCallback ์„ ์–ด๋””๋“ ์ง€ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๊ฝค ํˆฌ๋ฐ•ํ•œ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ๊ฐ•์กฐํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. useCallback ์€ ๊ฝค ์ข‹์€ ๋ŒํŒŒ๊ตฌ์ด๋ฉฐ ํ•จ์ˆ˜๊ฐ€ ์ „๋‹ฌ๋˜์–ด ์ž์† ์ปดํฌ๋„ŒํŠธ์˜ ์ดํŽ™ํŠธ ์•ˆ์—์„œ ํ˜ธ์ถœ๋˜๋Š” ๊ฒฝ์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์•„๋‹ˆ๋ฉด ์ž์† ์ปดํฌ๋„ŒํŠธ์˜ ๋ฉ”๋ชจ์ด์ œ์ด์…˜์ด ๊นจ์ง€์ง€ ์•Š๋„๋ก ๋ฐฉ์ง€ํ•  ๋•Œ๋„ ์“ฐ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ›… ์ž์ฒด๊ฐ€ ์ฝœ๋ฐฑ์„ ๋‚ด๋ ค๋ณด๋‚ด๋Š” ๊ฒƒ์„ ํ”ผํ•˜๋Š” ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์„ ํ•จ๊ป˜ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์œ„์˜ ์˜ˆ์ œ๋ผ๋ฉด ์ €๋Š” fetchData ๋ฅผ ์ดํŽ™ํŠธ ์•ˆ์— ๋‘๊ฑฐ๋‚˜(์ปค์Šคํ…€ ํ›…์œผ๋กœ ์ถ”์ƒํ™”๋  ์ˆ˜๋„ ์žˆ๊ณ ์š”) ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ๋กœ ๋งŒ๋“ค์–ด import ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ €๋Š” ์ดํŽ™ํŠธ๋ฅผ ์ตœ๋Œ€ํ•œ ๋‹จ์ˆœํ•˜๊ฒŒ ๋งŒ๋“ค๊ณ  ์‹ถ๊ณ  ๊ทธ ์•ˆ์— ์ฝœ๋ฐฑ์„ ๋‘๋Š” ๊ฒƒ์€ ๋‹จ์ˆœํ•˜๊ฒŒ ๋งŒ๋“œ๋Š”๋ฐ ๋ณ„๋กœ ๋„์›€์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. (โ€œ๋งŒ์•ฝ์— ์–ด๋–ค props.onComplete ์ฝœ๋ฐฑ์ด ์š”์ฒญ์ด ๋ณด๋‚ด์ง€๊ณ  ์žˆ์„ ๋•Œ ์‹คํ–‰๋œ๋‹ค๋ฉด?โ€œ) ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ ๋™์ž‘์„ ํ‰๋‚ด๋‚ผ์ˆœ ์žˆ์ง€๋งŒ ๊ฒฝ์Ÿ ์ƒํƒœ(race condition)๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

๊ฒฝ์Ÿ ์ƒํƒœ์— ๋Œ€ํ•ด

ํด๋ž˜์Šค๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ „ํ†ต์ ์ธ ์˜ˆ์ œ๋Š” ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ์„๊ฒ๋‹ˆ๋‹ค.

class Article extends Component {
  state = {
    article: null
  };
  componentDidMount() {
    this.fetchData(this.props.id);
  }
  async fetchData(id) {
    const article = await API.fetchArticle(id);
    this.setState({ article });
  }
  // ...
}

์•„๋งˆ ์•„์‹œ๊ฒ ์ง€๋งŒ, ์ด ์ฝ”๋“œ๋Š” ๋ฒ„๊ทธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜๋Š” ์ƒํ™ฉ์„ ๋‹ค๋ฃจ์ง€ ์•Š์ง€์š”. ๊ทธ๋ž˜์„œ ๋‘ ๋ฒˆ์งธ ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ ์˜ˆ์ œ๋ฅผ ์˜จ๋ผ์ธ์—์„œ ์ฐพ์•„๋ณด๋ฉด ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ์„ ๊ฒ๋‹ˆ๋‹ค.

class Article extends Component {
  state = {
    article: null
  };
  componentDidMount() {
    this.fetchData(this.props.id);
  }
  componentDidUpdate(prevProps) {    if (prevProps.id !== this.props.id) {      this.fetchData(this.props.id);    }  }  async fetchData(id) {
    const article = await API.fetchArticle(id);
    this.setState({ article });
  }
  // ...
}

์ด๊ฒŒ ํ›จ์”ฌ ๋‚ซ์ฃ ! ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ฒ„๊ทธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ด์œ ๋Š” ์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋งŒ์•ฝ ์ œ๊ฐ€ {id: 10} ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ณ  {id: 20} ์œผ๋กœ ๋ฐ”๊พธ์—ˆ๋‹ค๋ฉด, {id: 20} ์˜ ์š”์ฒญ์ด ๋จผ์ € ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋จผ์ € ์‹œ์ž‘๋œ ์š”์ฒญ์ด ๋” ๋Šฆ๊ฒŒ ๋๋‚˜์„œ ์ž˜๋ชป๋œ ์ƒํƒœ๋ฅผ ๋ฎ์–ด์”Œ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ๊ฒฝ์Ÿ ์ƒํƒœ๋ผ๊ณ  ํ•˜๋ฉฐ, (๋ณดํ†ต ๋น„๋™๊ธฐ ํ˜ธ์ถœ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋Œ์•„์˜ฌ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค๊ณ  ์—ฌ๊ธฐ๋ฉฐ) ์œ„์—์„œ ์•„๋ž˜๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ํ๋ฅด๋ฉด์„œ async / await ์ด ์„ž์—ฌ์žˆ๋Š” ์ฝ”๋“œ์— ํ”ํžˆ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ˜๋Ÿฌ๊ฐ„๋‹ค๋Š” ๋ง์€ props๋‚˜ state๊ฐ€ async ํ•จ์ˆ˜ ์•ˆ์—์„œ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋‹ค๋Š” ์ด์•ผ๊ธฐ์ž…๋‹ˆ๋‹ค.

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

์—ฌ๋Ÿฌ๋ถ„์ด ์‚ฌ์šฉํ•˜๋Š” ๋น„๋™๊ธฐ ์ ‘๊ทผ ๋ฐฉ์‹์ด ์ทจ์†Œ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•œ๋‹ค๋ฉด ์•„์ฃผ ์ข‹์Šต๋‹ˆ๋‹ค! ๊ทธ๋Ÿฌ๋ฉด ํด๋ฆฐ์—… ํ•จ์ˆ˜์—์„œ ๋ฐ”๋กœ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ์ทจ์†Œ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜๋Š” ์ œ์ผ ์‰ฝ๊ฒŒ ๋ถˆ๋ฆฐ(boolean) ๊ฐ’์œผ๋กœ ํ๋ฆ„์ด ๋ฉˆ์ถฐ์•ผ ํ•˜๋Š” ํƒ€์ด๋ฐ์„ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function Article({ id }) {
  const [article, setArticle] = useState(null);

  useEffect(() => {
    let didCancel = false;    async function fetchData() {
      const article = await API.fetchArticle(id);
      if (!didCancel) {
        setArticle(article);      }
    }

    fetchData();

    return () => {
      didCancel = true;    };  }, [id]);
  // ...
}

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

์ง„์ž… ์žฅ๋ฒฝ์„ ๋” ๋†’์ด๊ธฐ

ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ ๋ผ์ดํ”„์‚ฌ์ดํด ๊ฐœ๋…์œผ๋กœ ์ƒ๊ฐํ•˜๋ฉด, ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋Š” ๋žœ๋”๋ง ๊ฒฐ๊ณผ๋ฌผ๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. UI๋ฅผ ๋žœ๋”๋งํ•˜๋Š” ๊ฒƒ์€ props์™€ state๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ง€๋ฉฐ ์ด๋“ค์˜ ์ผ๊ด€์„ฑ์— ๋”ฐ๋ผ ๋ณด์žฅ๋ฐ›์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ์ด๊ฒŒ ํ”ํžˆ ๋ฒ„๊ทธ๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์›์ธ์ž…๋‹ˆ๋‹ค.

useEffect ์˜ ๊ฐœ๋…์œผ๋กœ ์ƒ๊ฐํ•˜๋ฉด, ๋ชจ๋“  ๊ฒƒ๋“ค์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋Š” ๋ฆฌ์•กํŠธ์˜ ๋ฐ์ดํ„ฐ ํ๋ฆ„์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  useEffect ํ˜ธ์ถœ์—์„œ, ์ œ๋Œ€๋กœ๋งŒ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค๋ฉด ์—ฃ์ง€ ์ผ€์ด์Šค๋ฅผ ํ›จ์”ฌ ์‰ฝ๊ฒŒ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

useEffect ๊ฐ€ ๋Œ€๋ถ€๋ถ„์˜ ์‹œ๊ฐ„๊ณผ ํ•จ๊ป˜ ํ•ด์•ผํ•˜๋Š” ๋„๊ตฌ ๋ผ๋ฉด ๊ฝค๋‚˜ ๊ฑฑ์ •์Šค๋Ÿฌ์šด ์ผ์ด ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ useEffect ๋Š” ๋‚ฎ์€ ์ˆ˜์ค€์˜ ๋ ˆ์ด์–ด(๋กœ์šฐ ๋ ˆ๋ฒจ)์— ์œ„์น˜ํ•œ ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ์•„์ง ๋ชจ๋‘๊ฐ€ ํ›…์„ ๋‹ค๋ฃจ๊ธฐ ์‹œ์ž‘ํ•œ์ง€ ์–ผ๋งˆ ๋˜์ง€ ์•Š์€ ์‹œ๊ธฐ๋ผ์„œ ํ•ญ์ƒ ๋กœ์šฐ ๋ ˆ๋ฒจ API๋ฅผ ๋‹ค๋ฃจ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ํŠœํ† ๋ฆฌ์–ผ์—์„œ์š”. ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ ์ปค๋ฎค๋‹ˆํ‹ฐ๋Š” ๋” ๋†’์€ ์ˆ˜์ค€์œผ๋กœ ์ถ”์ƒํ™”๋œ ํ›…์œผ๋กœ ์˜ฎ๊ฒจ๊ฐˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ €๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์•ฑ์ด ์ž์‹ ๋งŒ์˜ useFetch ํ›…์„ ๋งŒ๋“ค์–ด ์ธ์ฆ ๋กœ์ง์„ ์บก์Аํ™”ํ•˜๊ฑฐ๋‚˜, useTheme ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ๋งˆ ์ปจํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ์Šต์„ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋„๊ตฌ ๋ชจ์Œ์„ ๊ฐ€์ง€๊ฒŒ ๋˜๋ฉด, useEffect ๋ฅผ ์ง์ ‘ ์“ธ ์ผ์€ ๊ทธ๋ฆฌ ๋งŽ์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ์œ ์—ฐํ•จ์€ ๋ชจ๋“  ํ›…์„ ๋งŒ๋“œ๋Š”๋ฐ ์ถฉ๋ถ„ํžˆ ์œ ์šฉํ•˜๊ฒŒ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„์ง๊นŒ์ง€๋Š” useEffect ๊ฐ€ ๊ฐ€์žฅ ํ”ํžˆ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ๋Š” ๋ฐ์ดํ„ฐ ํŽ˜์นญ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฐ์ดํ„ฐ ํŽ˜์นญ์€ ์—„๋ฐ€ํžˆ ๋งํ•ด ๋™๊ธฐํ™”์˜ ๋ฌธ์ œ๋Š” ์•„๋‹™๋‹ˆ๋‹ค. ํŠนํžˆ๋‚˜ ๋ช…๋ฐฑํ•œ ๊ฒƒ์ด ์ฃผ๋กœ ์ด๋Ÿด ๋•Œ๋Š” deps๊ฐ€ [] ๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์ด์ฃ . ๋„๋Œ€์ฒด ์šฐ๋ฆฌ๋Š” ๋ฌด์—‡์„ ๋™๊ธฐํ™”ํ•˜๊ณ  ์žˆ์„๊นŒ์š”?

์žฅ๊ธฐ์ ์ธ ๊ด€์ ์—์„œ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋กœ์ง์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Suspense๊ฐ€ ๋„์ž…๋˜๋ฉด ์„œ๋“œ ํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฆฌ์•กํŠธ์—๊ฒŒ ์–ด๋–ค ๋น„๋™๊ธฐ์ ์ธ ํ–‰์œ„(์ฝ”๋“œ, ๋ฐ์ดํ„ฐ, ์ด๋ฏธ์ง€ ๋“ฑ ๋ชจ๋“  ๊ฒƒ)๊ฐ€ ์ค€๋น„๋  ๋•Œ๊นŒ์ง€ ๋žœ๋”๋ง์„ ์ž ์‹œ ๋ฏธ๋ฃฐ ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Suspense๊ฐ€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒฝ์šฐ๋ฅผ ๋” ๋งŽ์ด ์ปค๋ฒ„ํ•˜๊ฒŒ ๋˜๋ฉด, ์˜ˆ์ธก์ปจ๋Œ€ useEffect ๋Š” ๋”์šฑ ๋กœ์šฐ ๋ ˆ๋ฒจ๋กœ ๋‚ด๋ ค๊ฐ€ ํŒŒ์›Œ์œ ์ €๋“ค์ด ์ง„์ •์œผ๋กœ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋ฅผ ํ†ตํ•ด props์™€ state๋ฅผ ๋™๊ธฐํ™”ํ•˜๊ณ ์ž ํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋„๊ตฌ๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ํŽ˜์นญ๊ณผ ๋‹ค๋ฅด๊ฒŒ ์›๋ž˜ ๋””์ž์ธ ๋œ ๋Œ€๋กœ ์ด๋Ÿฐ ๋™๊ธฐํ™” ์ผ€์ด์Šค๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ๋•Œ๊นŒ์ง€๋Š”, ์—ฌ๊ธฐ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ปค์Šคํ…€ ํ›…์ด ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ ํŽ˜์นญ ๋กœ์ง์„ ๋‹ค๋ฃจ๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

๋งˆ์น˜๋ฉฐ

์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ์ œ๊ฐ€ ์•Œ๊ณ ์žˆ๋Š” ์ดํŽ™ํŠธ์— ๋Œ€ํ•œ ์ •๋ณด ๊ฑฐ์˜ ์ „๋ถ€๋ฅผ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค, ๋‹ค์‹œ ์‹œ์ž‘ ๋ถ€๋ถ„์œผ๋กœ ๋Œ์•„๊ฐ€ ์š”์•ฝ๋ณธ์„ ์ฝ์–ด ๋ณด์„ธ์š”. ์ดํ•ด๊ฐ€ ๋˜์‹œ๋‚˜์š”? ์•„๋‹ˆ๋ฉด ์ œ๊ฐ€ ๋ญ˜ ๋น ๋œจ๋ ธ์„๊นŒ์š”? (์•„์ง ์† ๋์˜ ์ž‰ํฌ๊ฐ€ ๋งˆ๋ฅด์ง€ ์•Š์•˜์–ด์š”!)

ํŠธ์œ„ํ„ฐ์—์„œ ์˜๊ฒฌ์„ ์ฃผ์‹œ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค! ์ฝ์–ด์ฃผ์…”์„œ ๊ณ ๋ง™์Šต๋‹ˆ๋‹ค.