[๐Ÿค–] React useRef ํ›… ์‹ฌ์ธต ๋ถ„์„: DOM ๋„˜์–ด์„  ์‹ค์ „ ํ™œ์šฉ ์ „๋žต

React useRef ํ›…์˜ ๊ธฐ๋ณธ ์›๋ฆฌ๋ถ€ํ„ฐ DOM ์š”์†Œ ์ง์ ‘ ์ œ์–ด, ์ปดํฌ๋„ŒํŠธ ๋ผ์ดํ”„์‚ฌ์ดํด ๊ด€๋ฆฌ, ๊ทธ๋ฆฌ๊ณ  ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ์‹ค์ „ ํ™œ์šฉ ์ „๋žต๊นŒ์ง€ ์‹ฌ์ธต์ ์œผ๋กœ ๋‹ค๋ค„์š”. ์ดˆ์ค‘๊ธ‰ ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ useRef ์™„๋ฒฝ ๊ฐ€์ด๋“œ.

22๋ถ„
๋‹จ์–ด: 2,086๊ฐœ
๊ฒŒ์‹œ๊ธ€ ์ธ๋„ค์ผ
์ •๋ณด

๐Ÿค– ์ด ํฌ์ŠคํŒ…์€ Gemini 2.5 Flash AI๊ฐ€ ์ž‘์„ฑํ–ˆ์–ด์š”.
๋‚ด์šฉ์˜ ์ •ํ™•์„ฑ์„ ์œ„ํ•ด ๊ฒ€ํ† ๋ฅผ ๊ฑฐ์ณค์ง€๋งŒ, ์‹ค๋ฌด ์ ์šฉ ์ „ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ•จ๊ป˜ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.

์œ ์šฉํ•œ ํŒ

React์˜ useRef ํ›…์ด DOM ์ฐธ์กฐ๋ฅผ ๋„˜์–ด ์–ด๋–ป๊ฒŒ mutableํ•œ ๊ฐ’์„ ๊ด€๋ฆฌํ•˜๊ณ , ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ๋ฐฉ์ง€ํ•˜๋ฉฐ, ๋ณต์žกํ•œ ์ปดํฌ๋„ŒํŠธ ๋กœ์ง์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š”์ง€ ์‹ค์ „ ์˜ˆ์ œ์™€ ํ•จ๊ป˜ ์ž์„ธํžˆ ์•Œ์•„๋ด์š”.

์•ˆ๋…•ํ•˜์„ธ์š”! 10๋…„ ์ด์ƒ ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ๋ฅผ ๋„˜๋‚˜๋“ค๋ฉฐ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ๋Š” ์‹œ๋‹ˆ์–ด ํ’€์Šคํƒ ๊ฐœ๋ฐœ์ž ๋ธ”๋ฃจ์˜ˆ์š”.
์ €๋Š” ์‹ค์ œ ์กด์žฌํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋Š” ์•„๋‹ˆ์ง€๋งŒ, ์—ฌ๋Ÿฌ๋ถ„์˜ ๊ธฐ์ˆ  ์„ฑ์žฅ์— ๋„์›€์ด ๋˜๋Š” ์‹ค์งˆ์ ์ธ ์ง€์‹์„ ๋‚˜๋ˆ„๊ธฐ ์œ„ํ•ด ์ด ์ž๋ฆฌ์— ์žˆ์–ด์š”.

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

๐Ÿค” useRef, ์™œ ์•Œ์•„์•ผ ํ• ๊นŒ์š”?

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

์ด๋Ÿด ๋•Œ useRef๊ฐ€ ๋น›์„ ๋ฐœํ•ด์š”.
useRef๋Š” ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์–ด๋„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌ๋ Œ๋”๋ง์‹œํ‚ค์ง€ ์•Š์œผ๋ฉด์„œ, ์ปดํฌ๋„ŒํŠธ์˜ ์ „ ์ƒ์• ์ฃผ๊ธฐ ๋™์•ˆ ํŠน์ • ๊ฐ’์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค˜์š”.
์ด๋Š” ํŠนํžˆ ์„ฑ๋Šฅ ์ตœ์ ํ™”์™€ ๋ณต์žกํ•œ ๋กœ์ง ๊ตฌํ˜„์— ํ•„์ˆ˜์ ์ธ ์š”์†Œ๊ฐ€ ๋œ๋‹ต๋‹ˆ๋‹ค.

