๐Ÿค” hook? custom hook? ๊ทธ๊ฒŒ ๋ญ”๋ฐ?

๋ฐ•์›๋นˆยท2024๋…„ 6์›” 14์ผ

๋ฆฌ์•กํŠธ โš™๏ธ

๋ชฉ๋ก ๋ณด๊ธฐ
9/14

React์—์„œ์˜ Hook์€ ๋ฌด์—‡์ผ๊นŒ?

๋‚š์‹œํ„ฐ๋กœ ๊ฐ€๋ณผ๊นŒ์š”?

Hook์€ ํ•œ๊ตญ์–ด๋กœ ๊ณ ๋ฆฌ, ๋‚š์‹ฏ๋ฐ”๋Š˜์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
๋งŒ์•ฝ ์ œ๊ฐ€ ๋‚š์‹œ๋ฅผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์˜€์„๋•Œ ๋‚š์‹œ๋Œ€๋ฅผ ์ค€๋น„ํ•ด์•ผํ•˜๋Š”๊ฒƒ์ด ํšจ์œจ์ ์ผ ๊ฒƒ์ด๊ณ ,
๊ทธ ๋‚š์‹œ๋Œ€์—๋Š” ๊ณ ๊ธฐ๋ฅผ ๋‚š๊ธฐ์œ„ํ•œ ๋‚š์‹ฏ๋ฐ”๋Š˜์ด ์žˆ๊ฒ ์ฃ ?
๊ทธ๋ฆฌ๊ณ  ๊ทธ ๋‚š์‹ฏ๋ฐ”๋Š˜์— ๋ฏธ๋ผ๋ฅผ ๊ฑธ๊ณ  ๊ธฐ๋‹ค๋ฆฌ๋‹ค๋ณด๋ฉด ๋ฌผ๊ณ ๊ธฐ๊ฐ€ ๊ทธ ๋ฏธ๋ผ๋ฅผ ๋ฌผ๊ณ , ๋‚š์‹œ๋ฐ”๋Š˜์— ๊ฑธ๋ฆฌ๊ณ  ๋ง™๋‹ˆ๋‹ค.

Hook์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋Š”๋ฐ ์™œ ๋‚š์‹œํ„ฐ๋กœ ๊ฐ€๋‚˜์š”?

( ๊ฐœ์ธ์ ์œผ๋กœ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ์ž‘์„ฑํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. ํ‹€๋ฆฌ๊ฑฐ๋‚˜ ๋น„์œ ๊ฐ€ ์–ด์ƒ‰ํ•œ ์˜ˆ์‹œ์ผ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค! )

  • ๋‚š์‹œ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‚š์‹œ๋Œ€๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค.
  • ์ค€๋น„ํ•œ ๋‚š์‹œ๋Œ€์—๋Š” ๋‚š์‹ฏ๋ฐ”๋Š˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋‚š์‹ฏ๋ฐ”๋Š˜์— ๋ฏธ๋ผ๋ฅผ ๊ฑธ์–ด ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
  • ๋ฌผ๊ณ ๊ธฐ๋Š” ๋ฏธ๋ผ๋ฅผ ๋ฌผ๊ณ , ๋‚š์‹œ๋ฐ”๋Š˜์— ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค.

์œ„ ๊ณผ์ •์„ ์ด๋ ‡๊ฒŒ ๋ฐ”๊พธ์–ด์„œ ๋งํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

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

๊ทธ๋ž˜์„œ Hook์€..

๊ฐœ๋ฐœ์ž๊ฐ€ ํ•„์š”ํ•  ๋•Œ, ํ˜น์€ ์‚ฌ์šฉํ•˜๋ฉด ์œ ์šฉํ•  ๊ฒƒ ๊ฐ™์„๋•Œ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•˜๋Š” ์ผ์ข…์˜ ๋‚š์‹ฏ๋ฐ”๋Š˜์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
๋ฌผ๋ก  ๋‚š์‹œ๋ฐ”๋Š˜, ์ฆ‰ hook์ด ํ•„์š”๊ฐ€ ์—†๋Š” ์ƒํ™ฉ์ด๋ผ๋ฉด ๊ตณ์ด ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋˜๊ฒ ์ฃ ?

hook์— ๋Œ€ํ•œ ์ •์˜๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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

useState, useReducer, useEffect, useContext, useRef ๋“ฑ
๋ฆฌ์•กํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚ด์žฅ๋˜์–ด์žˆ๋Š” ์ˆ˜๋งŽ์€ hook๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ๋ฐ๋„ ์™œ ์šฐ๋ฆฌ๋Š” ๊ตณ์ด React๊ฐ€ ๋งŒ๋“ค์–ด ๋‘” ํ›…์ด ์žˆ๋Š”๋ฐ ๋”ฐ๋กœ custom hook์„ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•˜๋ ค๊ณ ํ• ๊นŒ์š”?

custom hook?

