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

Teasanยท2022๋…„ 6์›” 14์ผ
0

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
7/36
post-thumbnail

๋ชฉ์ฐจ

  • ์ปค์Šคํ…€ ํ›…์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€
  • ์ปค์Šคํ…€ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ReEvaluation Hook ํ•จ์ˆ˜ ์ƒ์„ฑํ•˜๊ธฐ
  • ์‚ฌ์šฉ์ž ์ •์˜ ํ›… ์‚ฌ์šฉํ•˜๊ธฐ
  • ์‚ฌ์šฉ์ž ์ •์˜ ํ›… ๊ตฌ์„ฑํ•˜๊ธฐ

โœง ์ปค์Šคํ…€ ํ›…์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€

  • ์ปค์Šคํ…€ ํ›…์€ ๊ฒฐ๊ตญ ์ •๊ทœ ํ•จ์ˆ˜๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‚ด์žฅ ํ›…์ด๋ผ๋˜๊ฐ€ useState ๊ฐ™์€ ๊ฒƒ๋“ค ๋ง์ด๋‹ค. ํ•˜์ง€๋งŒ ๋‚ด๋ถ€์— ์ƒํƒœ(state)๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋กœ์ง์„ ํฌํ•จํ•œ ํ•จ์ˆ˜์ด๋‹ค. ์ปค์Šคํ…€ ํ›…์„ ๋งŒ๋“ค์–ด์„œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜์— ์ƒํƒœ(state)๋ฅผ ์„ค์ •ํ•˜๋Š” ๋กœ์ง์„ '์•„์›ƒ์†Œ์‹ฑ' ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ •๊ทœ ํ•จ์ˆ˜์™€๋Š” ๋‹ค๋ฅด๊ฒŒ, ์ปค์Šคํ…€ ํ›…์€ ๋‹ค๋ฅธ ์ปค์Šคํ…€ ํ›…์„ ํฌํ•จํ•œ ๋‹ค๋ฅธ ๋ฆฌ์•กํŠธ ํ›…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ useState๋‚˜ useReducer์™€ ๊ฐ™์€ ์ƒํƒœ(state) ๊ด€๋ฆฌ ํ›…์„ ์ด์šฉํ•ด์„œ ๋ฆฌ์•กํŠธ์˜ ์ƒํƒœ(state)๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ, useEffect์—๋„ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ์ปค์Šคํ…€ ํ›…์„ ํ†ตํ•ด ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋กœ์ง์„ ์ปค์Šคํ…€ ํ›…์œผ๋กœ ์•„์›ƒ์†Œ์‹ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ์ปดํฌ๋„ŒํŠธ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

์ปค์Šคํ…€ ํ›…์€ ๋กœ์ง ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค

  • ์ปค์Šคํ…€ ํ›…์€ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค. ์ •๊ทœ ํ•จ์ˆ˜์™€ ํŠน์ˆ˜ ํ•จ์ˆ˜์˜ ๊ด€๊ณ„์ฒ˜๋Ÿผ ์ปค์Šคํ…€ ํ›… ํ•จ์ˆ˜์—์„œ๋Š” ๋ฆฌ์•กํŠธ ํ›…๊ณผ ๋‹ค๋ฅธ ํ›…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

โœง ์ปค์Šคํ…€ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ReEvaluation Hook ํ•จ์ˆ˜ ์ƒ์„ฑํ•˜๊ธฐ

  • ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์—ด์–ด๋ณด๋ฉด, ์ด ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์€ 2๊ฐœ์˜ ์นด์šดํ„ฐ๊ฐ€ ์žˆ๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ์ผ์ • ์‹œ๊ฐ„ ๋’ค์— ํ•˜๋‚˜๋Š” ์ฆ๊ฐ€ํ•˜๊ณ  ๋˜ ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๊ฐ์†Œํ•˜๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

ForwardCounter.js

const ForwardCounter = () => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter((prevCounter) => prevCounter + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return <Card>{counter}</Card>;
};

BackwardCounter.js