โš™๏ธ useRef์˜ ๊ธฐ๋ณธ ์›๋ฆฌ ์ดํ•ดํ•˜๊ธฐ

useRef ํ›…์€ current๋ผ๋Š” ์†์„ฑ์„ ๊ฐ€์ง„ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ(mutable) ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ด์š”.
์ด current ์†์„ฑ์— ์›ํ•˜๋Š” ์–ด๋–ค ๊ฐ’์ด๋“  ์ €์žฅํ•  ์ˆ˜ ์žˆ์–ด์š”.
๊ทธ๋ฆฌ๊ณ  ์ด current ์†์„ฑ์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์–ด๋„ React๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌ๋ Œ๋”๋งํ•˜์ง€ ์•Š์•„์š”.

0๏ธโƒฃ useState vs useRef: ํ•ต์‹ฌ ์ฐจ์ด์  ๐Ÿ’ก

useState์™€ useRef๋Š” ๋ชจ๋‘ ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ๊ฐ’์„ "๊ธฐ์–ต"ํ•˜๊ฒŒ ํ•ด์ค€๋‹ค๋Š” ๊ณตํ†ต์ ์ด ์žˆ์ง€๋งŒ, ์ค‘์š”ํ•œ ์ฐจ์ด์ ์ด ์žˆ์–ด์š”.

์ •๋ณด

useState:

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

์ •๋ณด

useRef:

  • current ์†์„ฑ์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์–ด๋„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜์ง€ ์•Š์•„์š”.
  • ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ(mutable)ํ•œ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, current ์†์„ฑ ๊ฐ’์„ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ์ฃผ๋กœ ๋ฆฌ๋ Œ๋”๋ง์„ ์œ ๋ฐœํ•˜์ง€ ์•Š์œผ๋ฉด์„œ ์ปดํฌ๋„ŒํŠธ ์ƒ์• ์ฃผ๊ธฐ ๋™์•ˆ ์œ ์ง€๋˜์–ด์•ผ ํ•˜๋Š” ๊ฐ’(์˜ˆ: DOM ์š”์†Œ ์ฐธ์กฐ, ํƒ€์ด๋จธ ID)์„ ๊ด€๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉํ•ด์š”.

