React์ forwardRef๋ฅผ ๋ง์คํฐํ์ธ์: ๋ ํผ๋ฐ์ค ํฌ์๋ฉ์ ์ดํดํ๊ณ , ์์ ์ปดํฌ๋ํธ์ DOM ๋ ธ๋์ ์ ๊ทผํ๋ฉฐ, ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ๊ณ , ์ฝ๋ ์ ์ง๋ณด์์ฑ์ ํฅ์์ํค์ธ์.
React forwardRef: ๋ ํผ๋ฐ์ค ํฌ์๋ฉ์ ๋ํ ์ข ํฉ ๊ฐ์ด๋
React์์ ์์ ์ปดํฌ๋ํธ์ DOM ๋
ธ๋์ ์ง์ ์ ๊ทผํ๋ ๊ฒ์ ์ด๋ ค์ธ ์ ์์ต๋๋ค. ์ด๋ด ๋ forwardRef๊ฐ ๋ฑ์ฅํ์ฌ, ref๋ฅผ ์์ ์ปดํฌ๋ํธ๋ก ํฌ์๋ฉํ๋ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค. ์ด ๊ธ์ forwardRef์ ๋ํด ์ฌ์ธต์ ์ผ๋ก ๋ค๋ฃจ๋ฉฐ, ๊ทธ ๋ชฉ์ , ์ฌ์ฉ๋ฒ ๋ฐ ์ด์ ์ ์ค๋ช
ํ๊ณ , React ํ๋ก์ ํธ์์ ์ด๋ฅผ ํจ๊ณผ์ ์ผ๋ก ํ์ฉํ ์ ์๋ ์ง์์ ์ ๊ณตํฉ๋๋ค.
forwardRef๋ ๋ฌด์์ธ๊ฐ์?
forwardRef๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ์์ ์ปดํฌ๋ํธ ๋ด์ DOM ๋
ธ๋์ ๋ํ ref๋ฅผ ๋ฐ์ ์ ์๋๋ก ํ๋ React API์
๋๋ค. forwardRef๊ฐ ์์ผ๋ฉด, ref๋ ์ผ๋ฐ์ ์ผ๋ก ์์ฑ๋ ์ปดํฌ๋ํธ์ ํ์ ๋ฉ๋๋ค. ์ด๋ฌํ ์ ํ์ ๋ถ๋ชจ๊ฐ ์์ ์ปดํฌ๋ํธ์ ๊ธฐ๋ณธ DOM๊ณผ ์ง์ ์ํธ์์ฉํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
์ด๋ ๊ฒ ์๊ฐํด ๋ณด์ธ์: ์ฌ์ฉ์ ์ ์ ์
๋ ฅ ์ปดํฌ๋ํธ๊ฐ ์๊ณ , ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ๋ ์
๋ ฅ ํ๋๋ฅผ ์๋์ผ๋ก ํฌ์ปค์คํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํด ๋ด
์๋ค. forwardRef ์์ด๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ์
๋ ฅ ํ๋์ DOM ๋
ธ๋์ ์ง์ ์ ๊ทผํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. forwardRef๋ฅผ ์ฌ์ฉํ๋ฉด ๋ถ๋ชจ๋ ์
๋ ฅ ํ๋์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ ์งํ๊ณ ๊ทธ ์์ focus() ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
forwardRef๋ฅผ ์ฌ์ฉํ๋ ์ด์ ?
๋ค์์ forwardRef๊ฐ ๋งค์ฐ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋ ์ผ๋ฐ์ ์ธ ์๋๋ฆฌ์ค์
๋๋ค:
- ์์ DOM ๋ ธ๋ ์ ๊ทผ: ์ด๊ฒ์ด ์ฃผ์ ์ฌ์ฉ ์ฌ๋ก์ ๋๋ค. ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ ์์ ๋ด์ DOM ๋ ธ๋๋ฅผ ์ง์ ์กฐ์ํ๊ฑฐ๋ ์ํธ์์ฉํ ์ ์์ต๋๋ค.
- ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ ์์ฑ: ref๋ฅผ ํฌ์๋ฉํจ์ผ๋ก์จ, ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ๋ฌ ๋ถ๋ถ์ ์ฝ๊ฒ ํตํฉ๋ ์ ์๋ ๋์ฑ ์ ์ฐํ๊ณ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
- ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํตํฉ: ์ผ๋ถ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ DOM ๋
ธ๋์ ์ง์ ์ ๊ทผํด์ผ ํฉ๋๋ค.
forwardRef๋ ์ด๋ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ React ์ปดํฌ๋ํธ์ ์ํํ๊ฒ ํตํฉํ ์ ์๋๋ก ํฉ๋๋ค. - ํฌ์ปค์ค ๋ฐ ์ ํ ๊ด๋ฆฌ: ์์ ์ค๋ช
ํ๋ฏ์ด, ๋ณต์กํ ์ปดํฌ๋ํธ ๊ณ์ธต ๋ด์์ ํฌ์ปค์ค ๋ฐ ์ ํ์ ๊ด๋ฆฌํ๋ ๊ฒ์ด
forwardRef๋ฅผ ์ฌ์ฉํ๋ฉด ํจ์ฌ ๊ฐ๋จํด์ง๋๋ค.
forwardRef ์๋ ๋ฐฉ์
forwardRef๋ ๊ณ ์ฐจ ์ปดํฌ๋ํธ(HOC)์
๋๋ค. ๋ ๋๋ง ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์ React ์ปดํฌ๋ํธ๋ฅผ ๋ฐํํฉ๋๋ค. ๋ ๋๋ง ํจ์๋ props์ ref๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค. ref ์ธ์๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ์ ๋ฌํ๋ ref์
๋๋ค. ๋ ๋๋ง ํจ์ ๋ด์์ ์ด ref๋ฅผ ์์ ์ปดํฌ๋ํธ ๋ด์ DOM ๋
ธ๋์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.
๊ธฐ๋ณธ ๊ตฌ๋ฌธ
forwardRef์ ๊ธฐ๋ณธ ๊ตฌ๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
const MyComponent = React.forwardRef((props, ref) => {
// Component logic here
return <div ref={ref}>...</div>;
});
์ด ๊ตฌ๋ฌธ์ ๋ถ์ํด ๋ด ์๋ค:
React.forwardRef(): ์ด๊ฒ์ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ธ๋ ํจ์์ ๋๋ค.(props, ref) => { ... }: ์ด๊ฒ์ ๋ ๋๋ง ํจ์์ ๋๋ค. ์ปดํฌ๋ํธ์ props์ ๋ถ๋ชจ๋ก๋ถํฐ ์ ๋ฌ๋ ref๋ฅผ ๋ฐ์ต๋๋ค.<div ref={ref}>...</div>: ์ฌ๊ธฐ๊ฐ ๋ง๋ฒ์ด ์ผ์ด๋๋ ๊ณณ์ ๋๋ค. ์์ ๋ref๋ฅผ ์ปดํฌ๋ํธ ๋ด์ DOM ๋ ธ๋์ ์ฐ๊ฒฐํฉ๋๋ค. ์ด DOM ๋ ธ๋๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ์ ๊ทผํ ์ ์๊ฒ ๋ฉ๋๋ค.
์ค์ฉ์ ์ธ ์์
forwardRef๊ฐ ์ค์ ์๋๋ฆฌ์ค์์ ์ด๋ป๊ฒ ์ฌ์ฉ๋ ์ ์๋์ง ๋ณด์ฌ์ฃผ๋ ๋ช ๊ฐ์ง ์ค์ฉ์ ์ธ ์์๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์์ 1: ์ ๋ ฅ ํ๋ ํฌ์ปค์ฑ
์ด ์์์์๋ ๋ง์ดํธ๋ ๋ ์ ๋ ฅ ํ๋๋ฅผ ์๋์ผ๋ก ํฌ์ปค์คํ๋ ์ฌ์ฉ์ ์ ์ ์ ๋ ฅ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ ๊ฒ์ ๋๋ค.
import React, { useRef, useEffect } from 'react';
const FancyInput = React.forwardRef((props, ref) => {
return (
<input ref={ref} type="text" className="fancy-input" {...props} />
);
});
function ParentComponent() {
const inputRef = useRef(null);
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);
return (
<FancyInput ref={inputRef} placeholder="Focus me!" />
);
}
export default ParentComponent;
์ค๋ช :
FancyInput์React.forwardRef๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ๋ฉ๋๋ค.props์ref๋ฅผ ๋ฐ์ต๋๋ค.ref๋<input>์์์ ์ฐ๊ฒฐ๋ฉ๋๋ค.ParentComponent๋useRef๋ฅผ ์ฌ์ฉํ์ฌref๋ฅผ ์์ฑํฉ๋๋ค.ref๋FancyInput์ผ๋ก ์ ๋ฌ๋ฉ๋๋ค.useEffectํ ์์ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ๋ ์ ๋ ฅ ํ๋๊ฐ ํฌ์ปค์ค๋ฉ๋๋ค.
์์ 2: ํฌ์ปค์ค ๊ด๋ฆฌ ๊ธฐ๋ฅ์ด ์๋ ์ฌ์ฉ์ ์ ์ ๋ฒํผ
๋ถ๋ชจ๊ฐ ํฌ์ปค์ค๋ฅผ ์ ์ดํ ์ ์๋ ์ฌ์ฉ์ ์ ์ ๋ฒํผ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด ๋ด ์๋ค.
import React, { forwardRef } from 'react';
const MyButton = forwardRef((props, ref) => {
return (
<button ref={ref} className="my-button" {...props}>
{props.children}
</button>
);
});
function App() {
const buttonRef = React.useRef(null);
const focusButton = () => {
if (buttonRef.current) {
buttonRef.current.focus();
}
};
return (
<div>
<MyButton ref={buttonRef} onClick={() => alert('Button Clicked!')}>
Click Me
</MyButton>
<button onClick={focusButton}>Focus Button</button>
</div>
);
}
export default App;
์ค๋ช :
MyButton์forwardRef๋ฅผ ์ฌ์ฉํ์ฌ ref๋ฅผ ๋ฒํผ ์์๋ก ํฌ์๋ฉํฉ๋๋ค.- ๋ถ๋ชจ ์ปดํฌ๋ํธ(
App)๋useRef๋ฅผ ์ฌ์ฉํ์ฌ ref๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผMyButton์ ์ ๋ฌํฉ๋๋ค. focusButtonํจ์๋ ๋ถ๋ชจ๊ฐ ๋ฒํผ์ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ํฌ์ปค์คํ ์ ์๋๋ก ํฉ๋๋ค.
์์ 3: ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํตํฉ (์์: react-select)
๋ง์ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ธฐ๋ณธ DOM ๋
ธ๋์ ๋ํ ์ ๊ทผ์ ์๊ตฌํฉ๋๋ค. react-select๋ฅผ ์ฌ์ฉํ๋ ๊ฐ์์ ์๋๋ฆฌ์ค๋ฅผ ํตํด forwardRef๋ฅผ ํตํฉํ๋ ๋ฐฉ๋ฒ์ ์์ฐํด ๋ด
์๋ค. ์ด ์๋๋ฆฌ์ค์์๋ ์ ํ(select)์ ์
๋ ฅ ์์์ ์ ๊ทผํด์ผ ํ ์๋ ์์ต๋๋ค.
์ฐธ๊ณ : ์ด๊ฒ์ ๋จ์ํ๋ ๊ฐ์์ ์์์
๋๋ค. react-select ์ปดํฌ๋ํธ์ ์ ๊ทผํ๊ณ ์ฌ์ฉ์ ์ ์ํ๋ ๊ณต์์ ์ผ๋ก ์ง์๋๋ ๋ฐฉ๋ฒ์ ์ํด์๋ ์ค์ react-select ๋ฌธ์๋ฅผ ์ฐธ์กฐํ์ธ์.
import React, { useRef, useEffect } from 'react';
// Assuming a simplified react-select interface for demonstration
import Select from 'react-select'; // Replace with actual import
const CustomSelect = React.forwardRef((props, ref) => {
return (
<Select ref={ref} {...props} />
);
});
function MyComponent() {
const selectRef = useRef(null);
useEffect(() => {
// Hypothetical: Accessing the input element within react-select
if (selectRef.current && selectRef.current.inputRef) { // inputRef is a hypothetical prop
console.log('Input Element:', selectRef.current.inputRef.current);
}
}, []);
return (
<CustomSelect
ref={selectRef}
options={[
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' },
]}
/>
);
}
export default MyComponent;
์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ํ ์ค์ํ ๊ณ ๋ ค ์ฌํญ:
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฌธ์ ์ฐธ์กฐ: ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฌธ์๋ฅผ ํญ์ ํ์ธํ์ฌ ๋ด๋ถ ์ปดํฌ๋ํธ์ ์ ๊ทผํ๊ณ ์กฐ์ํ๋ ๊ถ์ฅ ๋ฐฉ๋ฒ์ ์ดํดํ์ญ์์ค. ๋ฌธ์ํ๋์ง ์๊ฑฐ๋ ์ง์๋์ง ์๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์๊ธฐ์น ์์ ๋์์ด๋ ํฅํ ๋ฒ์ ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
- ์ ๊ทผ์ฑ: DOM ๋ ธ๋์ ์ง์ ์ ๊ทผํ ๋๋ ์ ๊ทผ์ฑ ํ์ค์ ์ ์งํ๋์ง ํ์ธํ์ญ์์ค. ๋ณด์กฐ ๊ธฐ์ ์ ์์กดํ๋ ์ฌ์ฉ์๊ฐ ์ปดํฌ๋ํธ์ ์ํธ์์ฉํ ์ ์๋ ๋์ฒด ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ญ์์ค.
๋ชจ๋ฒ ์ฌ๋ก ๋ฐ ๊ณ ๋ ค ์ฌํญ
forwardRef๋ ๊ฐ๋ ฅํ ๋๊ตฌ์ด์ง๋ง, ์ ์คํ๊ฒ ์ฌ์ฉํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ๋ค์์ ์ผ๋์ ๋์ด์ผ ํ ๋ช ๊ฐ์ง ๋ชจ๋ฒ ์ฌ๋ก ๋ฐ ๊ณ ๋ ค ์ฌํญ์
๋๋ค:
- ๊ณผ๋ํ ์ฌ์ฉ ํผํ๊ธฐ: ๋ ๊ฐ๋จํ ๋์์ด ์๋ค๋ฉด
forwardRef๋ฅผ ์ฌ์ฉํ์ง ๋ง์ธ์. ์ปดํฌ๋ํธ ๊ฐ ํต์ ์๋ props ๋๋ ์ฝ๋ฐฑ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ณ ๋ คํด ๋ณด์ธ์.forwardRef๋ฅผ ๊ณผ๋ํ๊ฒ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ์ดํดํ๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. - ์บก์ํ ์ ์ง: ์บก์ํ๋ฅผ ๊นจ๋จ๋ฆฌ์ง ์๋๋ก ์ฃผ์ํ์ธ์. ์์ ์ปดํฌ๋ํธ์ DOM ๋ ธ๋๋ฅผ ์ง์ ์กฐ์ํ๋ฉด ์ฝ๋๊ฐ ๋ ์ทจ์ฝํด์ง๊ณ ๋ฆฌํฉํ ๋งํ๊ธฐ ์ด๋ ค์์ง ์ ์์ต๋๋ค. ์ง์ ์ ์ธ DOM ์กฐ์์ ์ต์ํํ๊ณ ๊ฐ๋ฅํ ํ ์ปดํฌ๋ํธ์ ๋ด๋ถ API์ ์์กดํ๋๋ก ๋ ธ๋ ฅํ์ธ์.
- ์ ๊ทผ์ฑ: ref ๋ฐ DOM ๋ ธ๋๋ฅผ ๋ค๋ฃฐ ๋๋ ํญ์ ์ ๊ทผ์ฑ์ ์ต์ฐ์ ์ผ๋ก ๊ณ ๋ คํ์ธ์. ์ปดํฌ๋ํธ๊ฐ ์ฅ์ ๊ฐ ์๋ ์ฌ๋๋ค๋ ์ฌ์ฉํ ์ ์๋์ง ํ์ธํ์ธ์. ์๋ฏธ๋ก ์ ์ธ HTML์ ์ฌ์ฉํ๊ณ , ์ ์ ํ ARIA ์์ฑ์ ์ ๊ณตํ๋ฉฐ, ๋ณด์กฐ ๊ธฐ์ ๋ก ์ปดํฌ๋ํธ๋ฅผ ํ ์คํธํ์ธ์.
- ์ปดํฌ๋ํธ ๋ผ์ดํ์ฌ์ดํด ์ดํด: ref๊ฐ ์ธ์ ์ฌ์ฉ ๊ฐ๋ฅํ์ง ์ธ์งํ์ธ์. ref๋ ์ผ๋ฐ์ ์ผ๋ก ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ํ์ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค. ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ํ ref์ ์ ๊ทผํ๋ ค๋ฉด
useEffect๋ฅผ ์ฌ์ฉํ์ธ์. - TypeScript์ ํจ๊ป ์ฌ์ฉ: TypeScript๋ฅผ ์ฌ์ฉํ๋ค๋ฉด, ref์
forwardRef๋ฅผ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ์ ํ์ ์ ์ ์ ํ๊ฒ ์ง์ ํด์ผ ํฉ๋๋ค. ์ด๋ ์ด๊ธฐ์ ์ค๋ฅ๋ฅผ ์ก๊ณ ์ฝ๋์ ์ ๋ฐ์ ์ธ ํ์ ์์ ์ฑ์ ํฅ์์ํค๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
forwardRef์ ๋์
์ด๋ค ๊ฒฝ์ฐ์๋ forwardRef๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ๋ ์ ์ ํ ์ ์๋ ๋์๋ค์ด ์์ต๋๋ค:
- Props ๋ฐ ์ฝ๋ฐฑ: props๋ฅผ ํตํด ๋ฐ์ดํฐ์ ๋์์ ์ ๋ฌํ๋ ๊ฒ์ ์ปดํฌ๋ํธ ๊ฐ์ ํต์ ํ๋ ๊ฐ์ฅ ๊ฐ๋จํ๊ณ ์ ํธ๋๋ ๋ฐฉ๋ฒ์ธ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์์์์ ๋ฐ์ดํฐ๋ง ์ ๋ฌํ๊ฑฐ๋ ํจ์๋ฅผ ํธ๋ฆฌ๊ฑฐํด์ผ ํ๋ ๊ฒฝ์ฐ, props์ ์ฝ๋ฐฑ์ด ์ผ๋ฐ์ ์ผ๋ก ์ต์ ์ ์ ํ์ ๋๋ค.
- Context: ๊น์ด ์ค์ฒฉ๋ ์ปดํฌ๋ํธ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํด์ผ ํ๋ ๊ฒฝ์ฐ, React์ Context API๊ฐ ์ข์ ๋์์ด ๋ ์ ์์ต๋๋ค. Context๋ฅผ ์ฌ์ฉํ๋ฉด ๋ชจ๋ ์์ค์์ ์๋์ผ๋ก props๋ฅผ ์ ๋ฌํ ํ์ ์์ด ์ ์ฒด ์ปดํฌ๋ํธ ์๋ธํธ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค.
- Imperative Handle:
useImperativeHandleํ ์forwardRef์ ํจ๊ป ์ฌ์ฉํ์ฌ ์ ์ฒด DOM ๋ ธ๋๋ฅผ ๋ ธ์ถํ๋ ๋์ ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ์ ํ์ ์ด๊ณ ์ ์ด๋ API๋ฅผ ๋ ธ์ถํ ์ ์์ต๋๋ค. ์ด๋ ๋ ๋์ ์บก์ํ๋ฅผ ์ ์งํฉ๋๋ค.
๊ณ ๊ธ ์ฌ์ฉ๋ฒ: useImperativeHandle
useImperativeHandle ํ
์ forwardRef๋ฅผ ์ฌ์ฉํ ๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ๋
ธ์ถ๋๋ ์ธ์คํด์ค ๊ฐ์ ์ฌ์ฉ์ ์ ์ํ ์ ์๋๋ก ํฉ๋๋ค. ์ด๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ์ ๊ทผํ ์ ์๋ ํญ๋ชฉ์ ๋ํ ๋ ๋ง์ ์ ์ด๋ฅผ ์ ๊ณตํ์ฌ ๋ ๋์ ์บก์ํ๋ฅผ ์ด์งํฉ๋๋ค.
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
const FancyInput = forwardRef((props, ref) => {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
getValue: () => {
return inputRef.current.value;
},
}));
return <input ref={inputRef} type="text" {...props} />;
});
function ParentComponent() {
const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current.focus();
};
const handleGetValue = () => {
alert(inputRef.current.getValue());
};
return (
<div>
<FancyInput ref={inputRef} placeholder="Enter text" />
<button onClick={handleFocus}>Focus Input</button>
<button onClick={handleGetValue}>Get Value</button>
</div>
);
}
export default ParentComponent;
์ค๋ช :
FancyInput์ปดํฌ๋ํธ๋useRef๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ ฅ ์์์ ๋ํ ๋ด๋ถ ref(inputRef)๋ฅผ ์์ฑํฉ๋๋ค.useImperativeHandle์ ํฌ์๋ฉ๋ ref๋ฅผ ํตํด ๋ถ๋ชจ ์ปดํฌ๋ํธ์ ๋ ธ์ถ๋ ์ฌ์ฉ์ ์ ์ ๊ฐ์ฒด๋ฅผ ์ ์ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ๊ฒฝ์ฐ,focusํจ์์getValueํจ์๋ฅผ ๋ ธ์ถํฉ๋๋ค.- ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ ref๋ฅผ ํตํด ์ด๋ฌํ ํจ์๋ฅผ ํธ์ถํ ์ ์์ผ๋ฉฐ, ์ ๋ ฅ ์์์ DOM ๋ ธ๋์ ์ง์ ์ ๊ทผํ ํ์๊ฐ ์์ต๋๋ค.
์ผ๋ฐ์ ์ธ ๋ฌธ์ ํด๊ฒฐ
๋ค์์ forwardRef๋ฅผ ์ฌ์ฉํ ๋ ๋ฐ์ํ ์ ์๋ ๋ช ๊ฐ์ง ์ผ๋ฐ์ ์ธ ๋ฌธ์ ์ ํด๊ฒฐ ๋ฐฉ๋ฒ์
๋๋ค:
- Ref๊ฐ null์ธ ๊ฒฝ์ฐ: ref๊ฐ ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ์ ๋๋ก ์ ๋ฌ๋์๋์ง, ์์ ์ปดํฌ๋ํธ๊ฐ ref๋ฅผ DOM ๋
ธ๋์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฐ๊ฒฐํ๋์ง ํ์ธํ์ธ์. ๋ํ, ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ํ(์:
useEffectํ ์์) ref์ ์ ๊ทผํ๊ณ ์๋์ง ํ์ธํ์ธ์. - 'focus' ์์ฑ์ null์์ ์ฝ์ ์ ์์: ์ด๋ ์ผ๋ฐ์ ์ผ๋ก ref๊ฐ DOM ๋ ธ๋์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฐ๊ฒฐ๋์ง ์์๊ฑฐ๋, DOM ๋ ธ๋๊ฐ ์์ง ๋ ๋๋ง๋์ง ์์์์ ๋ํ๋ ๋๋ค. ์ปดํฌ๋ํธ ๊ตฌ์กฐ๋ฅผ ๋ค์ ํ์ธํ๊ณ ref๊ฐ ์ฌ๋ฐ๋ฅธ ์์์ ์ฐ๊ฒฐ๋์๋์ง ํ์ธํ์ธ์.
- TypeScript์ ํ์
์ค๋ฅ: ref์ ํ์
์ด ์ฌ๋ฐ๋ฅด๊ฒ ์ง์ ๋์๋์ง ํ์ธํ์ธ์.
React.RefObject<HTMLInputElement>(๋๋ ์ ์ ํ HTML ์์ ํ์ )๋ฅผ ์ฌ์ฉํ์ฌ ref์ ํ์ ์ ์ ์ํ์ธ์. ๋ํ,forwardRef๋ฅผ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๊ฐReact.forwardRef<HTMLInputElement, Props>๋ก ์ฌ๋ฐ๋ฅด๊ฒ ํ์ ์ง์ ๋์๋์ง ํ์ธํ์ธ์. - ์์์น ๋ชปํ ๋์: ์์์น ๋ชปํ ๋์์ ๊ฒฝํํ๊ณ ์๋ค๋ฉด, ์ฝ๋๋ฅผ ์ฃผ์ ๊น๊ฒ ๊ฒํ ํ์ฌ React์ ๋ ๋๋ง ํ๋ก์ธ์ค๋ฅผ ๋ฐฉํดํ ์ ์๋ ๋ฐฉ์์ผ๋ก DOM์ ์ค์๋ก ์กฐ์ํ๊ณ ์์ง ์์์ง ํ์ธํ์ธ์. React DevTools๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ ํธ๋ฆฌ๋ฅผ ๊ฒ์ฌํ๊ณ ์ ์ฌ์ ์ธ ๋ฌธ์ ๋ฅผ ์๋ณํ์ธ์.
๊ฒฐ๋ก
forwardRef๋ React ๊ฐ๋ฐ์์ ๋ฌด๊ธฐ๊ณ ์ ์๋ ๊ท์คํ ๋๊ตฌ์
๋๋ค. ์ด๋ ๋ถ๋ชจ์ ์์ ์ปดํฌ๋ํธ ๊ฐ์ ๊ฐ๊ทน์ ๋ฉ์ ์ง์ ์ ์ธ DOM ์กฐ์์ ๊ฐ๋ฅํ๊ฒ ํ๊ณ ์ปดํฌ๋ํธ ์ฌ์ฌ์ฉ์ฑ์ ํฅ์์ํต๋๋ค. ๊ทธ ๋ชฉ์ , ์ฌ์ฉ๋ฒ ๋ฐ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ดํดํจ์ผ๋ก์จ forwardRef๋ฅผ ํ์ฉํ์ฌ ๋์ฑ ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ๋ฉฐ ์ ์ง๋ณด์ ๊ฐ๋ฅํ React ์ ํ๋ฆฌ์ผ์ด์
์ ๋ง๋ค ์ ์์ต๋๋ค. ์ ์คํ๊ฒ ์ฌ์ฉํ๊ณ , ์ ๊ทผ์ฑ์ ์ฐ์ ์ํ๋ฉฐ, ๊ฐ๋ฅํ ํ ํญ์ ์บก์ํ๋ฅผ ์ ์งํ๋๋ก ๋
ธ๋ ฅํ์ญ์์ค.
์ด ์ข
ํฉ ๊ฐ์ด๋๋ React ํ๋ก์ ํธ์์ forwardRef๋ฅผ ์์ ์๊ฒ ๊ตฌํํ ์ ์๋ ์ง์๊ณผ ์์๋ฅผ ์ ๊ณตํ์ต๋๋ค. ์ฆ๊ฑฐ์ด ์ฝ๋ฉ ๋์ธ์!