const BackwardCounter = () => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter((prevCounter) => prevCounter - 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return <Card>{counter}</Card>;
};
  • ์œ„์˜ ์ฝ”๋“œ๋“ค์€ ๊ฐ๊ฐ์˜ ์ฆ๊ฐ€์™€ ๊ฐ์†Œ ์นด์šดํ„ฐ๋ฅผ ๋งก๊ณ  ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์ด๋‹ค. ์ด ์ปดํฌ๋„ŒํŠธ๋“ค์€ ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ์˜ ์—ญํ• ์„ ํ•ด์ฃผ๊ณ  ์žˆ๋‹ค. ForwardCounter ์ปดํฌ๋„ŒํŠธ๋Š” useState์™€ useEffect๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒํƒœ(state)๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์„ ๋งŒ๋“ค์–ด์„œ(setInterval) ์ •๋ฐฉํ–ฅ์œผ๋กœ ์นด์šดํŒ…์„ ์‹œ์ž‘ํ•˜๋ฉฐ ๋งค ์ดˆ, ์ฆ‰ ๋งค 1000 ๋ฐ€๋ฆฌ์ดˆ ๋งˆ๋‹ค ์ƒˆ๋กœ์šด counter ์ƒํƒœ(state)๋ฅผ ์„ค์ •ํ•œ๋‹ค. BackwardCounter ์ปดํฌ๋„ŒํŠธ ์—ญ์‹œ ForwardCounter ์ปดํฌ๋„ŒํŠธ์™€ ๋™์ผํ•œ ์—ญํ• ์„ ํ•˜์ง€๋งŒ ๋‹ค๋งŒ ์—ญ๋ฐฉํ–ฅ์œผ๋กœ ์นด์šดํŒ…์„ ํ•˜๊ณ  ์žˆ๋‹ค. ์ด๊ฒƒ ์™ธ์—๋Š” ๋‘ ์ปดํฌ๋„ŒํŠธ ๋ชจ๋‘ ๋™์ผํ•œ ๋กœ์ง์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ, ์ด ๋‘ ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ๋Š” ๋งค์šฐ ์œ ์‚ฌํ•˜๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋ฌผ๋ก  ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๊ณ , ์ด ์ปดํฌ๋„ŒํŠธ์— props ๋ฅผ ๋„˜๊ฒจ๋ฐ›๋Š” ํ˜•์‹์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ๋„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์‹ค์ œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์ƒํ˜ธ ๊ฐ„์— ์—ฐ๊ด€๋œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ •๋ฐฉํ–ฅ/์—ญ๋ฐฉํ–ฅ counter ์—๋„ ์–‘ ๋กœ์ง๊ฐ„์— ์ค‘๋ณต๋˜๋Š” ์ฝ”๋“œ๊ฐ€ ์กด์žฌํ•  ๊ฒƒ์ด๋‹ค. (์–ด์จŒ๋“  ๋ง์…ˆ๊ณผ ๋บ„์…ˆ์ด๋ผ๋Š” ์ฐจ์ด๋งŒ ์ œ์™ธํ•˜๋ฉด ์ด ๋‘˜์€ ์ •ํ™•ํžˆ ๊ฐ™์€ ์ฝ”๋“œ๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.)

์ค‘๋ณต๋œ ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง ํ•˜๊ธฐ

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

์ปค์Šคํ…€ ํ›… ๋งŒ๋“ค๊ธฐ

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

์ปค์Šคํ…€ ํ›…์„ ๋งŒ๋“œ๋Š” ๊ทœ์น™

  • ์ปค์Šคํ…€ ํ›…์—๋Š” ๋ช‡ ๊ฐ€์ง€ ๊ทœ์น™์ด ์žˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ๋กœ ์•ž์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋…๋ฆฝ๋œ ํŒŒ์ผ์— ์ €์žฅํ•  ์ˆ˜ ์—†๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‘ ๋ฒˆ์งธ ๊ทœ์น™์œผ๋กœ๋Š” ์ปค์Šคํ…€ ํ›…์˜ ๋„ค์ด๋ฐ์˜ ์‹œ์ž‘์„ use๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์— ์žˆ๋‹ค.

use-counter.js

const useCounter = () => {};
export default useCounter;
  • ๋ณ„๋„๋กœ ๋งŒ๋“  hooks ํด๋” ์•ˆ์— use-counter.js ๋ผ๋Š” ์ปค์Šคํ…€ ํ›… ํŒŒ์ผ์„ ๋งŒ๋“ ๋‹ค. ์•ž์„œ ์„ค๋ช…ํ–ˆ๋˜ ๋‘ ๋ฒˆ์งธ ๊ทœ์น™์„ ๋”ฐ๋ผ์„œ use๋กœ ์‹œ์ž‘๋˜๋Š” ์ด๋ฆ„์˜ ์ปค์Šคํ…€ ํ›…์ด๋‹ค. ์ด๋ ‡๊ฒŒ ํŒŒ์ผ ์ด๋ฆ„์„ ์ง€์€ ๊ฒƒ์—๋Š” ์ด์œ ๊ฐ€ ์žˆ๋‹ค. ํŒŒ์ผ ์•ˆ์— ํ•จ์ˆ˜ ์ด๋ฆ„์— ๋Œ€ํ•ด ๋”ฐ๋ผ์•ผ ํ•˜๋Š” ๊ทœ์น™์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์šฐ๋ฆฌ๋Š” use-counter.js ๋ผ๋Š” ํŒŒ์ผ ์•ˆ์—์„œ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ด๊ณ , ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ ํ•จ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ์ด๋ฆ„์„ use๋กœ ๋ช…๋ช…ํ•ด์•ผ ํ•œ๋‹ค. ์ด๋Š” ํ•„์ˆ˜์ ์œผ๋กœ ์ง€์ผœ์•ผํ•˜๋Š” ์—„๊ฒฉํ•œ ๊ทœ์น™์ด๋‹ค.