React๋Š” useState, useContext, ๊ทธ๋ฆฌ๊ณ  useEffect๊ฐ™์ด ๋ช‡๋ช‡ ๋‚ด์žฌํ•˜๊ณ  ์žˆ๋Š” Hook์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
๊ฐ€๋” ์กฐ๊ธˆ ๋” ๊ตฌ์ฒด์ ์ธ ๋ชฉ์ ์„ ๊ฐ€์ง„ Hook์ด ์กด์žฌํ•˜๊ธธ ๋ฐ”๋ž„ ๋•Œ๋„ ์žˆ์„ ๊ฒ๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค๋˜๊ฐ€, ์‚ฌ์šฉ์ž๊ฐ€ ์˜จ๋ผ์ธ ์ƒํƒœ์ธ์ง€ ๊ณ„์† ํ™•์ธํ•œ๋‹ค๋˜๊ฐ€, ํ˜น์€ ์ฑ„ํŒ…๋ฐฉ์— ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ชฉ์ ๋“ค์ฒ˜๋Ÿผ์š”.
React์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ Hook๋“ค์„ ์ฐพ๊ธฐ๋Š” ์–ด๋ ค์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ•„์š”์— ์•Œ๋งž์€ ๋ณธ์ธ๋งŒ์˜ Hook์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

React Docs์˜ custom hook์— ๋Œ€ํ•œ ๊ฐœ์š”์ž…๋‹ˆ๋‹ค.
๋‚ด์žฌ๋˜์–ด ์žˆ๋Š” hook์ด ์กด์žฌํ•˜์ง€๋งŒ,
์กฐ๊ธˆ ๋” ๊ตฌ์ฒด์ ์ธ ๋ชฉ์ ์„ ๊ฐ€์ง„ hook์ด ํ•„์š”ํ•  ๋•Œ custom hook์„ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•œ๋‹ค!
๋ผ๊ณ  ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ๋กœ ๋ณด๋Š” custom hook

๋งŒ์•ฝ ์šฐ๋ฆฌ์˜ ์›น์‚ฌ์ดํŠธ์—์„œ ์œ ์ €์—๊ฒŒ ๋„คํŠธ์›Œํฌ ์ƒํƒœ(์ธํ„ฐ๋„ท์˜ ์ƒํƒœ)๋ฅผ ์•Œ๋ ค์ฃผ๊ณ  ์‹ถ์„๋•Œ,
์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

export default function HomePage() {
  const [isOnline, setIsOnline] = useState(true);
  useEffect(() => {
    function handleOnline() {
      setIsOnline(true);
    }
    function handleOffline() {
      setIsOnline(false);
    }
    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);

  return (
    <div>
    	<h1>ํ™ˆํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.<p>
	    <p>{isOnline ? 'โœ… ์˜จ๋ผ์ธ' : 'โŒ ์—ฐ๊ฒฐ ์•ˆ ๋จ'}<p>
    </div>);
}

์œ„ ์˜ˆ์‹œ๋Š” ๋งŒ์•ฝ ์œ ์ €๊ฐ€ ํ™ˆํŽ˜์ด์ง€์—์„œ ์ธํ„ฐ๋„ท์— ์—ฐ๊ฒฐ๋˜์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด 'โŒ ์—ฐ๊ฒฐ ์•ˆ ๋จ'์„ ๋ณด์—ฌ์ฃผ๊ณ ,
์—ฐ๊ฒฐ์ด ๋˜์–ด์žˆ๋‹ค๋ฉด 'โœ… ์˜จ๋ผ์ธ' ์ด๋ผ๋Š” UI๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ํŽ˜์ด์ง€์—์„œ๋„ ์ด ๋กœ์ง์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์–ด๋–จ๊นŒ์š”?

export default function DetailPage() {
  const [isOnline, setIsOnline] = useState(true);
  useEffect(() => {
    function handleOnline() {
      setIsOnline(true);
    }
    function handleOffline() {
      setIsOnline(false);
    }
    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);

  return (
    <div>
    	<h1>๋””ํ…Œ์ผ ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.<p>
	    <p>{isOnline ? 'โœ… ์˜จ๋ผ์ธ' : 'โŒ ์—ฐ๊ฒฐ ์•ˆ ๋จ'}<p>
    </div>);
}

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

์—ฌ๊ธฐ๊นŒ์ง€ ์ฝ์–ด๋ณด์‹œ๋ฉด์„œ ๋ฌด์–ธ๊ฐ€ ์•„์‰ฌ์›€์ด ์žˆ์œผ์…จ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์‹ ๋‹ค๋ฉด,
์ง€๊ธˆ์ด ๋ฐ”๋กœ custom hook์„ ์ ์šฉ์‹œํ‚ฌ ํƒ€์ด๋ฐ์ž…๋‹ˆ๋‹ค!
์ˆœ์ฐจ์ ์œผ๋กœ ์ค‘๋ณต๋˜๋Š” ๋กœ์ง์„ custom hook์œผ๋กœ ๋ฐ”๊พธ๋Š” ๊ณผ์ •์„ ์ง„ํ–‰ํ•ด๋ณผ๊นŒ์š”?

1. ์œ„ ์˜ˆ์‹œ ํŽ˜์ด์ง€๋“ค์˜ ๋™์ผํ•œ ๋กœ์ง ์•Œ์•„๋‚ด๊ธฐ

const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
  function handleOnline() {
    setIsOnline(true);
  }
  function handleOffline() {
    setIsOnline(false);
  }
  window.addEventListener('online', handleOnline);
  window.addEventListener('offline', handleOffline);
  return () => {
    window.removeEventListener('online', handleOnline);
    window.removeEventListener('offline', handleOffline);
  };
}, []);