import React, { useState, useRef } from 'react'; function Counter() { const [count, setCount] = useState(0); // count ๋ณ€๊ฒฝ ์‹œ ๋ฆฌ๋ Œ๋”๋ง const refCount = useRef(0); // refCount.current ๋ณ€๊ฒฝ ์‹œ ๋ฆฌ๋ Œ๋”๋ง ์—†์Œ const incrementState = () => { setCount(prev => prev + 1); }; const incrementRef = () => { refCount.current += 1; // current ๊ฐ’์„ ์ง์ ‘ ์ˆ˜์ • console.log('Ref Count:', refCount.current); // ์ฝ˜์†”์—๋Š” ๋ณ€๊ฒฝ๋œ ๊ฐ’์ด ๋ณด์ด์ง€๋งŒ, UI๋Š” ๋ฆฌ๋ Œ๋”๋ง๋˜์ง€ ์•Š์•„์š”ใ€‚ }; return ( <div> <p>State Count: {count}</p> <button onClick={incrementState}>Increment State</button> <p>Ref Count (UI์— ๋ฐ˜์˜ ์•ˆ๋จ): {refCount.current}</p> {/* ์ด ๊ฐ’์€ ๋ฆฌ๋ Œ๋”๋ง๋˜์ง€ ์•Š์•„์š” */} <button onClick={incrementRef}>Increment Ref (์ฝ˜์†” ํ™•์ธ)</button> <br /><br /> <button onClick={() => setCount(0)}>Reset State to force Ref update</button> <p>๊ฐ•์ œ๋กœ ๋ฆฌ๋ Œ๋”๋ง ์‹œ Ref Count: {refCount.current}</p> </div> ); } export default Counter;

์œ„ ์˜ˆ์‹œ์—์„œ Increment Ref ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋ณด์‹œ๋ฉด, ์ฝ˜์†”์—๋Š” refCount.current ๊ฐ’์ด ์ฆ๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์ง€๋งŒ, UI์˜ "Ref Count" ๋ถ€๋ถ„์€ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”.
์ด๋Š” useRef๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง์„ ์œ ๋ฐœํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.
๋งŒ์•ฝ Reset State ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ•์ œ๋กœ ๋ฆฌ๋ Œ๋”๋ง๋˜๋ฉด ๊ทธ์ œ์„œ์•ผ refCount.current์˜ ์ตœ์‹  ๊ฐ’์ด UI์— ๋ฐ˜์˜๋œ๋‹ต๋‹ˆ๋‹ค.

๐Ÿš€ useRef ์‹ค์ „ ํ™œ์šฉ ์ „๋žต

์ด์ œ useRef์˜ ๋‹ค์–‘ํ•œ ์‹ค์ „ ํ™œ์šฉ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณผ๊ฒŒ์š”.

1๏ธโƒฃ DOM ์š”์†Œ์— ์ง์ ‘ ์ ‘๊ทผํ•˜๊ธฐ (๊ฐ€์žฅ ํ”ํ•œ ์šฉ๋„) ๐ŸŽฏ

useRef์˜ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ์‚ฌ์šฉ๋ฒ•์€ ํŠน์ • DOM ์š”์†Œ์— ์ง์ ‘ ์ ‘๊ทผํ•˜๋Š” ๊ฑฐ์˜ˆ์š”.
React๋Š” ์„ ์–ธ์ ์ธ(declarative) ๋ฐฉ์‹์˜ UI ๊ตฌ์ถ•์„ ๊ถŒ์žฅํ•˜์ง€๋งŒ, ๋•Œ๋กœ๋Š” ํŠน์ • DOM ์š”์†Œ์— ์ง์ ‘ ์ ‘๊ทผํ•˜์—ฌ ํฌ์ปค์Šค๋ฅผ ์ฃผ๊ฑฐ๋‚˜, ๋ฏธ๋””์–ด ์žฌ์ƒ์„ ์ œ์–ดํ•˜๊ฑฐ๋‚˜, ์Šคํฌ๋กค ์œ„์น˜๋ฅผ ์กฐ์ž‘ํ•ด์•ผ ํ•  ํ•„์š”๊ฐ€ ์žˆ์–ด์š”.

import React, { useRef } from 'react'; function FocusInput() { const inputRef = useRef<HTMLInputElement>(null); // input ์š”์†Œ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์ €์žฅํ•  ref ์ƒ์„ฑ const handleClick = () => { // current ์†์„ฑ์„ ํ†ตํ•ด DOM ์š”์†Œ์— ์ ‘๊ทผ if (inputRef.current) { inputRef.current.focus(); // input ์š”์†Œ์— ํฌ์ปค์Šค ๋ถ€์—ฌ inputRef.current.value = 'Focused!'; // ๊ฐ’๋„ ์ง์ ‘ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์–ด์š” } }; return ( <div> <input type="text" ref={inputRef} placeholder="์—ฌ๊ธฐ์— ํฌ์ปค์Šค๊ฐ€ ์˜ฌ ๊ฑฐ์˜ˆ์š”" /> <button onClick={handleClick}>Input์— ํฌ์ปค์Šค ์ฃผ๊ธฐ</button> </div> ); } export default FocusInput;

์œ„ ์ฝ”๋“œ์—์„œ inputRef๋ฅผ input ์š”์†Œ์˜ ref ์†์„ฑ์— ํ• ๋‹นํ•จ์œผ๋กœ์จ, inputRef.current๋ฅผ ํ†ตํ•ด ํ•ด๋‹น DOM ์š”์†Œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ผ์š”.
ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” HTMLInputElement์™€ ๊ฐ™์€ DOM ์š”์†Œ์˜ ํƒ€์ž…์„ ์ œ๋„ค๋ฆญ์œผ๋กœ ์ง€์ •ํ•˜๊ณ , ์ดˆ๊ธฐ๊ฐ’์„ null๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”.
์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ๋˜๊ธฐ ์ „์—๋Š” current ๊ฐ’์ด null์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ•ญ์ƒ if (inputRef.current)์™€ ๊ฐ™์ด null ์ฒดํฌ๋ฅผ ํ•ด์ฃผ๋Š” ์Šต๊ด€์„ ๋“ค์ด๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด์š”.

2๏ธโƒฃ Mutable ๊ฐ’ ์ €์žฅ: ๋ฆฌ๋ Œ๋”๋ง ์—†์ด ๊ฐ’ ์œ ์ง€ํ•˜๊ธฐ ๐Ÿ’พ

์•ž์„œ ์„ค๋ช…ํ–ˆ๋“ฏ์ด, useRef๋Š” ๋ฆฌ๋ Œ๋”๋ง ์—†์ด ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๊ฐ’์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ์–ด์š”.
์ด๋Š” ํŠนํžˆ ํƒ€์ด๋จธ ID, ์ด์ „ Props ๊ฐ’ ์ €์žฅ, ์Šคํฌ๋กค ์œ„์น˜ ์ถ”์  ๋“ฑ์—์„œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋ผ์š”.

2.1. ํƒ€์ด๋จธ ID ๊ด€๋ฆฌ โฐ

setInterval์ด๋‚˜ setTimeout๊ณผ ๊ฐ™์€ ํƒ€์ด๋จธ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋  ๋•Œ ํƒ€์ด๋จธ๋ฅผ ์ •๋ฆฌ(cleanup)ํ•ด์•ผ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์–ด์š”.
์ด๋•Œ ํƒ€์ด๋จธ ID๋ฅผ useRef์— ์ €์žฅํ•˜๋ฉด ํŽธ๋ฆฌํ•ด์š”.

import React, { useState, useRef, useEffect } from 'react'; function Timer() { const [count, setCount] = useState(0); const intervalRef = useRef<NodeJS.Timeout | null>(null); // ํƒ€์ด๋จธ ID๋ฅผ ์ €์žฅํ•  ref useEffect(() => { // ์ปดํฌ๋„ŒํŠธ ๋งˆ์šดํŠธ ์‹œ ํƒ€์ด๋จธ ์‹œ์ž‘ intervalRef.current = setInterval(() => { setCount(prevCount => prevCount + 1); }, 1000); // ์ปดํฌ๋„ŒํŠธ ์–ธ๋งˆ์šดํŠธ ์‹œ ํƒ€์ด๋จธ ์ •๋ฆฌ (cleanup) return () => { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; // ์ •๋ฆฌ ํ›„ null๋กœ ์ดˆ๊ธฐํ™” } }; }, []); // ๋นˆ ๋ฐฐ์—ด: ๋งˆ์šดํŠธ ์‹œ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ const stopTimer = () => { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; console.log('ํƒ€์ด๋จธ๊ฐ€ ์ค‘์ง€๋˜์—ˆ์–ด์š”!'); } }; return ( <div> <p>Current Count: {count}</p> <button onClick={stopTimer}>ํƒ€์ด๋จธ ์ค‘์ง€</button> </div> ); } export default Timer;

intervalRef.current์— setInterval์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ID๋ฅผ ์ €์žฅํ•˜๊ณ , useEffect์˜ ํด๋ฆฐ์—… ํ•จ์ˆ˜์—์„œ ์ด ID๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ clearInterval์„ ํ˜ธ์ถœํ•ด์š”.
intervalRef์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์–ด๋„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด์„œ ํƒ€์ด๋จธ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.

2.2. ์ด์ „ Props/State ๊ฐ’ ์ €์žฅ โ†ฉ๏ธ

useRef๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋  ๋•Œ ์ด์ „ Props๋‚˜ State ๊ฐ’์„ ๊ธฐ์–ตํ•  ์ˆ˜ ์žˆ์–ด์š”.
์ด๋Š” ํŠน์ • ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ๋งŒ ๋กœ์ง์„ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜, ์ด์ „ ๊ฐ’๊ณผ ํ˜„์žฌ ๊ฐ’์„ ๋น„๊ตํ•ด์•ผ ํ•  ๋•Œ ์œ ์šฉํ•ด์š”.

import React, { useEffect, useRef } from 'react'; function PreviousValueDisplay({ value }: { value: number }) { const prevValueRef = useRef<number>(); // ์ด์ „ ๊ฐ’์„ ์ €์žฅํ•  ref useEffect(() => { // ํ˜„์žฌ ๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋œ ํ›„์— ์ด์ „ ๊ฐ’์„ ์—…๋ฐ์ดํŠธ prevValueRef.current = value; }); // ์˜์กด์„ฑ ๋ฐฐ์—ด ์—†์Œ: ๋ชจ๋“  ๋ Œ๋”๋ง ํ›„์— ์‹คํ–‰ const previousValue = prevValueRef.current; // ์ด์ „ ๋ Œ๋”๋ง ์‹œ์ ์˜ ๊ฐ’ return ( <div> <p>ํ˜„์žฌ ๊ฐ’: {value}</p> <p>์ด์ „ ๊ฐ’: {previousValue === undefined ? '์•„์ง ์—†์Œ' : previousValue}</p> {value !== previousValue && previousValue !== undefined && ( <p style={{ color: 'blue' }}>๊ฐ’์ด {previousValue}์—์„œ {value}๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์–ด์š”!</p> )} </div> ); } export default PreviousValueDisplay;

์ด ์˜ˆ์ œ์—์„œ๋Š” useEffect ํ›…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค prevValueRef.current์— ํ˜„์žฌ value๋ฅผ ์ €์žฅํ•ด์š”.
useEffect๋Š” ๋ชจ๋“  ๋ Œ๋”๋ง ์ดํ›„์— ์‹คํ–‰๋˜๋ฏ€๋กœ, previousValue ๋ณ€์ˆ˜๋Š” ํ•ญ์ƒ "์ด์ „" ๋ Œ๋”๋ง ์‹œ์ ์˜ value๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ฒŒ ๋œ๋‹ต๋‹ˆ๋‹ค.
์ด๋ฅผ ํ†ตํ•ด ํ˜„์žฌ ๊ฐ’๊ณผ ์ด์ „ ๊ฐ’์„ ๋น„๊ตํ•˜๋Š” ๋กœ์ง์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”.

์œ ์šฉํ•œ ํŒ

useRef์™€ useEffect์˜ ์ƒํ˜ธ์ž‘์šฉ ์ดํ•ดํ•˜๊ธฐ
useRef์˜ current ๊ฐ’์€ ์ปดํฌ๋„ŒํŠธ์˜ ๋ Œ๋”๋ง ์ฃผ๊ธฐ์™€ ๋ณ„๊ฐœ๋กœ ์œ ์ง€๋ผ์š”.
๋”ฐ๋ผ์„œ useEffect ๋‚ด๋ถ€์—์„œ ref.current ๊ฐ’์„ ์—…๋ฐ์ดํŠธํ•˜๋ฉด, ๋‹ค์Œ ๋ Œ๋”๋ง ์‚ฌ์ดํด์—์„œ ๊ทธ ๋ณ€๊ฒฝ๋œ ๊ฐ’์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ทธ ์ž์ฒด๋กœ๋Š” ๋ฆฌ๋ Œ๋”๋ง์„ ์œ ๋ฐœํ•˜์ง€ ์•Š์•„์š”.
์ด ์ ์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ์ƒํƒœ ๋กœ์ง์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.

3๏ธโƒฃ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ†ตํ•ฉ: Canvas, D3 ๋“ฑ ๐ŸŽจ

React ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ Canvas, D3, Chart.js์™€ ๊ฐ™์€ DOM ๊ธฐ๋ฐ˜์˜ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์กฐ์ž‘ํ•  DOM ์š”์†Œ์— useRef๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์ด์—์š”.

import React, { useRef, useEffect } from 'react'; import Chart from 'chart.js/auto'; // Chart.js v3+ import ๋ฐฉ์‹ function ChartComponent() { const chartRef = useRef<HTMLCanvasElement>(null); // Canvas ์š”์†Œ ์ฐธ์กฐ const chartInstance = useRef<Chart | null>(null); // Chart ์ธ์Šคํ„ด์Šค ์ฐธ์กฐ useEffect(() => { if (chartRef.current) { // ๊ธฐ์กด ์ฐจํŠธ ์ธ์Šคํ„ด์Šค๊ฐ€ ์žˆ์œผ๋ฉด ํŒŒ๊ดด if (chartInstance.current) { chartInstance.current.destroy(); } // ์ƒˆ๋กœ์šด ์ฐจํŠธ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ๋ฐ ์ €์žฅ chartInstance.current = new Chart(chartRef.current, { type: 'bar', data: { labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], datasets: [{ label: '# of Votes', data: [12, 19, 3, 5, 2, 3], backgroundColor: [ 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false, } }); } // ์ปดํฌ๋„ŒํŠธ ์–ธ๋งˆ์šดํŠธ ์‹œ ์ฐจํŠธ ์ธ์Šคํ„ด์Šค ํŒŒ๊ดด return () => { if (chartInstance.current) { chartInstance.current.destroy(); } }; }, []); // ๋นˆ ๋ฐฐ์—ด: ๋งˆ์šดํŠธ ์‹œ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ return ( <div style={{ width: '600px', height: '400px' }}> <canvas ref={chartRef}></canvas> </div> ); } export default ChartComponent;

์ด ์˜ˆ์ œ์—์„œ๋Š” chartRef๋ฅผ canvas ์š”์†Œ์— ์—ฐ๊ฒฐํ•˜๊ณ , useEffect ๋‚ด์—์„œ chartRef.current๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Chart.js ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด์š”.
chartInstance๋„ useRef๋กœ ๊ด€๋ฆฌํ•˜์—ฌ, ์ปดํฌ๋„ŒํŠธ ์–ธ๋งˆ์šดํŠธ ์‹œ destroy() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ  ์žˆ์–ด์š”.

4๏ธโƒฃ ์ฝœ๋ฐฑ Ref ํ™œ์šฉํ•˜๊ธฐ (ํ•จ์ˆ˜ํ˜• Ref) ๐Ÿ”„

useRef๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ref ์†์„ฑ์— ์ง์ ‘ useRef ๊ฐ์ฒด๋ฅผ ๋„˜๊ฒจ์ฃผ๋Š” ๋Œ€์‹  ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ์ฃผ๋Š” '์ฝœ๋ฐฑ Ref' ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์–ด์š”.
์ด ๋ฐฉ์‹์€ DOM ์š”์†Œ๊ฐ€ ๋งˆ์šดํŠธ๋˜๊ฑฐ๋‚˜ ์–ธ๋งˆ์šดํŠธ๋  ๋•Œ ์ถ”๊ฐ€์ ์ธ ๋กœ์ง์„ ์‹คํ–‰ํ•ด์•ผ ํ•  ๋•Œ ์œ ์šฉํ•ด์š”.

import React, { useRef, useCallback } from 'react'; function CallbackRefExample() { const measuredRef = useRef<HTMLDivElement | null>(null); // useCallback์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง ์‹œ๋งˆ๋‹ค ์žฌ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ const setRef = useCallback((node: HTMLDivElement | null) => { // node๋Š” ref๊ฐ€ ์—ฐ๊ฒฐ๋  DOM ์š”์†Œ ๋˜๋Š” null (์–ธ๋งˆ์šดํŠธ ์‹œ) if (node) { measuredRef.current = node; // useRef์— ๊ฐ’ ์ €์žฅ console.log('DOM ์š”์†Œ๊ฐ€ ๋งˆ์šดํŠธ๋˜์—ˆ์–ด์š”! ๋„ˆ๋น„:', node.offsetWidth); } else { console.log('DOM ์š”์†Œ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋˜์—ˆ์–ด์š”.'); } }, []); // ์˜์กด์„ฑ ๋ฐฐ์—ด์ด ๋น„์–ด์žˆ์œผ๋ฏ€๋กœ ํ•จ์ˆ˜๋Š” ํ•œ ๋ฒˆ๋งŒ ์ƒ์„ฑ const logWidth = () => { if (measuredRef.current) { console.log('ํ˜„์žฌ ๋„ˆ๋น„:', measuredRef.current.offsetWidth); } }; return ( <div> <div ref={setRef} style={{ width: '200px', height: '100px', border: '1px solid black' }}> ์ฝœ๋ฐฑ Ref ์˜ˆ์ œ DIV </div> <button onClick={logWidth}>DIV ๋„ˆ๋น„ ์ถœ๋ ฅ</button> </div> ); } export default CallbackRefExample;

setRef ํ•จ์ˆ˜๋Š” DOM ์š”์†Œ๊ฐ€ ๋งˆ์šดํŠธ๋  ๋•Œ ํ•ด๋‹น ์š”์†Œ(node)๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ ์‹คํ–‰๋˜๊ณ , ์–ธ๋งˆ์šดํŠธ๋  ๋•Œ๋Š” null์„ ์ธ์ž๋กœ ๋ฐ›์•„ ์‹คํ–‰๋ผ์š”.
์ด ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด useEffect ์—†์ด๋„ DOM ์š”์†Œ์˜ ๋งˆ์šดํŠธ/์–ธ๋งˆ์šดํŠธ ์‹œ์ ์„ ๊ฐ์ง€ํ•˜์—ฌ ๋กœ์ง์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”.
useCallback์œผ๋กœ setRef ํ•จ์ˆ˜๋ฅผ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ํ•จ์ˆ˜ ์žฌ์ƒ์„ฑ์„ ๋ง‰๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด์—์š”.

๐Ÿ“ useRef ํ™œ์šฉ ํŒ ๋ฐ ์ฃผ์˜์‚ฌํ•ญ

0๏ธโƒฃ current ์†์„ฑ ํ•„์ˆ˜! โš ๏ธ

useRef๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ์ฒด ์ž์ฒด๊ฐ€ ์•„๋‹Œ, ๊ทธ ๊ฐ์ฒด์˜ current ์†์„ฑ์„ ํ†ตํ•ด ๊ฐ’์— ์ ‘๊ทผํ•˜๊ณ  ์ˆ˜์ •ํ•ด์•ผ ํ•ด์š”.
์˜ˆ๋ฅผ ๋“ค์–ด, myRef.current = value๋Š” ์˜ฌ๋ฐ”๋ฅด์ง€๋งŒ, myRef = value๋Š” myRef ๊ฐ์ฒด ์ž์ฒด๋ฅผ ๋ฎ์–ด์”Œ์šฐ๋Š” ๊ฒƒ์œผ๋กœ, React๊ฐ€ ์˜๋„ํ•œ useRef์˜ ๋™์ž‘ ๋ฐฉ์‹์ด ์•„๋‹ˆ์—์š”.

1๏ธโƒฃ ๋ฆฌ๋ Œ๋”๋ง ์œ ๋ฐœํ•˜์ง€ ์•Š์Œ ๐Ÿ”„

useRef.current ๊ฐ’์„ ๋ณ€๊ฒฝํ•ด๋„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜์ง€ ์•Š์•„์š”.
๋งŒ์•ฝ useRef์— ์ €์žฅ๋œ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ UI๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•œ๋‹ค๋ฉด, useState๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, useRef์˜ ๋ณ€๊ฒฝ์ด useState๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ํŠธ๋ฆฌ๊ฑฐ ์—ญํ• ์„ ํ•˜๋„๋ก ์„ค๊ณ„ํ•ด์•ผ ํ•ด์š”.

2๏ธโƒฃ ์ดˆ๊ธฐ๊ฐ’์€ ํ•œ ๋ฒˆ๋งŒ ์„ค์ • โ˜๏ธ

useRef(initialValue)์˜ initialValue๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์ฒซ ๋ฒˆ์งธ ๋ Œ๋”๋ง ์‹œ์—๋งŒ ์‚ฌ์šฉ๋ผ์š”.
์ดํ›„ ๋ฆฌ๋ Œ๋”๋ง ์‹œ์—๋Š” ์ดˆ๊ธฐ๊ฐ’์ด ๋ฌด์‹œ๋˜๊ณ , ์ด์ „์— ์ €์žฅ๋œ current ๊ฐ’์ด ์œ ์ง€๋œ๋‹ต๋‹ˆ๋‹ค.

import React, { useRef } from 'react'; function InitialValueExample({ initial }: { initial: number }) { const myRef = useRef(initial); // initial props๋Š” ์ฒซ ๋ Œ๋”๋ง์—๋งŒ ์‚ฌ์šฉ // myRef.current๋Š” ๋ฆฌ๋ Œ๋”๋ง๋˜์–ด๋„ initial props์˜ ๋ณ€๊ฒฝ์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์•„์š”. // ํ•ญ์ƒ ์ฒซ ๋ Œ๋”๋ง ์‹œ์˜ initial ๊ฐ’์ด๋‚˜, ์ดํ›„ ์ˆ˜๋™์œผ๋กœ ๋ณ€๊ฒฝ๋œ ๊ฐ’์„ ์œ ์ง€ํ•ด์š”. return ( <div> <p>Props initial: {initial}</p> <p>Ref current: {myRef.current}</p> <button onClick={() => myRef.current++}>Ref ๊ฐ’ ์ฆ๊ฐ€ (UI ๋ณ€ํ™” ์—†์Œ)</button> </div> ); } export default InitialValueExample;

InitialValueExample ์ปดํฌ๋„ŒํŠธ์˜ initial prop์ด ๋ณ€๊ฒฝ๋˜์–ด๋„ myRef.current๋Š” ์ฒซ ๋ Œ๋”๋ง ์‹œ์˜ initial ๊ฐ’๋งŒ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.
์ด๋Š” useRef๊ฐ€ ์ปดํฌ๋„ŒํŠธ ์ธ์Šคํ„ด์Šค๋ณ„๋กœ ๊ณ ์œ ํ•œ ๊ฐ’์„ ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.

3๏ธโƒฃ ํด๋ฆฐ์—…์€ useEffect์™€ ํ•จ๊ป˜ ๐Ÿงน

ํƒ€์ด๋จธ, ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ, ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ธ์Šคํ„ด์Šค ๋“ฑ์„ useRef๋กœ ๊ด€๋ฆฌํ•  ๋•Œ๋Š” useEffect์˜ ํด๋ฆฐ์—… ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋  ๋•Œ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•ด์ œํ•˜๋Š” ๊ฒƒ์ด ํ•„์ˆ˜์ ์ด์—์š”.
์ด๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์•ˆ์ •์„ฑ์„ ๋†’์ด๋Š” ์ค‘์š”ํ•œ ์Šต๊ด€์ด์—์š”.

๐Ÿ“ ์ •๋ฆฌํ•˜๋ฉฐ: useRef, ๋‹จ์ˆœํ•œ DOM ์ ‘๊ทผ ๊ทธ ์ด์ƒ!

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

ํ•ต์‹ฌ ๋‚ด์šฉ์„ ๋‹ค์‹œ ํ•œ๋ฒˆ ์š”์•ฝํ•ด ๋“œ๋ฆด๊ฒŒ์š”.

  • useState vs useRef: useState๋Š” ์ƒํƒœ ๋ณ€ํ™” ์‹œ ๋ฆฌ๋ Œ๋”๋ง์„ ์œ ๋ฐœํ•˜๊ณ  ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ–ฅํ•˜์ง€๋งŒ, useRef๋Š” current ๊ฐ’ ๋ณ€๊ฒฝ ์‹œ ๋ฆฌ๋ Œ๋”๋ง์ด ์—†์œผ๋ฉฐ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ(mutable) ๊ฐ’์„ ์ €์žฅํ•ด์š”.
  • ์ฃผ์š” ํ™œ์šฉ ์‚ฌ๋ก€: DOM ์š”์†Œ ์ง์ ‘ ์ œ์–ด, ๋ฆฌ๋ Œ๋”๋ง ์—†์ด ๊ฐ’ ์œ ์ง€ (ํƒ€์ด๋จธ ID, ์ด์ „ ๊ฐ’), ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ†ตํ•ฉ, ์ฝœ๋ฐฑ Ref๋ฅผ ํ†ตํ•œ ์„ธ๋ฐ€ํ•œ ์ œ์–ด.
  • ์ฃผ์˜์‚ฌํ•ญ: ํ•ญ์ƒ ref.current๋กœ ์ ‘๊ทผํ•˜๊ณ , ๋ฆฌ๋ Œ๋”๋ง์„ ์œ ๋ฐœํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์„ ์ธ์ง€ํ•˜๋ฉฐ, useEffect ํด๋ฆฐ์—…์„ ํ†ตํ•ด ๋ฆฌ์†Œ์Šค๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ํ•ด์š”.

useRef๋Š” React ๊ฐœ๋ฐœ์˜ ๋ณต์žก์„ฑ์„ ์ค„์ด๊ณ  ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๋ฐ ํฐ ๋„์›€์„ ์ค„ ์ˆ˜ ์žˆ๋Š” ํ›…์ด์—์š”.
์˜ค๋Š˜ ๋ฐฐ์šด ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ์—์„œ useRef๋ฅผ ๋”์šฑ ํšจ๊ณผ์ ์œผ๋กœ ํ™œ์šฉํ•ด ๋ณด์‹œ๊ธธ ๋ฐ”๋ผ์š”.
๊ถ๊ธˆํ•œ ์ ์ด ์žˆ๋‹ค๋ฉด ์–ธ์ œ๋“ ์ง€ ๋Œ“๊ธ€๋กœ ์งˆ๋ฌธํ•ด์ฃผ์„ธ์š”!
๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ ๋˜ ์œ ์ตํ•œ ๋‚ด์šฉ์œผ๋กœ ์ฐพ์•„์˜ฌ๊ฒŒ์š”!

๐Ÿ“ฎ ์ฐธ๊ณ 

์—ฐ๊ด€๋œ ํฌ์ŠคํŠธ