๋ฆฌ์•กํŠธ๊ฐ€ ์ปค์Šคํ…€ ํ›…์—๊ฒŒ ์š”๊ตฌํ•˜๋Š” ๊ทœ์น™ use ๋„ค์ด๋ฐ

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

์ค‘๋ณต๋œ ์นด์šดํ„ฐ ์ฝ”๋“œ๋ฅผ ์ปค์Šคํ…€ ํ›…์œผ๋กœ ์ด์ „ํ•˜๊ธฐ

const useCounter = () => {};
export default useCounter;
  • useCounter ๋ผ๋Š” ์ •๊ทœ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ํ•จ์ˆ˜์˜ ๊ถ๊ทน์ ์ธ ๋ชฉ์ ์€ ์™ธ๋ถ€์˜ ๋‹ค๋ฅธ ํŒŒ์ผ์—์„œ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋ฏ€๋กœ, ์ด ํ•จ์ˆ˜๋ฅผ export ํ•˜๋„๋ก ์ž‘์„ฑํ•œ๋‹ค.
import { useEffect, useState } from "react";

const useCounter = () => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter((prevCounter) => prevCounter + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);
};

export default useCounter;
  • ๊ทธ๋ฆฌ๊ณ  ForwardCounter ์ปดํฌ๋„ŒํŠธ์— ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ๋ณต์‚ฌ(JSX ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋‚จ๊ฒจ๋‘”๋‹ค.)ํ•ด์„œ ํ•ด๋‹น ์ปค์Šคํ…€ ํ›… ํ•จ์ˆ˜ ์•ˆ์— ์ด์ „์‹œ์ผœ ์ค€๋‹ค.

โœง ์‚ฌ์šฉ์ž ์ •์˜ ํ›… ์‚ฌ์šฉํ•˜๊ธฐ

  • ์‚ฌ์šฉ์ž ์ •์˜(Custom) ํ›…์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋‚ด์žฅ ํ›…์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋– ์˜ฌ๋ฆฌ๋ฉด ๋œ๋‹ค. ๊ฒฐ๊ตญ ์ปค์Šคํ…€ ํ›…๋„ ํ•จ์ˆ˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
import useCounter from "../hooks/use-counter";
  • ๋จผ์ € ForwardCounter ์ปดํฌ๋„ŒํŠธ์— ํ•ด๋‹น ๋กœ์ง์„ ๋ณต์‚ฌํ•ด๋‘์—ˆ๋˜ ์ปค์Šคํ…€ ํ›…(useCounter)๋ฅผ import ํ•ด์˜จ๋‹ค.

ForwardCounter.js

import useCounter from "../hooks/use-counter";

