useRef
useRef
๋ ๋ ๋๋ง์ ํ์ํ์ง ์์ ๊ฐ์ ์ฐธ์กฐํ ์ ์๋ React Hook์
๋๋ค.
const ref = useRef(initialValue)
๋ ํผ๋ฐ์ค
useRef(initialValue)
์ปดํฌ๋ํธ์ ์ต์์ ๋ ๋ฒจ์์ useRef
๋ฅผ ํธ์ถํ์ฌ ref๋ฅผ ์ ์ธํฉ๋๋ค.
import { useRef } from 'react';
function MyComponent() {
const intervalRef = useRef(0);
const inputRef = useRef(null);
// ...
์๋์์ ๋ ๋ง์ ์์๋ฅผ ํ์ธํ์ธ์.
๋งค๊ฐ๋ณ์
initialValue
: ref ๊ฐ์ฒด์current
ํ๋กํผํฐ ์ด๊ธฐ ์ค์ ๊ฐ์ ๋๋ค. ์ฌ๊ธฐ์๋ ์ด๋ค ์ ํ์ ๊ฐ์ด๋ ์ง์ ํ ์ ์์ต๋๋ค. ์ด ์ธ์๋ ์ด๊ธฐ ๋ ๋๋ง ์ดํ๋ถํฐ๋ ๋ฌด์๋ฉ๋๋ค.
๋ฐํ๊ฐ
useRef
๋ ๋จ์ผ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค:
current
: ์ฒ์์๋ ์ ๋ฌํinitialValue
๋ก ์ค์ ๋ฉ๋๋ค. ๋์ค์ ๋ค๋ฅธ ๊ฐ์ผ๋ก ๋ฐ๊ฟ ์ ์์ต๋๋ค. ref ๊ฐ์ฒด๋ฅผ JSX ๋ ธ๋์ref
์ดํธ๋ฆฌ๋ทฐํธ๋ก React์ ์ ๋ฌํ๋ฉด React๋current
ํ๋กํผํฐ๋ฅผ ์ค์ ํฉ๋๋ค.
๋ค์ ๋ ๋๋ง์์ useRef
๋ ๋์ผํ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
์ฃผ์์ฌํญ
ref.current
ํ๋กํผํฐ๋ state์ ๋ฌ๋ฆฌ ๋ณ์ดํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ ๋๋ง์ ์ฌ์ฉ๋๋ ๊ฐ์ฒด(์: state์ ์ผ๋ถ)๋ฅผ ํฌํจํ๋ ๊ฒฝ์ฐ ํด๋น ๊ฐ์ฒด๋ฅผ ๋ณ์ดํด์๋ ์ ๋ฉ๋๋ค.ref.current
ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝํด๋ React๋ ์ปดํฌ๋ํธ๋ฅผ ๋ค์ ๋ ๋๋งํ์ง ์์ต๋๋ค. ref๋ ์ผ๋ฐ JavaScript ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ React๋ ์ฌ์ฉ์๊ฐ ์ธ์ ๋ณ๊ฒฝํ๋์ง ์์ง ๋ชปํฉ๋๋ค.- ์ด๊ธฐํ๋ฅผ ์ ์ธํ๊ณ ๋ ๋ ๋๋ง ์ค์
ref.current
๋ฅผ ์ฐ๊ฑฐ๋ ์ฝ์ง ๋ง์ธ์. ์ด๋ ๊ฒ ํ๋ฉด ์ปดํฌ๋ํธ์ ๋์์ ์์ธกํ ์ ์๊ฒ ๋ฉ๋๋ค. - Strict Mode์์ React๋ ์ปดํฌ๋ํธ ํจ์๋ฅผ ๋ ๋ฒ ํธ์ถํ์ฌ ์๋ํ์ง ์์ ๋ถ์๋ฌผ์ ์ฐพ์ ์ ์๋๋ก ๋์ต๋๋ค. ์ด๋ ๊ฐ๋ฐ ํ๊ฒฝ ์ ์ฉ ๋์์ด๋ฉฐ ์์ฉ ํ๊ฒฝ์๋ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค. ๊ฐ ref ๊ฐ์ฒด๋ ๋ ๋ฒ ์์ฑ๋๊ณ ๊ทธ์ค ํ๋๋ ๋ฒ๋ ค์ง๋๋ค. ์ปดํฌ๋ํธ ํจ์๊ฐ ์์ํ๋ค๋ฉด(๊ทธ๋์ผ๋ง ํฉ๋๋ค), ์ปดํฌ๋ํธ์ ๋ก์ง์ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค.
์ฌ์ฉ๋ฒ
ref๋ก ๊ฐ ์ฐธ์กฐํ๊ธฐ
์ปดํฌ๋ํธ์ ์ต์์ ๋ ๋ฒจ์์ useRef
๋ฅผ ํธ์ถํ์ฌ ํ๋ ์ด์์ ref๋ฅผ ์ ์ธํฉ๋๋ค.
import { useRef } from 'react';
function Stopwatch() {
const intervalRef = useRef(0);
// ...
useRef
๋ ์ฒ์์ ์ ๊ณตํ ์ด๊ธฐ๊ฐ์ผ๋ก ์ค์ ๋ ๋จ์ผ current
ํ๋กํผํฐ๊ฐ ์๋ ref ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
๋ค์ ๋ ๋๋ง์์ useRef
๋ ๋์ผํ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค. ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ๋์ค์ ์ฝ์ ์ ์๋๋ก current
์์ฑ์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. state๊ฐ ๋ ์ค๋ฅผ ์ ์์ง๋ง, ๋ ์ฌ์ด์๋ ์ค์ํ ์ฐจ์ด์ ์ด ์์ต๋๋ค.
ref๋ฅผ ๋ณ๊ฒฝํด๋ ๋ฆฌ๋ ๋๋ง์ ์ด๋ฐํ์ง ์์ต๋๋ค. ์ฆ ref๋ ์ปดํฌ๋ํธ์ ์๊ฐ์ ์ถ๋ ฅ์ ์ํฅ์ ๋ฏธ์น์ง ์๋ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ๋ฐ ์ ํฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด interval ID๋ฅผ ์ ์ฅํ๋ค๊ฐ ๋์ค์ ๋ถ๋ฌ์์ผ ํ๋ ๊ฒฝ์ฐ ref์ ๋ฃ์ ์ ์์ต๋๋ค. ref ๋ด๋ถ์ ๊ฐ์ ์
๋ฐ์ดํธํ๋ ค๋ฉด current
ํ๋กํผํฐ๋ฅผ ์๋์ผ๋ก ๋ณ๊ฒฝํด์ผ ํฉ๋๋ค:
function handleStartClick() {
const intervalId = setInterval(() => {
// ...
}, 1000);
intervalRef.current = intervalId;
}
๋์ค์ ref์์ ํด๋น interval ID๋ฅผ ์ฝ์ด ํด๋น interval์ ์ทจ์ํ ์ ์์ต๋๋ค:
function handleStopClick() {
const intervalId = intervalRef.current;
clearInterval(intervalId);
}
ref๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์์ ๋ณด์ฅํฉ๋๋ค:
- (๋ ๋๋งํ ๋๋ง๋ค ์ฌ์ค์ ๋๋ ์ผ๋ฐ ๋ณ์์ ๋ฌ๋ฆฌ) ๋ฆฌ๋ ๋๋ง ์ฌ์ด์ ์ ๋ณด๋ฅผ ์ ์ฅํ ์ ์์ต๋๋ค.
- (๋ฆฌ๋ ๋๋ง์ ์ด๋ฐํ๋ state ๋ณ์์ ๋ฌ๋ฆฌ) ๋ณ๊ฒฝํด๋ ๋ฆฌ๋ ๋๋ง์ ์ด๋ฐํ์ง ์์ต๋๋ค.
- (์ ๋ณด๊ฐ ๊ณต์ ๋๋ ์ธ๋ถ ๋ณ์์ ๋ฌ๋ฆฌ) ๊ฐ๊ฐ์ ์ปดํฌ๋ํธ์ ๋ก์ปฌ๋ก ์ ์ฅ๋ฉ๋๋ค.
ref๋ฅผ ๋ณ๊ฒฝํด๋ ๋ค์ ๋ ๋๋ง๋์ง ์์ผ๋ฏ๋ก ํ๋ฉด์ ํ์๋๋ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ๋ฐ๋ ref๊ฐ ์ ํฉํ์ง ์์ต๋๋ค. ๋์ state๋ฅผ ์ฌ์ฉํ์ธ์. ๋ ์์ธํ ๋ด์ฉ์ useRef
์ useState
์ค ์ ํํ๊ธฐ์์ ํ์ธํ์ธ์.
์์ 1 of 2: counter ํด๋ฆญํ๊ธฐ
์ด ์ปดํฌ๋ํธ๋ ref๋ฅผ ์ฌ์ฉํ์ฌ ๋ฒํผ์ด ํด๋ฆญ๋ ํ์๋ฅผ ์ถ์ ํฉ๋๋ค. ํด๋ฆญ ํ์๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ์์๋ง ์ฝ๊ณ ์ฐ๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์๋ state ๋์ ref๋ฅผ ์ฌ์ฉํด๋ ๊ด์ฐฎ์ต๋๋ค.
import { useRef } from 'react'; export default function Counter() { let ref = useRef(0); function handleClick() { ref.current = ref.current + 1; alert('You clicked ' + ref.current + ' times!'); } return ( <button onClick={handleClick}> Click me! </button> ); }
JSX์ {ref.current}
๋ฅผ ํ์ํ๋ฉด ํด๋ฆญ ์ ๋ฒํธ๊ฐ ์
๋ฐ์ดํธ๋์ง ์์ต๋๋ค. ref.current
๋ฅผ ์ค์ ํด๋ ๋ฆฌ๋ ๋๋ง์ ์ด๋ฐํ์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ ๋๋ง์ ์ฌ์ฉํ๋ ์ ๋ณด๋ ref๊ฐ ์๋ state์ฌ์ผ ํฉ๋๋ค.
ref๋ก DOM ์กฐ์ํ๊ธฐ
ref๋ฅผ ์ฌ์ฉํ์ฌ DOM์ ์กฐ์ํ๋ ๊ฒ์ ํนํ ์ผ๋ฐ์ ์ ๋๋ค. React์๋ ์ด๋ฅผ ์ํ ๊ธฐ๋ณธ ์ง์์ด ์์ต๋๋ค.
๋จผ์ ์ด๊ธฐ๊ฐ์ด null
์ธ ref ๊ฐ์ฒด๋ฅผ ์ ์ธํ์ธ์:
import { useRef } from 'react';
function MyComponent() {
const inputRef = useRef(null);
// ...
๊ทธ๋ฐ ๋ค์ ref ๊ฐ์ฒด๋ฅผ ref
์์ฑ์ผ๋ก ์กฐ์ํ๋ ค๋ DOM ๋
ธ๋์ JSX์ ์ ๋ฌํ์ธ์:
// ...
return <input ref={inputRef} />;
React๊ฐ DOM ๋
ธ๋๋ฅผ ์์ฑํ๊ณ ํ๋ฉด์ ๊ทธ๋ฆฐ ํ, React๋ ref ๊ฐ์ฒด์ current
ํ๋กํผํฐ๋ฅผ DOM ๋
ธ๋๋ก ์ค์ ํฉ๋๋ค. ์ด์ DOM ๋
ธ๋ <input>
์ ๊ทผํด focus()
์ ๊ฐ์ ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
function handleClick() {
inputRef.current.focus();
}
๋
ธ๋๊ฐ ํ๋ฉด์์ ์ ๊ฑฐ๋๋ฉด React๋ current
ํ๋กํผํฐ๋ฅผ ๋ค์ null
๋ก ์ค์ ํฉ๋๋ค.
์์ธํ ๋ด์ฉ์ ref๋ก DOM ์กฐ์ํ๊ธฐ์์ ์์๋ณด์ธ์.
์์ 1 of 4: ํ
์คํธ input์ ์ด์ ๋ง์ถ๊ธฐ
์ด ์์ ์์๋ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ ๋ ฅ์ ์ด์ ์ด ๋ง์ถฐ์ง๋๋ค:
import { useRef } from 'react'; export default function Form() { const inputRef = useRef(null); function handleClick() { inputRef.current.focus(); } return ( <> <input ref={inputRef} /> <button onClick={handleClick}> Focus the input </button> </> ); }
ref ์ฝํ ์ธ ์ฌ์์ฑ ํผํ๊ธฐ
React๋ ์ด๊ธฐ์ ref ๊ฐ์ ํ ๋ฒ ์ ์ฅํ๊ณ , ๋ค์ ๋ ๋๋ง๋ถํฐ๋ ์ด๋ฅผ ๋ฌด์ํฉ๋๋ค.
function Video() {
const playerRef = useRef(new VideoPlayer());
// ...
new VideoPlayer()
์ ๊ฒฐ๊ณผ๋ ์ด๊ธฐ ๋ ๋๋ง์๋ง ์ฌ์ฉ๋์ง๋ง, ํธ์ถ ์์ฒด๋ ์ดํ์ ๋ชจ๋ ๋ ๋๋ง์์๋ ์ฌ์ ํ ๊ณ์ ์ด๋ค์ง๋๋ค. ์ด๋ ๊ฐ๋น์ผ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒฝ์ฐ ๋ญ๋น์ผ ์ ์์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ๋์ ๋ค์๊ณผ ๊ฐ์ด ref๋ฅผ ์ด๊ธฐํํ ์ ์์ต๋๋ค:
function Video() {
const playerRef = useRef(null);
if (playerRef.current === null) {
playerRef.current = new VideoPlayer();
}
// ...
์ผ๋ฐ์ ์ผ๋ก ๋ ๋๋ง ์ค์ ref.current
๋ฅผ ์ฐ๊ฑฐ๋ ์ฝ๋ ๊ฒ์ ํ์ฉ๋์ง ์์ต๋๋ค. ํ์ง๋ง ์ด ๊ฒฝ์ฐ์๋ ๊ฒฐ๊ณผ๊ฐ ํญ์ ๋์ผํ๊ณ ์ด๊ธฐํ ์ค์๋ง ์กฐ๊ฑด์ด ์คํ๋๋ฏ๋ก ์ถฉ๋ถํ ์์ธกํ ์ ์์ผ๋ฏ๋ก ๊ด์ฐฎ์ต๋๋ค.
Deep Dive
ํ์
๊ฒ์ฌ๊ธฐ๋ฅผ ์ฌ์ฉํ๋ฉด์ ํญ์ null
์ ๊ฒ์ฌํ๊ณ ์ถ์ง ์๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ํจํด์ ๋์ ์ฌ์ฉํด ๋ณผ ์ ์์ต๋๋ค:
function Video() {
const playerRef = useRef(null);
function getPlayer() {
if (playerRef.current !== null) {
return playerRef.current;
}
const player = new VideoPlayer();
playerRef.current = player;
return player;
}
// ...
์ฌ๊ธฐ์ playerRef
์์ฒด๋ nullableํฉ๋๋ค. ํ์ง๋ง ํ์
๊ฒ์ฌ๊ธฐ์ getPlayer()
๊ฐ null
์ ๋ฐํํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค๋ ๊ฒ์ ํ์ ์ํฌ ์ ์์ด์ผ ํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ด๋ฒคํธ ํธ๋ค๋ฌ์์ getPlayer()
๋ฅผ ์ฌ์ฉํ์ญ์์ค.
๋ฌธ์ ํด๊ฒฐ
์ปค์คํ ์ปดํฌ๋ํธ์ ๋ํ ref๋ฅผ ์ป์ ์ ์์ต๋๋ค
์ปดํฌ๋ํธ์ ref
๋ฅผ ์ ๋ฌํ๊ณ ์ ๋ค์๊ณผ ๊ฐ์ด ํ๋ฉด:
const inputRef = useRef(null);
return <MyInput ref={inputRef} />;
๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒ์ ๋๋ค:
๊ธฐ๋ณธ์ ์ผ๋ก ์ปดํฌ๋ํธ๋ ๋ด๋ถ์ DOM ๋ ธ๋์ ๋ํ ref๋ฅผ ์ธ๋ถ๋ก ๋ ธ์ถํ์ง ์์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ref๋ฅผ ๊ฐ์ ธ์ค๊ณ ์ ํ๋ ์ปดํฌ๋ํธ๋ฅผ ์ฐพ์ผ์ธ์:
export default function MyInput({ value, onChange }) {
return (
<input
value={value}
onChange={onChange}
/>
);
}
๊ทธ๋ฐ ๋ค์ ์๋์ ๊ฐ์ด forwardRef
๋ก ๊ฐ์ธ์ธ์:
import { forwardRef } from 'react';
const MyInput = forwardRef(({ value, onChange }, ref) => {
return (
<input
value={value}
onChange={onChange}
ref={ref}
/>
);
});
export default MyInput;
๊ทธ๋ฌ๋ฉด ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ref๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
์์ธํ ๋ด์ฉ์ ๋ค๋ฅธ ์ปดํฌ๋ํธ์ DOM ๋ ธ๋์ ์ ๊ทผํ๊ธฐ์์ ํ์ธํ์ธ์.