๋‹ค์‹œ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด, ์œ„ ๋กœ์ง์ด ์ •ํ™•ํžˆ ๋™์ผํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋˜ํ•œ, ์‚ฌ์šฉํ•˜๋Š” state๋„ isOnline ์œผ๋กœ ๋™์ผํ•˜์ฃ !

2. custom hook ๋งŒ๋“ค์–ด์ฃผ๊ธฐ

// useOnlineStatus.js
function useOnlineStatus() {
  const [isOnline, setIsOnline] = useState(true);
  useEffect(() => {
    function handleOnline() {
      setIsOnline(true);
    }
    function handleOffline() {
      setIsOnline(false);
    }
    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);
  return isOnline;
}

์ž, ์œ„์—์„œ ๋™์ผํ•œ ๋กœ์ง์„ ํŒŒ์•…ํ•˜๊ณ , ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋Š” state์ธ isOnline์„ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” custom hook์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

3. custom hook ์‚ฌ์šฉํ•ด์ฃผ๊ธฐ

export default function HomePage() {
  const isOnline = useOnlineStatus();

  return (
    <div>
    	<h1>ํ™ˆํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.<p>
	    <p>{isOnline ? 'โœ… ์˜จ๋ผ์ธ' : 'โŒ ์—ฐ๊ฒฐ ์•ˆ ๋จ'}<p>
    </div>);
}
export default function DetailPage() {
  const isOnline = useOnlineStatus();

  return (
    <div>
    	<h1>๋””ํ…Œ์ผ ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.<p>
	    <p>{isOnline ? 'โœ… ์˜จ๋ผ์ธ' : 'โŒ ์—ฐ๊ฒฐ ์•ˆ ๋จ'}<p>
    </div>);
}

์–ด๋–ค๊ฐ€์š”? ์ฝ”๋“œ๊ฐ€ ์งง์•„์ ธ ๊ฐ€๋…์„ฑ์ด ์˜ฌ๋ผ๊ฐ€์ง€ ์•Š์•˜๋‚˜์š”?
์ด์ œ ๋‘ ํŽ˜์ด์ง€๋Š” ๋ฐ˜๋ณต๋˜๋Š” ๋กœ์ง์ด ๊ฑฐ์˜ ์‚ฌ๋ผ์กŒ์Šต๋‹ˆ๋‹ค.
์ค‘์š”ํ•œ ์ ์€,
๋‘ ํŽ˜์ด์ง€์˜ ๋‚ด๋ถ€ ์ฝ”๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ทธ๊ฒƒ์„ ํ•˜๋Š”์ง€๋ณด๋‹ค
๊ทธ ํŽ˜์ด์ง€๋“ค์ด ๋ฌด์—‡์„ ํ•˜๋ ค๋Š”์ง€์— ๋Œ€ํ•ด ์ž‘์„ฑ์„ ํ–ˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

custom hook์„ ๋งŒ๋“ค์–ด ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•˜๋ฉด
๋ธŒ๋ผ์šฐ์ € API๋‚˜ ์™ธ๋ถ€ ์‹œ์Šคํ…œ(์„œ๋ฒ„)๊ณผ ์†Œํ†ตํ•˜๋Š” ์ฝ”๋“œ์— ๋Œ€ํ•ด ๋ถˆํ•„์š”ํ•œ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์ˆจ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

custom hook์„ ์‚ฌ์šฉํ•˜์˜€์„๋•Œ์˜ ์žฅ์ 

์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋“ฏ์ด, custom hook์„ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š”
๋‚ด๋ถ€ ์ฝ”๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ทธ๊ฒƒ์„ ํ•˜๋Š”์ง€ ๊ฐ€ ์•„๋‹Œ,
๊ทธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•ด๋‹น custom hook์„ ๊ฐ€์ง€๊ณ  ๋ฌด์—‡์„ ํ•˜๋ ค๋Š”์ง€์— ๋Œ€ํ•ด์„œ๋งŒ ์‹ ๊ฒฝ์„ ์“ฐ๋ฉด๋˜๋‹ˆ
์„œ๋กœ์˜ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•ด ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค!

custom hook์„ ์‚ฌ์šฉํ• ๋•Œ์˜ ์ฃผ์˜์‚ฌํ•ญ

๋ชจ๋“  hook์˜ ์ด๋ฆ„์€ use ๋’ค์˜ ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
Ex. useCustomHook ์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค!

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