const ForwardCounter = () => {
  useCounter();
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter((prevCounter) => prevCounter + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return <Card>{counter}</Card>;
};
  • ๊ทธ๋ฆฌ๊ณ  ์ปค์Šคํ…€ ํ›…์ธ useCounter๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. useCounter๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด useCounter์˜ ๋‚ด๋ถ€ ์ฝ”๋“œ๋“ค์ด ์‹คํ–‰๋  ๊ฒƒ์ด๋‹ค.

useCounter.js

const useCounter = () => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter((prevCounter) => prevCounter + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);
};
  • ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ์—์„œ ์ปค์Šคํ…€ ํ›…์„ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด, ํ˜ธ์ถœํ•œ ์ปค์Šคํ…€ ํ›… ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ์žˆ๋Š” ์ƒํƒœ(state)๋‚˜ effect๊ฐ€ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์— ๋ฌถ์ด๊ฒŒ ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ForwardCounter์—์„œ useCounter๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด useCounter์—์„œ ๋งŒ๋“ค์–ด์ง„ ์ƒํƒœ(state)๊ฐ€ ForwardCounter ์ปดํฌ๋„ŒํŠธ์— ๋ฌถ์ด๋Š” ๊ฒƒ์ด๋‹ค. ๋˜ ๋‹ค์ˆ˜์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ํŠน์ • ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์ด ๋‹ค์ˆ˜์˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ปค์Šคํ…€ ํ›…์˜ ์ƒํƒœ(state)๋ฅผ ๋ฐ›๊ฒŒ ๋œ๋‹ค. ๋ฌผ๋ก  ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•ด์„œ ์ปดํฌ๋„ŒํŠธ ์ „๋ฐ˜์— ๊ฑธ์ณ ๋™์ผํ•œ ์ƒํƒœ(state)์™€ effect๋ฅผ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์—์„œ ์ปค์Šคํ…€ ํ›…์ด ์žฌ์‹คํ–‰๋˜๊ณ  ์ด ์ปค์Šคํ…€ ํ›…์„ ํ˜ธ์ถœํ•˜๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ์ž์˜ ์ƒํƒœ(state)๋ฅผ ๋ฐ›๊ฒŒ ๋  ๋ฟ์ด๋‹ค.

์ปค์Šคํ…€ ํ›…์„ ํ˜ธ์ถœํ•˜๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋Š” ์ปค์Šคํ…€ ํ›…์˜ ๋กœ์ง๋งŒ์„ ๊ณต์œ ํ•œ๋‹ค

  • ์žŠ์ง€ ๋ง์•„์•ผ๋  ๊ฒƒ์€ ์•ž์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์ปค์Šคํ…€ ํ›…์˜ ๋กœ์ง๋งŒ ๊ณต์œ ํ•  ๋ฟ ์ƒํƒœ(state)๋ฅผ ๋™์ผํ•˜๊ฒŒ ๊ณต์œ ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์ด๋‹ค. ๋”ฐ๋ผ์„œ ForwardCounter ์ปดํฌ๋„ŒํŠธ์—์„œ useCounter๋ฅผ ํ˜ธ์ถœํ–ˆ์œผ๋ฏ€๋กœ useCounter์˜ ์ƒํƒœ์ธ counter๋Š” ForwardCounter์— ์˜ํ•ด์„œ ์„ค์ •๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  useCounter์˜ useEffect ์—ญ์‹œ ForwardCounter ์— ์˜ํ•ด์„œ ์„ค์ •๋˜๊ณ  ๋ฐœ์ƒ๋œ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ForwardCounter์—์„œ useCounter์˜ ์ƒํƒœ counter์— ์ ‘๊ทผํ•ด์„œ ์„ค์ •ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ•˜๋Š” ๊ฑธ๊นŒ?

์ปดํฌ๋„ŒํŠธ์—์„œ ์ปค์Šคํ…€ ํ›…์˜ ์ƒํƒœ(state) ์ ‘๊ทผํ•˜๊ธฐ

  • ์ปดํฌ๋„ŒํŠธ์—์„œ ํ˜ธ์ถœํ•˜๋Š” ์ปค์Šคํ…€ ํ›…์˜ ์ƒํƒœ(state)์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์€ ๋‚ด์žฅ ํ›…์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ๋™์ผํ•œ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. useState ๊ฐ™์€ ๋‚ด์žฅ ํ›…๋„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•˜๊ณ  ์žˆ๋‹ค. ์ƒํƒœ๋ฅผ ๋งŒ๋“ค๊ณ  ๊ด€๋ฆฌ๋„ ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์–ด๋– ํ•œ ์ค‘์š”ํ•œ ์—ญํ• ๋„ ๋งก์•„์„œ ํ•œ๋‹ค.
const [counter, setCounter] = useState(0);
  • ์œ„์˜ useState์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๋ฐฐ์—ด ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์„ ํ†ตํ•ด ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ์ปค์Šคํ…€ ํ›… ์—ญ์‹œ ํ•จ์ˆ˜์ด๋ฏ€๋กœ, ์ปค์Šคํ…€ ๋‚ด๋ถ€์— ์žˆ๋Š” ์–ด๋–ค ๊ฒƒ์ด๋“  ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค. useCounter ๊ฐ™์€ ์ปค์Šคํ…€ ํ›…์„ ํ˜ธ์ถœํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ counter ๋ผ๋Š” ์ƒํƒœ(state)์— ์ ‘๊ทผํ•ด ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ปค์Šคํ…€ ํ›…์ธ useCounter์—์„œ ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฐ˜ํ™˜์„ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.
