๐๏ธ ๋ฐฑ์๋ ๊ฐ๋ฐ์๋ฅผ ์ํ React Hook ๊ฐ์ด๋
๊ณผ๊ฑฐ์๋ React์์ ์ํ(state)๋ฅผ ๊ด๋ฆฌํ๋ ค๋ฉด ํด๋์คํ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํด์ผ ํ์ต๋๋ค. ํ์ง๋ง ์ฝ๋๊ฐ ๊ธธ์ด์ง๊ณ , ์ฌ์ฌ์ฉ์ฑ์ด ๋จ์ด์ง๋ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด React Hook์ด ๋ฑ์ฅํ์์ผ๋ฉฐ, ํจ์ํ ์ปดํฌ๋ํธ์์๋ ์ํ ๊ด๋ฆฌ์ ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋์ ์ญํ ์ ์ํํ ์ ์๋๋ก ๋์์ค๋๋ค. ย React Hook์ด ํ์ํ ์ด์ * ๋ ๊ฐ๊ฒฐํ ์ฝ๋: ํด๋์คํ ์ปดํฌ๋ํธ๋ณด๋ค ์ฝ๋๊ฐ ์ง๊ด์ ์ด๊ณ ์งง์์ง * ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ ํฅ์: ๊ด์ฌ์ฌ ๋ถ๋ฆฌ๊ฐ ์ฌ์์ง๊ณ , ์ฌ์ฌ์ฉ์ฑ์ด ์ฆ๊ฐ * ๋ถ์ ํจ๊ณผ ๊ด๋ฆฌ๊ฐ ์ฉ์ด: useEffect๋ฅผ ํ์ฉํ์ฌ ์ฌ์ด๋ ์ดํํธ ๊ด๋ฆฌ๋ฅผ ์ฝ๊ฒ ์ํ ๊ฐ๋ฅ ์ด๋ฒ ๊ธ์์๋ ๋ฐฑ์๋ ๊ฐ๋ฐ์์ ์์ ์์ React Hook์ ์ดํดํ๊ธฐ ์ฝ๊ฒ ์ค๋ช ํ๊ณ , ์ค๋ฌด์์ ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค. ย ์ฃผ์ React Hook ์๊ฐ ย [useState - ์ํ ๊ด๋ฆฌ] useState๋ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ํ(state)๋ฅผ ์ ์ธํ๊ณ ๋ณ๊ฒฝํ ์ ์๋๋ก ๋์์ค๋๋ค. import { useState } from "react"; function Counter() { const [count, setCount] = useState(0); // ์ํ ์ ์ธ return ( ํ์ฌ ์นด์ดํธ: {count} setCount(count + 1)}>์ฆ๊ฐ ); } โ useState๋ Java์์ ๋ณ์์ Setter ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์๊ณผ ์ ์ฌํฉ๋๋ค. ํ์ง๋ง React์์๋ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์ปดํฌ๋ํธ๊ฐ ๋ค์ ๋ ๋๋ง๋๋ค๋ ์ฐจ์ด์ ์ด ์์ต๋๋ค. ย [useEffectย - ๋ถ์ ํจ๊ณผ(Site Effect) ์ฒ๋ฆฌ] useEffect๋ย ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ๋ ์คํํด์ผ ํ๋ ์ฝ๋(๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ, ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ฑ๋ก ๋ฑ)๋ฅผ ์ฒ๋ฆฌํ๋ Hook ์ ๋๋ค. import { useState, useEffect } from "react"; function Timer() { const [seconds, setSeconds] = useState(0); useEffect(() => { const interval = setInterval(() => { setSeconds((prev) => prev + 1); }, 1000); return () => clearInterval(interval); }, []); return ํ์ด๋จธ: {seconds}์ด; } โ useEffect๋ Spring์ @PostConstruct ๋ฐ @PreDestroy์ ์ ์ฌํฉ๋๋ค. * @PostConstruct: ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ๋ ๋๋ง๋ ๋ ์คํ (useEffect์ ์ด๊ธฐ ์คํ) * @PreDestroy: ์ปดํฌ๋ํธ๊ฐ ์ฌ๋ผ์ง ๋ ์ ๋ฆฌ (useEffect์ Cleanup) [useMemoย - ์ฑ๋ฅ ์ต์ ํ] useMemo๋ ๋ถํ์ํ ์ฐ์ฐ์ ๋ฐฉ์งํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํ ๋ ์ฌ์ฉ๋ฉ๋๋ค. import { useState, useMemo } from "react"; function ExpensiveCalculation({ num }) { const squaredValue = useMemo(() => { console.log("์ฐ์ฐ ์ํ ์ค..."); return num * num; }, [num]); // num์ด ๋ณ๊ฒฝ๋ ๋๋ง ๋ค์ ๊ณ์ฐ return ๊ณ์ฐ ๊ฒฐ๊ณผ: {squaredValue}; } โ useMemo๋ Java์ ์บ์ฑ(Cache)๊ณผ ๋น์ทํฉ๋๋ค. useMemo๋ฅผ ํ์ฉํ๋ฉด ๊ฐ์ ์ ๋ ฅ๊ฐ์ ๋ํด ๋ถํ์ํ ์ฐ์ฐ์ ์ค์ด๊ณ ์บ์ฑ๋ ๊ฐ์ ํ์ฉํ ์ ์์ต๋๋ค. ย [useCallbackย - ํจ์ ๋ฉ๋ชจ์ด์ ์ด์ ] useCallback์ useMemo์ ์ ์ฌํ์ง๋ง, ํจ์์ ์ฐธ์กฐ๊ฐ์ ์ ์งํ์ฌ ๋ถํ์ํ ๋ ๋๋ง์ ๋ฐฉ์งํ๋ Hook์ ๋๋ค. import { useState, useCallback } from "react"; function Parent() { const [count, setCount] = useState(0); const handleClick = useCallback(() => { setCount((prev) => prev + 1); }, []); return ์ฆ๊ฐ; } โ useCallback์ Spring์ Singleton ํจํด๊ณผ ๋น์ทํฉ๋๋ค. ย [useRefย - DOM ์ ๊ทผ & ์ํ ์ ์ง] useRef๋ ์ปดํฌ๋ํธ์ ์ํ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ๋ ํน์ ๊ฐ์ ์ ์งํ๊ฑฐ๋, DOM ์์์ ์ง์ ์ ๊ทผํ ๋ ์ฌ์ฉ๋ฉ๋๋ค. import { useRef } from "react"; function TextInput() { const inputRef = useRef(null); const focusInput = () => { inputRef.current.focus(); }; return ( ํฌ์ปค์ค ์ด๋ ); } โ useRef๋ Java์ ์ธ์คํด์ค ๋ณ์์ ๋น์ทํ ์ญํ ์ ํฉ๋๋ค. ย ๊ฒฐ๋ก React Hook์ ํจ์ํ ์ปดํฌ๋ํธ์์ ์ํ ๊ด๋ฆฌ์ ๋ถ์ ํจ๊ณผ ์ฒ๋ฆฌ๋ฅผ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋๋ก ๋์์ค๋๋ค. ๊ฐ Hook์ ํ์ฉ ์ฌ๋ก๋ฅผ ์ ๋ฆฌํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค. * useState โ ์ปดํฌ๋ํธ ๋ด๋ถ์ ์ํ ๊ด๋ฆฌ * useEffect โ ๋ถ์ ํจ๊ณผ ์ฒ๋ฆฌ (API ํธ์ถ, ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ฑ๋ก ๋ฑ) * useMemo โ ์ฐ์ฐ ๊ฒฐ๊ณผ ์บ์ฑ (๋ถํ์ํ ์ฌ๊ณ์ฐ ๋ฐฉ์ง) * useCallback โ ํจ์ ๋ฉ๋ชจ์ด์ ์ด์ (๋ถํ์ํ ๋ ๋๋ง ๋ฐฉ์ง) * useRef โ DOM ์ ๊ทผ ๋ฐ ๊ฐ ์ ์ง ๋ฐฑ์๋ ๊ฐ๋ฐ์๋ผ๋ฉด, React๋ฅผ API ์ฐ๋์ด ํ์ํ ๋์๋ณด๋๋ ์ด๋๋ฏผ UI ๊ฐ๋ฐ์ ํ์ฉํ ๋๊ฐ ๋ง์ ๊ฒ์ ๋๋ค. Hook์ ์ ํ์ฉํ๋ฉด ์ฑ๋ฅ์ ์ต์ ํํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฌ์ด ์ฝ๋ ์์ฑ์ด ๊ฐ๋ฅํ๋ฏ๋ก, ์ค๋ฌด์์๋ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค!