๐จ 08. useRef: ๋ ๋๋ง์ ํผํ๋ ๋น๋ฐ ๊ธ๊ณ
๐ ๊ฐ์
ํญ์ ์ต์ ๊ฐ์ ์ ์งํด์ผ ํ์ง๋ง ํ๋ฉด์ด ๋ฆฌ๋ ๋๋ง๋๋ ๊ฒ์ ์์น ์์ ๋, useRef๊ฐ ์ด๋ค ์ญํ ์ ํ๋์ง ๋ด๋ถ ์๋ฆฌ์ ํจ๊ป ํํค์นฉ๋๋ค.
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
useRef๊ฐ ๋จ์ํ<input>์ฐฝ์ ํฌ์ปค์ค๋ฅผ ๋ง์ถ๋ DOM ์ฐ๊ฒฐ ๋๊ตฌ๊ฐ ์๋์ ์๊ฒ ๋๋ค.- ์ํ(
useState)์ ์ฐธ์กฐ(useRef)์ ๋ณธ์ง์ ์ธ ๊ธฐ์ ์ ์ฐจ์ด๋ฅผ ์ค๋ ์ท vs ์๊ตฌ ๋ณ์ ๋ฉํ ๋ชจ๋ธ๋ก ๊ตฌ๋ถํ ์ ์๋ค.- ํ๋ฉด ์ ๋ฐ์ดํธ ์์ด ๋ถ๋ณํ๋ ๊ฐ์ ์๋ฐํ ์ถ์ ํ๊ณ ์ถ์ ๋(ํ์ด๋จธ ID ์ ์ฅ, ์ด์ ์ํ ์ถ์ )
useRef๋ฅผ ํ๋ฅญํ๊ฒ ์ค๊ณํ ์ ์๋ค.
๐ ๋ชฉ์ฐจ
- ๐ค ์ ์์์ผ ํ๋๊ฐ: ์๋์น๋ ์ปดํฌ๋ํธ๋ฅผ ๊ฒฌ๋๋ ๋ป
- ๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
- ๐งฉ ์ค์ ๋ฌด๊ธฐํ: ์จ๊ฒจ์ง ๋ณ์๋ค ๋ค๋ฃจ๊ธฐ
- ๐ฅ ์๋ฌ ํด๊ฒฐ ์นดํ๋ก๊ทธ
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 10๋ถ / ํต์ฌ ํํธ: 7๋ถ
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
- ์์ฒ (์ ์
): "ํ์ด๋จธ ์คํฑ์์น๋ฅผ ๋ง๋ค๊ณ ์๋๋ฐ์! ์์ ๋ฒํผ์ ๋๋ ๋๋ฐ ์ค์ง ๋ฒํผ์ ๋๋ฅผ ๋ ํ์ด๋จธ๊ฐ ์ ๋ฉ์ถ๊ณ ๊ณ์ ๊ฐ์! ์ธํฐ๋ฒ ์์ด๋(ID)๋ฅผ
useState์ ๋ด์๋๋๋ฐ ๋ญ๊ฐ ๋ฌธ์ ์ฃ ?" - ์ํธ(๋ฆฌ๋): "์์ฒ ๋, ํ๋ฉด์ ๊ทธ ์ซ์ ๋ณด์ฌ์ฃผ์ค ๊ฑด๊ฐ์? ์ ๋ณด์ฌ์ค ๋ณ์๋ผ๋ฉด ๋ ๋๋ง ํญํ(
useState) ํฐ๋จ๋ฆฌ์ง ๋ง๊ณ ์กฐ์ฉํ ๋ท์ฃผ๋จธ๋(useRef)์ ๋ฃ๊ณ ๋ค๋๋ผ๊ณ ์์ ์ ๋ง์๋๋ ธ์ ํ ๋ฐ์."
๐ค ์ ์์์ผ ํ๋๊ฐ: ์๋์น๋ ์ปดํฌ๋ํธ๋ฅผ ๊ฒฌ๋๋ ๋ป
๋๋ถ๋ถ์ React ์์ ๋ฌธ์๋ฅผ ๋ณด๋ฉด useRef๋ฅผ ์ฒ์ ์๊ฐํ ๋ ๊ผญ **"DOM ์กฐ์(<input ref={myRef}>)์ ์ํ ๊ฐ๊ณ ๋ฆฌ์
๋๋ค~"**๋ผ๊ณ ๊ฐ๋ฅด์ณ. ํ์ง๋ง ์ด๊ฑด useRef ๋ฅ๋ ฅ์น ์ค ๋น์ฐ์ ์ผ๊ฐ๋ ์ ๋๋ 10%์ ๋ถ๊ฐ ๊ธฐ๋ฅ์ ๋ถ๊ณผํด.
๐ค ์ ๊น, ๋จผ์ ์๊ฐํด๋ด
์คํฑ์์น ์ฝ๋๋ฅผ ์ง๋ ค๊ณ ํด. ํ์ด๋จธ๋ฅผ ๋ฉ์ถ๋ ค๋ฉด ์๋ฐ์คํฌ๋ฆฝํธ์clearInterval(์์ด๋๊ณ ์ ๋ฒํธ)๊ฐ ํ์ํ์ง.
์ด ๊ณ ์ ๋ฒํธ๋ฅผ ๋ ๋๋ง ์ฌ์ดํด์ด ๋์๋ ๊ธฐ์ตํ๋ ค๋ฉด ์ด๋๋ค ๋ณ์๋ฅผ ๋ง๋ค์ด์ผ ํ ๊น?
// โ ์์ฒ ์ด์ ํญํ ํฌ์ฒ (์ํ ์ค๋จ์ฉ)
function Stopwatch() {
const [seconds, setSeconds] = useState(0);
const [timerId, setTimerId] = useState(null); // ๐จ ํ๋ฉด์ ๊ทธ๋ฆฌ์ง๋ ์์ ๊ฑด๋ฐ ๊ตณ์ด ์ํ๋ก ๋ง๋ฆ!
const handleStart = () => {
const id = setInterval(() => setSeconds(s => s + 1), 1000);
setTimerId(id); // ๋ถํ์ํ๊ฒ ์ํ ๊ฐฑ์ ๋ฐ๋! -> ๋ฌด์๋ฏธํ ๋ ๋๋ง 1ํ ์ถ๊ฐ ๋ฐ์ฌ!
};
const handleStop = () => {
clearInterval(timerId);
};
return (
<div>
<p>๊ฒฝ๊ณผ ์๊ฐ: {seconds}์ด</p>
<button onClick={handleStart}>์์</button>
<button onClick={handleStop}>๋ฉ์ถฐ!</button>
</div>
);
}์์ฒ ์ด ์ฝ๋๋ ์ผํ ๋ฌธ์ ๊ฐ ์์ด ๋ณด์ฌ(๊ตฌ๋์ ๋๋๊น).
ํ์ง๋ง ์ด๊ฑด ์์ฐ์ค์ํ ํผํฌ๋จผ์ค ์ฐ๋ ๊ธฐ ์ฝ๋์
๋๋ค. timerId๋ ํ๋ฉด UI์ ํฝ์
๋จ ํ๋๋ ๋ฐ๊พธ์ง ์๋๋ฐ, ์๋ฅผ ๊ฐฑ์ ํ๋ต์๊ณ setTimerId(id)๋ฅผ ๋๋ฆฌ๋ ์๊ฐ ๋ฆฌ์กํธ ์ ์ฒด ์์ง์ด "์! ์ํ ๋ณ๊ฒฝ! ๋ ๋๋ง ํธ๋ฆฌ ํ์!" ์๋์ ์น๋ฉฐ ํ๋ฉด ์ ์ฒด๋ฅผ ๋ถํ์ํ๊ฒ ์๋ก ๊ทธ๋ฆฝ๋๋ค.
์ฐ๋ฆฌ์๊ฒ **"๊ฐ์ ์์ ํ๊ฒ ์ ์ฅํ๋, ๊ฐ์ด ๋ฐ๋๋ค๊ณ ์๋ง(React)ํํ
์ผ๋ฌ์ผ๋ฌ ๋ ๋๋ง ํญํ์ ๋ถ๋ฅด์ง๋ ์๋ ๋น๋ฐ ์ฐฝ๊ณ "**๊ฐ ์ ๋์ ์ผ๋ก ํ์ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ ๋ฐ๋ก useRef์ ๋ณธ์ง์
๋๋ค.
๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
๐ง 5์ด์๊ฒ ์ค๋ช ํ๋ค๋ฉด?
useState๋ ๋ฐฉ์ก๊ตญ ๋ง์ดํฌ์ผ. ๋ง์ดํฌ์ ๋๊ณ ์ซ์๋ฅผ ๋ฐ๊พธ๋ฉด ์จ ๋๋ค ๋ง์ ์ฌ๋๋ค(์ปดํฌ๋ํธ๋ค)์ด ๋ค ๋ฆฌ์ ๋ผ์ ๋ค์ ๋ค์ผ๋ฌ ๊ด์ฅ์ผ๋ก ๋ชจ์ด์ง(๋ฆฌ๋ ๋๋ง ํํฐ).
useRef๋ ๋ค ๋ฐ์ง๋จ ๊น์์ด ์จ๊ฒจ๋์ **์์ ๊ธ๊ณ ๋ฐ์ค(current์์ฑ)**์ผ.
๋ค๊ฐ ๋ชฐ๋ ๊ธ๊ณ ๋ฌธ์ ์ด๊ณcurrent๊ณต๊ฐ ์์ ๋์ 100๋ง ์์ผ๋ก ๋ฐ๊พธ๋ 10์์ผ๋ก ์ชผ๊ฐ๋ ๋๋ค ์ฌ๋๋ค์ ์๋ฌด๋ ๋ชจ๋ฅด๊ณ ์๋ฌด ์๋ฆฌ๋ ์ ๋(๋ฆฌ๋ ๋๋ง ๋ฌด์).
ํ์ง๋ง ์ปดํฌ๋ํธ ๊ด์ฅ์ด ์ฌ๋ฌ ๋ฒ ํญ๋ฐํ๊ณ ๋ค์ ์๊ฒจ๋, ๊ทธ ๋ฐ์ง๋จ ์ ๊ธ๊ณ ์์๋ ์ปดํฌ๋ํธ๊ฐ ์ด์์๋ ๊ธฐ๊ฐ ๋ด๋ด ์๊ตฌ์ ์ผ๋ก ๋ณด์กด๋๋ฉด์ ์ ๋ ์ ๋ณด๊ฐ ์ฆ๋ฐํ์ง ์์.
โ
ํต์ฌ ์๋ฆฌ:
๋ฆฌ์กํธ ์ฝ์ด ๊ฐ๋ฐ์๋ค์ ๋จธ๋ฆฌํต์ ๋ฏ์ด๋ณด๋ฉด ์ด๋ ๊ฒ ์ค๊ณ๋์ด ์์ต๋๋ค.
์ฌ์ค useRef ๋ด๋ถ ์ฝ๋๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋จ์ํ ๊ผผ์์
๋๋ค. useState({ current: initialValue })๋ผ๊ณ ์ธํ
ํด๋๊ณ ๊ทธ setter ํจ์๋ฅผ ํ์ ์ .๋ ์ ๊ณตํ์ง ์์์, ๋ฐ๊ตฌ๋ ์ฃผ์๊ฐ์ด ์ปดํฌ๋ํธ ์์ ๋ด๋ด **์ฒ ๋ฒฝ ๋ฐฉ์ด ๋ ํผ๋ฐ์ค(๋ถ๋ณ ์ฃผ์)**๋ก ์ ์ง๋๊ฒ ๋ง๋ค์ด๋์ ๊ฒ์
๋๋ค!
(ํ๋ฉด UI ํ์ดํ๋ผ์ธ๊ณผ ์๋ฒฝํ ๊ฒฉ๋ฆฌ๋, ํ(่ซ)๋ฆฌ์กํธ ์ํ๊ณ์ ์ค์์ค ์ํ ๋น๋ฐ ๊ธ๊ณ ์ฃ .)
๐งฉ ์ค์ ๋ฌด๊ธฐํ: ์จ๊ฒจ์ง ๋ณ์๋ค ๋ค๋ฃจ๊ธฐ
โ
์ํธ์ ์๋ฒฝํ ๋ฆฌํฉํ ๋ง: current ๋ฌด๊ธฐ๊ณ ์ฌ์ฉ
- UI(ํ๋ฉด)์ ๊ทธ๋ฆด ๋ด์ฉ์ -> ๋ ๋๋ง์ ๋ฐ์ํ๋
useState๋ง์ดํฌ์ ๋ด๋๋ค (seconds) - ๋ด๋ถ ๋ก์ง ํต์ ์ฉ(์๋, ํ์ด๋จธ ์์ด๋, ๋๋๊ทธ ์คํฌ๋กค ํฝ์
์ด์ ์์น ๋ฑ) ๋ฐฑ๊ทธ๋ผ์ด๋ ๋ฐ์ดํฐ๋ -> ๋น๋ฐ ๊ธ๊ณ
useRef์ ๋ด์ ๋ชฐ๋ ๊ด๋ฆฌํ๋ค (timerRef)
// โ
์ฐ์ํ ๊ณ ์ฑ๋ฅ ๋ ๋๋ง ์ฝ๋ (Pro Approach)
function Stopwatch() {
const [seconds, setSeconds] = useState(0); // ํ๋ฉด UI์ ์ง๊ฒฐ๋ ์ ์ผํ ์น๊ตฌ
const timerRef = useRef(null); // ๐ฏ ๋ฆฌ๋ ๋๋ง ๊ฐ์ ๋ฉด์ ๊ถ ๋ฐ๊ธ!
const handleStart = () => {
if (timerRef.current) return; // ์ด๋ฏธ ๋๊ณ ์์ผ๋ฉด ๋ฐฉ์ด!
// ์ด ๊ฐ์ ๊ฐฑ์ ํด๋ ๋ฆฌ์กํธ๋ ๋๋ ๊น์ง ์ ํฉ๋๋ค. ๋ถํ์ํ ๋ ๋๋ง 0ํ ๋ฌ์ฑ.
timerRef.current = setInterval(() => setSeconds(s => s + 1), 1000);
};
const handleStop = () => {
clearInterval(timerRef.current);
timerRef.current = null; // ์ด๊ธฐํ
};
return (
<div>
<p>๊ฒฝ๊ณผ ์๊ฐ: {seconds}์ด</p>
<button onClick={handleStart}>์์</button>
<button onClick={handleStop}>๋ฉ์ถฐ!</button>
</div>
);
}๊น๋ํฉ๋๋ค. setTimerId(id) ๊ฐ์ ๋นํจ์จ์ด ๋ชจ์กฐ๋ฆฌ ํ๊ดด๋์์ด.
timerRef.current = ... ํ ๋น๋ฌธ์ ๊ทธ์ ์์ํ ๋ฐ๋๋ผ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๊ฐ ๋๋ ๊ฒ๊ณผ ๋๊ฐ์ ๋ ๋ ตํ ์์ค์ ์๋๋ฅผ ๋ณด์ฅํฉ๋๋ค.
๐ฅ ์๋ฌ ํด๊ฒฐ ์นดํ๋ก๊ทธ
โ useRef ๊ธ๊ณ ์์ ๊ฐ์ ํ๋ฉด์ ๋ ธ์ถ์ํค๋ ์ฌ์๋๊ฐ
์ธ์ ๋์ค๋๊ฐ?
const countRef = useRef(0);
const handleAdd = () => {
countRef.current += 1;
// ๐ฅ ์์ฒ : "ํํ ๋๋ ๋๋ฐ ํ๋ฉด ์ซ์๊ฐ ์ ๋ฐ๋์์์!"
};
// ... <button onClick={handleAdd}>๋๋น ๋๋ฆ ํ์: {countRef.current}</button> ...์์ธ: useRef๊ฐ ๋ ๋๋ง์ ๋ฐ๋์ํค์ง ์๋๋ค(ํ-๋ฆฌ์กํธ ์ฑ์ง)๋ ๊ฒ์ ์ธ์งํ์ง ๋ชปํ๊ณ ์ต์ง๋ก ํ๋ฉด UI ํฝ์
(JSX ๋ฐํ ๊ณต๊ฐ)์ ์ค์
๋ฃ์ ๊ฑฐ์ผ. ๋ฆฌ์กํธ๋ ๋ค๊ฐ ๋ฒํผ์ ๋๋ฌ์ current์ 500์ ์ค์
๋ฃ๋ 100์ ์ค์
๋ฃ๋ "์ด์ฉ๋ผ๊ณ ? ๋ํํ
๋ ๋๋งํ๋ผ๊ณ (setState) ์ ํธ ์ ์คฌ์์?" ํ๋ฉฐ ํ์
ํด๋ฒ๋ฆฌ์ง.
๊ทธ๋ฌ๋ค๊ฐ ์ฐ์ฐํ ์์ ์๋ ๋ค๋ฅธ ์ํ(State)๊ฐ setState๋์ด ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง์ ํ ๋ฐํด ๋๋ฉด... ๋๋๊ฒ๋ ์๊น ์์๋ 500์ด๋ผ๋ ๋๋ฆ ํ์๊ฐ ์๊ตฌ๋ณด์กด๋์ด ์๋ค๊ฐ ๊ทธ์ ์ผ ๊ฐ์๊ธฐ ํ๋ฉด์ ํ! ํ๊ณ ํ์ด๋์ต๋๋ค(๋ฐ๋ฆฐ ๋ ๋๋ง). ์ฌ์ฉ์๋ ๊ทน๋์ ํผ๋์ ๊ฒช์ฃ .
ํด๊ฒฐ์ฑ
:
์ ๋๋ก!! useRef์ current ์์ฑ๊ฐ์ ๋ ๋๋ง ๊ฒฐ๊ณผ๋ฌผ(<p>{์ฌ๊ธฐ}</p>) ์์๋ค ์จ์ ๋์ฐ์ง ๋ง์ธ์. UI์ ์ง๊ฒฐ๋๋ ๋ฐ์ดํฐ๋ผ๋ฉด ๋ฐ๋์ useState๋ฅผ ๊ณ ๋ฅด์ญ์์ค.
"๋ฐ์ดํฐ์ ๋ณ๊ฒฝ์ด ์๊ฐ์ ์ธ ๋ณํ๋ฅผ ๋ณ๋๊ฐ?" -> YES๋ฉด State, NO๋ฉด Ref์
๋๋ค.
๐ ์ด๋ฒ์ ๋ฐฐ์ด ๋ด์ฉ ์ด์ ๋ฆฌ
| ๋๊ตฌ์ ๋ณธ์ง | useState (๋ง์ดํฌ) | useRef (๋น๋ฐ ๊ธ๊ณ ) |
|---|---|---|
| ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ฉด? | ์ฆ์ ๋ฆฌ๋ ๋๋ง ๋ฐ์ (UI ์ ๋ฐ์ดํธ O) | ๋ฆฌ๋ ๋๋ง ๋ฐ์ ์ ํจ (ํ๋ฉด ์ผ์ด์์ X) |
| ๋ ๋๋ง ๊ฐ ๋ฐ์ดํฐ ์ ์ง | O (ํ์ง๋ง ๋ ๋๋ง๋ง๋ค ๊ฐ์ ์ค๋ ์ท ๊ณ ์ ๋ณต์ฌํด ์ค) | O (์ธ์ ๊ฐ๋ฆฌ์ผ๋ '๋์ผํ ์ต์ ์ฃผ์ ํ ๋ฒํผ' ์ฐธ์กฐ) |
| ์ด๋์ ์ด์ธ๋ฆฌ๋๊ฐ? | ์ธํ ์ ๋ ฅ ํ ์คํธ, ๋ชจ๋ฌ์ฐฝ(T/F), ๋ฒํผ ์ปฌ๋ฌ ๋ฑ ํ๋ฉด ๊ทธ๋ฆด ๋ | ํ์ด๋จธ ์์ด๋ ์ฅ๊ธฐ, DOM ์์ ํฌ์ปค์ค ์กฐ์ํ๊ธฐ, ์ด์ (Prev) ๊ฐ ๋ชฐ๋ ์ ์ฅํ๊ธฐ ๋ฑ |
๐ก ํ ์ค๋ก ๊ธฐ์ตํ๊ธฐ
**"๋๋ง์ ์ด ์์คํ ๋ฐ์ดํฐ๊ฐ ๋ฐ๋์์ ๋, ์จ ๋ง์์ ๋ค์ง์ด์๊ณ ํ๋ฉด์ ์๋ก๊ณ ์นจํ๊ณ ์ถ์๊ฐ?"**์ด ๋ฌธํญ์ "์๋์, ๊ทธ๋ฅ ๋ฐ์ดํฐ ์ซ์๋ง ํผ์ ๊ธฐ์ตํด์ฃผ๋ฉด ๋ผ์."๋ผ๊ณ ์ธ์น๊ณ ์ถ๋ค๋ฉด ๋ฌด์กฐ๊ฑด ๋ง์ค์ด์ง ๋ง๊ณuseRef์์ฃผ๋จธ๋๋ฅผ ์ง๋ผ.
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
ํ๋ฉด์ ๊ทธ๋ฆฌ์ง๋ ์์ ํ์ด๋จธ ์์ด๋๋ก ๋ฌด์๋ฏธํ ๋ ๋๋ง ํญํ์ ๋ ๋ฆฌ๊ณ ์์๋ค๋, useRef๊ฐ ๋จ์ํ ํฌ์ปค์ค ์ก๋ ์ฉ๋๊ฐ ์๋๋ผ '์์ฃผ๋จธ๋ ๋น๋ฐ ๊ธ๊ณ '๋ผ๋ ๋น์ ๊ฐ ํต์ฌ์ ๊ดํตํ๋ค.
๐ก "์ํ(State)๋ ๋ง์ดํฌ, ์ฐธ์กฐ(Ref)๋ ๋น๋ฐ ๊ธ๊ณ . ๋ฐ์ดํฐ๊ฐ ๋ณํ ๋ ํ๋ฉด ํฝ์ ์ด ๋ฐ๋์ด์ผ ํ๋์ง ํ ๋ฒ๋ง ์๊ฐํด๋ณด์!"
์๋ฐ์คํฌ๋ฆฝํธ ๋ณ์๋ ๋ค๋ฅผ ๊ฒ ์์ง๋ง ์ปดํฌ๋ํธ ์๋ช
๋ด๋ด ์๊ตฌ ๋ณด์กด๋๋ค๋ ๊ฒ ์ ๊ธฐ์์ด๋ค. ๋น์ฅ ๋ด์ผ ์ถ๊ทผํด์ ์ธ๋ฐ์์ด ์ํ๋ก ๋นผ๋์ ์คํฌ๋กค ์์น๊ฐ์ด๋ ํ์ด๋จธ ์๋ณ์๋ค ๋ค useRef๋ก ๊ฐ์์์ด์ผ์ง. ์์ด ๋ปฅ ๋ซ๋ฆฌ๋ ๊ธฐ๋ถ์ด๋ค.
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. useState ๋์ useRef๋ฅผ ์ ํํ๋ ๊ฒ์ด ๊ฐ์ฅ ์๋ฒฝํ ๋ฒ ์คํธ ํ๋ํฐ์ค(Best Practice)๋ก ๋ถํฉํ๋ ์ํฉ์ ํ๋ ๊ณ ๋ฅด์ธ์.
- A) ์ฌ์ฉ์๊ฐ ์ผํ๋ชฐ ๊ฒ์์ฐฝ์์ ํ์ดํํ๊ณ ์๋ ์ค์๊ฐ ๊ฒ์์ด ํ ์คํธ ๊ฐ์ ์ ์งํ๊ณ ์ถ์ ๋.
- B) ํ์ฌ ๋ก๊ทธ์ธํ ํ ํฐ์ด ์ ํจํ ์ ์ ์ธ์ง์ ๋ํ boolean(T/F) ๊ฐ์ ์ ์ฅํ๊ณ ๊ถํ ์๋ฌ ๋ชจ๋ฌ์ ๋์ธ ๋.
- C) ์ปดํฌ๋ํธ ๋ง์ดํธ ์ดํ 30์ด ๋์ ์๋ฌด ํด๋ฆญ๋ ํ์ง ์์ผ๋ฉด ๊ฒฝ๊ณ ํ์
์ ๋์์ค
setTimeoutํจ์์ ์์ฝ ๊ณ ์ ํต์ ์์ด๋(ID)๋ฅผ ์ ์ฅํ ๋. - D) ์ฌ์ฉ์์ ํ์ฌ ์ผํ ์นดํธ์ ๋ด๊ธด ๋ฌผํ ์ด ๊ฒฐ์ ๊ธ์ก์ ์ค์๊ฐ ๊ณ์ฐํ์ฌ ์ฐ์ธก ํ๋จ ์์์ฆ์ ๋ณด์ฌ์ค ๋.
โ ์ ๋ต: C
๐ก ์์ธ ํด์ค: ๋ ๋๋ง ํธ๋ฆฌ๊ฑฐ ์ฌ๋ถ๋ง ๊ตฌ์ํ ์ค ์๋ฉด ๋ฉ๋๋ค! A์ ๊ฒ์์ด, B์ ๋ชจ๋ฌ T/F, D์ ์นดํธ ๊ฒฐ์ ์ก ์ซ์๋ ์ ๋ถ "๊ฐ์ด ํ ๋ฒ์ด๋ผ๋ ๋ฐ๋๋ฉด ํ๋ฉด์ ํฝ์
UI๊ฐ ์ ์ ๋์์์ ์ฆ์์ฆ์ ๋ณ๊ฒฝ๋์ด์ผ ํ๋" UI ์ง๊ฒฐํ ๋ฐ์ดํฐ์ด๋ฏ๋ก ๋ฌด์กฐ๊ฑด useState์ ์์ญ์
๋๋ค.
๋ฐ๋ฉด C์ ํ์ด๋จธ ์์ด๋๋ ๋จ์ ์ ์ ์ซ์(1, 2, 3...)์ผ ๋ฟ ๋ธ๋ผ์ฐ์ DOM ์ด๋์๋ ์ถ๋ ฅ๋ ์ผ์ด ์์ผ๋ฉฐ, ์ค์ง ํด๋ฆฐ์
์ clearTimeout(ID) ์ฒ๋ฆฌ ๋ก์ง์ ํต์ ํ๊ธฐ ๋ท๊ตฌ๋ฉ ๋ฐ์ดํฐ์ด๋ฏ๋ก ๋ฆฌ์กํธ ์์ง์ ์๋น(๋ฆฌ๋ ๋๋ง ๋ถ๋ด)๋ฅผ ๊ฑธ ํ์๊ฐ 1๋ ์๋ useRef์ ์ต์ ๋ฌด๋์
๋๋ค.
Q2. ๋ค์ ์ค ์์ฒ ์ด๊ฐ ์ง useRef ์กฐ์์ ๋ํด, ๋ฆฌ์กํธ ํต์ฌ ํ ๋๋ฃ๊ฐ ๊ฐ์ฅ ๊ฒฝ์
(Horrify)ํ๊ณ ์ฝ๋ ๋ฆฌ๋ทฐ ์ ๋ฐ๋ก ๋น ๊พธ(Reject)๋ฅผ ๋จน์ผ ์น๋ช
์ ํจํด์ ๋ฌด์์ธ๊ฐ์?
- A)
<input ref={myInputRef} />ํํ๋ก DOM ์์์ ์ง์ ๊ฐ๊ณ ๋ฆฌ๋ฅผ ๋์ง ๊ฒ. - B)
useEffect์ธ๋ถ ํด๋ฆฐ์ ๊ณต๊ฐ์์myRef.current = null๋ก ์ด๊ธฐํํ ๊ฒ. - C)
<div>๋ด ๋น๋ฐ ๊ธ๊ณ : {secretRef.current}</div>ํํ๋ก JSX ๋ ๋๋ง ๋ฐํ ๊ณต๊ฐ์์ ๋ณ์๋ฅผ ๋ฐ์๋ ๊ฒ. - D) ์ธ๋ถ ํ๊ฒฝ์
const initial = 'abc'๋ฅผ ๋นผ๋๊ณuseRef(initial)๋ก ๊ฐ์ ์ด๊ธฐ ์ธํ ํ ๊ฒ.
โ ์ ๋ต: C
๐ก ์์ธ ํด์ค: ์ ๋ ๊ธ๊ธฐ์ฌํญ(Antipattern)์
๋๋ค! useRef๋ ํ์๋ถํฐ "๋ฆฌ์กํธ์ ํต์ ๋ฐ(๋ ๋๋ง ํธ๋ฆฌ๊ฑฐ ๊ธฐ๋ฅ ๊ฑฐ์ธ๋จ)"์ ์กด์ฌํ๋ ๋น๋ฐ ์์์ธ๋ฐ, ์ด๊ฑธ ์ต์ง๋ก ํ๋ฉด์ ๊ทธ๋ ค๋ฌ๋ผ๊ณ ๋๊ฒจ์ฃผ๋ฉด ๊ฐ๋ฐ์์ ํ๋ ์์ํฌ ๊ฐ์ ์ ๋ขฐ๊ฐ ๋ฐ์ด๋ฉ๋๋ค. ๊ฐ์ ๋ฐฑ๋ ์ฒ๋ ๋ค์์ ๋ชฐ๋ ๋ฐ๊ฟ๋ดค์ ๋ฆฌ์กํธ๋ ๋ฆฌ๋ ๋๋งํด์ฃผ์ง ์์ผ๋ฏ๋ก ์ฌ์ฉ์๋ ๋ก์ ํ๋ฉด์ ๋ณด๊ฒ ๋๋ฉฐ, ์ปดํฌ๋ํธ์ ์๋ช
์ฃผ๊ธฐ๋ฅผ ์๋ฒฝํ ํผ๋์ ๋น ๋จ๋ฆฌ๋ ๋ฒ๊ทธ ๋จธ์ ์ ๋ณ๊ฒ ๋ฉ๋๋ค. (A๋ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ, B์ D๋ ์ ์ ์ฌ์ฉ๋ฒ).
Q3. ์ฃผ๊ด์ ๋
ผ์ : useRef๊ฐ ์ปดํฌ๋ํธ์ ๋ ๋๋ง ํ์(์ฌ์คํ)์ ๊ด๊ณ์์ด ์ด๋ป๊ฒ ํญ์ "๋จ ํ๋์ ์จ์ ํ ํต(๋ฐ์ค)"์ ๊ธฐ์ตํ๊ณ ์๊ตฌ ๋ถ๋ณํ๊ฒ ์ ์ฅํ๋ ๊ตฌ์กฐ๋ฅผ ๋ฆฌ์กํธ ๋ด๋ถ์์ ํ๋ด(๊ตฌํ) ๋ด์์์ง, useState ๊ฐ๋
์ ๋น๋์ด ๊ทธ ๋น๋ฐ์ ์๋ ์๋ฆฌ๋ฅผ ์์ ํ์์ค.
โ ์ ๋ต ๋ฐ ์ฃผ๊ด์ ํด์ค:
๋ด๋ถ ์๋ ์๋ฆฌ: ๋ฆฌ์กํธ์ useRef๋ ์ฌ์ค ์ธ๊ณ ๊ธฐ์ ์ด ์๋๋๋ค. ์ด๋์ ๋ด๋ถ๋ ์ฒ ์ ํ๊ฒ useState์ ๋๊ฐ์ด "์ด๊ธฐ๊ฐ ์ ์ฅ ๋ก์ง"์ ๊ธฐ๋ฐ์ผ๋ก ๊น๊ณ ์์ต๋๋ค. ์์ค์ฝ๋ ๋ด๋ถ๋ฅผ ์ด์ด๋ณด๋ฉด ๋๋ต useState({ current: initialValue })[0] ์ฝ๋๋ฅผ ๋์ ธ์ฃผ๋ ๊ฒ๊ณผ ๋งค์ปค๋์ฆ์ด ์์ ํ ๋๊ฐ์ฃ .
๊ฐ์ฅ ํฐ ํต์ฌ์ **"์ํ๋ฅผ ๋ฐ๊ตฌ๋({ current: ... }์ธ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด) ๊ป๋ฐ๊ธฐ์ ๊ฐ์ธ์ ๋จ ํ ๋ฒ ๋๊ฒจ์ฃผ๊ณ ๋, ๊ทธ ์ํ๋ฅผ ๋ณ๊ฒฝ์ํค๋ ๋ฐฉ๋ฒ์ธ Setter ํจ์(setState)๋ฅผ ์ธ๋ถ ์ธ๊ณ(๊ฐ๋ฐ์)์ ์ ๋ ๋
ธ์ถ ์ ๊ณตํ์ง ์๋๋ค"**๋ ๊ฒ์
๋๋ค.
๊ฒฐ๊ตญ ๊ฐ๋ฐ์๋ ์ด ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด(Object)์ "์ฃผ์(Reference)" ํ๋๋ง ํ์ ๊ณต์ ๋ฐ์ผ๋ฉฐ, ๊ทธ ์ฃผ์ ์์ ๋ด์ฉ๋ฌผ(Property)์ธ current๋ง ์ฃผ๊ตฌ์ฅ์ฐฝ ์ง์ ์ค์
์ ๋ณ์น ์กฐ์ํ๊ฒ ๋ฉ๋๋ค. ๊ฐ์ฒด ์ฃผ์๋ ๋ง๋
๊ฐ์ผ๋ฏ๋ก ๋ฆฌ์กํธ๋ ์์ํ ๋ฆฌ๋ ๋๋ง์ ์ผ์ผํค์ง ์๊ณ , ๋ด์ฉ๋ฌผ์ ๋ฌด์ฌํ ์ด์๋จ๋ ์๋ฒฝํ ํ์ถ๊ตฌ๊ฐ ๋๋ ๊ฒ์ด์ฃ .