const useCounter = () => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter((prevCounter) => prevCounter + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return counter;
};
  • return counter๋ฅผ ์ถ”๊ฐ€ํ•ด์คŒ์œผ๋กœ์„œ useCounter ์ปค์Šคํ…€ ํ›…์˜ ์ƒํƒœ(state)๋ฅผ ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค. ์ปค์Šคํ…€ ํ›…์—์„œ๋Š” ์™ธ๋ถ€ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•„์š”ํ•œ ๋ฌด์—‡์ด๋“ ๊ฐ„์— ๋ฐ˜ํ™˜์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ๋ฐฐ์—ด์ด๋‚˜ ๊ฐ์ฒด, ์ˆซ์ž๋„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
const [counter, setCounter] = useState(0);
  • ์ด ์ƒํƒœ(state)๋Š” ์ปค์Šคํ…€ ํ›…์ด ์„ค์ •ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ useCounter๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ๋Š” ForwardCounter ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” useCounter๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ForwardCounter.js

const counter = useCounter();
  • ForwardCounter ์ปดํฌ๋„ŒํŠธ์—์„œ ํ˜ธ์ถœํ•œ useCounter()๋ฅผ counter ๋ผ๋Š” ์ƒ์ˆ˜๋กœ ์ง€์ •ํ•˜๊ณ , ์ด๋ฅผ ํ• ๋‹นํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, useCounter๊ฐ€ counter๋กœ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ForwardCounter ์ปดํฌ๋„ŒํŠธ ์•ˆ์˜ ์ƒ์ˆ˜(counter)์— ๊ฐ’์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
const ForwardCounter = () => {
  const counter = useCounter();

  return <Card>{counter}</Card>;
};
  • ์ด์ „์— ์‚ฌ์šฉํ–ˆ๋˜ ๋กœ์ง๋“ค์„ ๋ชจ๋‘ ์ œ๊ฑฐํ•˜๋‹ˆ ForwardCounter ์ปดํฌ๋„ŒํŠธ์˜ ๋กœ์ง์ด ๋งค์šฐ ๊ฐ„๊ฒฐํ•ด์กŒ๋‹ค.

  • ์ €์žฅํ•˜๊ณ  ์ƒˆ๋กœ๊ณ ์นจ ํ•ด๋ณด๋ฉด, ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•˜๋˜ ์ด์ „๊ณผ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์ •๋ฆฌ

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

โœง ์‚ฌ์šฉ์ž ์ •์˜ ํ›… ๊ตฌ์„ฑํ•˜๊ธฐ

BackwardCounter.js

const BackwardCounter = () => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter((prevCounter) => prevCounter - 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return <Card>{counter}</Card>;
};
  • BackwardCounter ์ปดํฌ๋„ŒํŠธ์—๋„ ForwardCounter ์ปดํฌ๋„ŒํŠธ์™€ ๋™์ผํ•œ ๋กœ์ง์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๋‹ค๋งŒ ๋ง์…ˆ ๋Œ€์‹  ๋บ„์…ˆ์„ ์ด์šฉํ•  ๋ฟ์ด๋‹ค. ๋‹น์—ฐํžˆ ForwardCounter ์ฒ˜๋Ÿผ useCounter ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๋‹ค๋งŒ ์ด ๋‘ ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ์˜ ์ฐจ์ด์ (๋ง์…ˆ๊ณผ ๋บ„์…ˆ)์— ๋”ฐ๋ฅธ ์กฐ๊ฑด๋ถ€ ๋กœ์ง์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„๋“ค์ด๊ฒŒ ํ•ด์•ผ๋งŒ ํ•œ๋‹ค. ์ปค์Šคํ…€ ํ›…๋„ ํ•จ์ˆ˜์ด๊ธฐ์— ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์“ฐ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ์žฌ์‚ฌ์šฉ ๋ฐ ์žฌ์„ค์ •์„ ์œ„ํ•ด์„œ ์ธ์ž์™€ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜(Custom) ํ›…์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐ›๊ธฐ

  • ์•ž์„œ ์„ค๋ช…ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์ปค์Šคํ…€ ํ›…๋„ ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‚ด์žฅ ํ›…์ธ useState ์—ญ์‹œ ์ดˆ๊ธฐ ๊ฐ’์„ ์„ค์ •ํ•ด์ฃผ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. ๋‘ ๊ฐœ์˜ ์ธ์ž๋ฅผ ๋ฐ›๋Š” useEffect ์—ญ์‹œ 2๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. effect ํ•จ์ˆ˜๋ฅผ ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ ๋ฐ›๊ณ , ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ ๋ฐ›์•„๋“ค์ด๊ธฐ ๋–„๋ฌธ์ด๋‹ค. ์ด๋Š” ์ง€๊ธˆ๊นŒ์ง€ ์šฐ๋ฆฌ๊ฐ€ ํ•ด์™”๋˜ ๋ฐฉ์‹์ด๊ณ , ์ด ๋ฐฉ์‹์€ ์ปค์Šคํ…€ ํ›…์—์„œ๋„ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด, ํ˜„์žฌ์˜ ์ปค์Šคํ…€ ํ›…์—์„œ๋Š” ์–ด๋–ค ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„๊นŒ?
const interval = setInterval(() => {
  setCounter((prevCounter) => prevCounter - 1);
}, 1000);
  • ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ฑด counter๊ฐ€ ์–ด๋–ป๊ฒŒ ์ฆ๊ฐ€ํ•˜๋Š”์ง€๋ฅผ ์ œ์–ดํ•˜๋Š” ์ง€ํ‘œ์ด๋‹ค. ์ด ์ƒํƒœ(state) ๊ฐฑ์‹  ํ•จ์ˆ˜ ์ „์ฒด(setCounter)๋ฅผ ๋ฐ›์•„๋“ค์—ฌ์„œ ์ž‘๋™์„ ๋” ์œ ์—ฐํ•˜๊ฒŒ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

useCounter.js

const useCounter = (counterUpdateFn) => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter((prevCounter) => prevCounter + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return counter;
};
  • ์—ฌ๊ธฐ์— counterUpdateFn ์ด๋ผ๋Š” counter ์ƒํƒœ ๊ฐฑ์‹  ํ•จ์ˆ˜๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋„ฃ๊ณ , ใ…“์Šคํ…€ ํ›…์—์„œ๋Š” ์ด counterUpdateFn๋ฅผ ์‹คํ–‰ํ•ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.
const useCounter = (counterUpdateFn) => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter(counterUpdateFn());
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return counter;
};
  • ๊ทธ๋ฆฌ๊ณ  useCounter ์—์„œ ๋ฐ›๊ฒŒ๋˜๋Š” counterUpdateFn ์ธ์ž๋Š” ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜์ด๋ฉฐ, ์ด๋Š” ์ด์ „์˜ counter๋ฅผ ๋ฐ›์•„ ์ƒˆ๋กœ์šด counter๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค. ๋ฌผ๋ก  ์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์ปค์Šคํ…€ ํ›…์„ ์ด๋ ‡๊ฒŒ ์œ ์—ฐํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ๋ง์…ˆ์„ ํ• ์ง€ ๋บ„์…ˆ์„ ํ• ์ง€๋ฅผ ์ œ์–ดํ•˜๋Š” boolean ํ”Œ๋ž˜๊ทธ์™€ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด,
const useCounter = (forwards) => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter((prevCounter) => prevCounter + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return counter;
};
  • forwards ๋ผ๊ณ  ๋ช…๋ช…ํ•œ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅํ•œ๋‹ค๊ณ  ํ•ด๋ณด์ž. forwards๊ฐ€ true ์ด๋ฉด ๋ง์…ˆ์„ ํ•  ๊ฒƒ์ด๊ณ , false ๋ฉด ๋บ„์…ˆ์„ ํ•˜๋„๋ก ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค. ์ด forwards๋Š” ์ดˆ๊ธฐ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” boolean ๋ฐฉ์‹์œผ๋กœ ์„ ํƒํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.
const useCounter = (forwards = true) => {
  const [counter, setCounter] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCounter((prevCounter) => prevCounter + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return counter;
};
  • forwards ๋ผ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ดˆ๊ธฐ ๊ฐ’์„ true๋กœ ์„ค์ •ํ–ˆ๋‹ค. setInterval() ์•ˆ์—์„œ๋Š” ์ด forwards๊ฐ€ true ์ธ์ง€ false ์ธ์ง€๋ฅผ ํ™•์ธํ•ด์„œ true ๋ฉด setCounter์˜ ์‹์„ ๋ง์…ˆ์œผ๋กœ ๋งŒ๋“ค ๊ฒƒ์ด๊ณ , false ์ด๋ฉด setCounter์˜ ์‹์„ ๋บ„์…ˆ์œผ๋กœ ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค.
useEffect((forwards) => {
  const interval = setInterval(() => {
    if (forwards) {
      setCounter((prevCounter) => prevCounter + 1);
    } else {
      setCounter((prevCounter) => prevCounter - 1);
    }
  }, 1000);

  return () => clearInterval(interval);
}, []);
  • ๊ฐ„๋‹จํ•˜๊ฒŒ if ๋ฌธ์„ ์‚ฌ์šฉํ•ด์„œ setCounter๋ฅผ ๊ฐ๊ฐ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์กฐ๊ฑด์— ๋งž๊ฒŒ ๊ฐฑ์‹ ํ•˜๋„๋ก ํ–ˆ์ง€๋งŒ, ์•ž์„œ ํ–ˆ๋˜ ๋ฐฉ์‹์œผ๋กœ ์ „์ฒด ํ•จ์ˆ˜(ex. counterUpdateFn)๋ฅผ ๋ฐ›์•„๋“ค์ด๋Š” ๋ฐฉ๋ฒ•๋„ ๊ฐ€๋Šฅํ•˜๋‹ค. ์–ด๋Š ์ชฝ์ด๋“  ๊ฐ„์— ์ด ์ปค์Šคํ…€ ํ›…์˜ effect ์•ˆ์—๋Š” ์ด์ œ ์ƒˆ๋กœ์šด ์˜์กด์„ฑ์ด ์ƒ๊ฒผ์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์ปค์Šคํ…€ ํ›…์˜ useEffect์— ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์˜์กด์„ฑ์œผ๋กœ ์ฃผ์ž…ํ•˜๊ธฐ

  • useEffect ์•ˆ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ forwards๋Š” ๋ถ„๋ช… ์˜์กด์„ฑ์ด๋‹ค. ์ด๋Š” useEffect ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ์ •์˜๋œ ๊ฒƒ๋„ ์•„๋‹ˆ๊ณ , useCounter ์ปค์Šคํ…€ ํ›… '์™ธ๋ถ€' ์—์„œ ์„ค์ •๋œ ๊ฒƒ๋„ ์•„๋‹ˆ๋‹ค. ๋Œ€์‹ ์— ์ด๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ์„œ useCounter๊ฐ€ ๋ฐ›๊ฒŒ ๋˜๋Š” ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ useEffect์˜ ์˜์กด์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•ด์•ผ๋งŒ ํ•œ๋‹ค.
useEffect(() => {
  const interval = setInterval(() => {
    if (forwards) {
      setCounter((prevCounter) => prevCounter + 1);
    } else {
      setCounter((prevCounter) => prevCounter - 1);
    }
  }, 1000);

  return () => clearInterval(interval);
}, [forwards]);
  • forwards ๋ฅผ ์˜์กด์„ฑ์œผ๋กœ ์ถ”๊ฐ€ํ•จ์œผ๋กœ์จ ์˜์กด์„ฑ(forwards) ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚  ๋•Œ๋งˆ๋‹ค useEffect ํ•จ์ˆ˜๊ฐ€ ์žฌ์‹คํ–‰ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.

์ปค์Šคํ…€ ํ›…์˜ useEffect์— ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•ด์•ผ ํ•˜๋Š” ์ด์œ 

  • ๋ฌผ๋ก  ์ด๋Ÿฐ ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ์ฝ”๋“œ์— ๋”ฐ๋ผ์„œ ์ด ์˜์กด์„ฑ(forwards)์ด ๋ฐ”๋€Œ์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ๊ทธ ๊ฐ’์ด ํ•ญ์ƒ ์ฐธ ๋˜๋Š” ๊ฑฐ์ง“์œผ๋กœ ๊ณ ์ •๋  ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ•˜์ง€๋งŒ ๊ดœ์ฐฎ๋‹ค. ์˜์กด์„ฑ์ด ๋ฐ”๋€Œ์ง€ ์•Š๋Š” ์ด์ƒ useEffect๋Š” ์žฌ์‹คํ–‰ ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋˜ํ•œ, ์˜์กด์„ฑ ๊ฐ’์ด ๋ฐ”๋€Œ์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  useEffect์— ํ•ด๋‹น ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•˜๋Š” ๊ฒƒ์—๋Š” ํฐ ์ด์œ ๊ฐ€ ์žˆ๋‹ค. useCounter ์ปค์Šคํ…€ ํ›…์„ ํ˜ธ์ถœํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ(์„œ๋กœ ๋‹ค๋ฅธ ์ธ์ž๋ฅผ ์‚ฌ์šฉ)๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์— ์ธ์ž๊ฐ€ ๋ฐ”๋€Œ๋ฉด effect ํ•จ์ˆ˜ ์—ญ์‹œ ์žฌ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

BackwardCounter ์—์„œ ์ปค์Šคํ…€ ํ›… ํ˜ธ์ถœํ•˜๊ธฐ

  • ์ด์ œ BackwardCounter ์ปดํฌ๋„ŒํŠธ์—์„œ useCounter ํ›…์„ ํ˜ธ์ถœํ•ด์•ผ๋งŒ ํ•œ๋‹ค. ์ด์ „๊ณผ ๋™์ผํ•˜๊ฒŒ useCounter๋ฅผ import ํ•ด์˜จ ๋’ค์— useCounter์— ์ธ์ž๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
import useCounter from "../hooks/use-counter";

const BackwardCounter = () => {
  const counter = useCounter(false);

  return <Card>{counter}</Card>;
};
  • BackwardCounter ์ปดํฌ๋„ŒํŠธ์˜ ๋บ„์…ˆ ๋กœ์ง์€ useCounter๋กœ ์ „๋‹ฌํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜(forwards)์˜ ๊ฐ’์ด false ์—ฌ์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— useCounter์— false ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

    ForwardCounter ์ปดํฌ๋„ŒํŠธ์˜ ๋ง์…ˆ ๋กœ์ง์€ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ true ์ด๊ณ , ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ดˆ๊ธฐ๊ฐ’์ด true ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋Œ€๋กœ useCounter๋ฅผ ํ˜ธ์ถœ๋งŒ ํ•œ๋‹ค.

  • ๋งŒ์•ฝ, ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ธฐ๋ณธ ๊ฐ’ ์™ธ์— ๋‹ค๋ฅธ ๊ฐ’์„ ์›ํ•œ๋‹ค๋ฉด ๋‹น์—ฐํžˆ BackwardCounter ์ปดํฌ๋„ŒํŠธ์˜ useCounter(false) ์ฒ˜๋Ÿผ ํ•ด๋‹น ๊ฐ’์„ ์ง€์ •ํ•ด์„œ ๋„˜๊ฒจ์ค˜์•ผ ํ•œ๋‹ค. ์ด์ œ ๋ชจ๋“  ๋กœ์ง์ด ์™„๋ฃŒ ๋˜์—ˆ๋‹ค. BackwardCounter ์ปดํฌ๋„ŒํŠธ ์—ญ์‹œ ForwardCounter ์ปดํฌ๋„ŒํŠธ์ฒ˜๋Ÿผ ๋กœ์ง์ด ๋งค์šฐ ๊ฐ„๊ฒฐํ•ด์ง„ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

const BackwardCounter = () => {
  const counter = useCounter(false);

  return <Card>{counter}</Card>;
};

  • ๋‘ ๊ฐœ์˜ ์นด์šดํ„ฐ๊ฐ€ ๋ชจ๋‘ ์ปค์Šคํ…€ ํ›…(useCounter)๋ฅผ ํ†ตํ•ด ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™๋˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ •๋ฆฌ

  • ์ง€๊ธˆ๊นŒ์ง€์˜ ์ฝ”๋“œ๋“ค์€ ์ธ์œ„์ ์ธ ์˜ˆ์‹œ์ผ ๋ฟ์ด๋ฉฐ, ํ˜„์‹ค์ ์œผ๋กœ ์‹ค๋ฌด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์•„๋‹ ์ˆ˜๋„ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‘ ๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ ๋Œ€์‹  ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์ปค์Šคํ…€ ํ›…์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๊ฐœ๋กœ ๋‚˜๋ˆˆ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด ์ ์„ ์ธ์ง€ํ•˜๊ณ  ์žˆ๋„๋ก ํ•˜์ž.


โœฆ ์ถœ์ฒ˜


๐Ÿšจ ํ•ด๋‹น ํฌ์ŠคํŒ…์€ Udemy์˜ โŒœReact ์™„๋ฒฝ ๊ฐ€์ด๋“œโŒŸ ๊ฐ•์˜๋ฅผ ๋ฒ ์ด์Šค๋กœ ํ•œ ๊ธฐ๋ก์ž…๋‹ˆ๋‹ค.
โœ๐Ÿป ๊ฐ•์˜ git repo ๋ฐ”๋กœ๊ฐ€๊ธฐ

profile
์ผ๋‹จ ๊ณต๋ถ€๊ฐ€ '์ ์„ฑ'์— ๋งž๋Š” ๊ฐœ๋ฐœ์ž. ๊ทผ์„ฑ์žˆ์Šต๋‹ˆ๋‹ค.

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