๐ [Recat] React Refs(์ฐธ์กฐ) & Portals(ํฌํ) ํ์ฉ
![๐ [Recat] React Refs(์ฐธ์กฐ) & Portals(ํฌํ) ํ์ฉ](/assets/img/thumbnail/react-thumbnail.jpg)
[Recat] React Refs(์ฐธ์กฐ) & Portals(ํฌํ) ํ์ฉ
Refs(์ฐธ์กฐ)๋ก HTML ์์ ์ฐ๊ฒฐ ๋ฐ ์ ๊ทผ
useRef(์ฐธ์กฐ)๋ ๋ฌด์์ธ๊ฐ?
ref
๋ HTML ์์๋ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ์ ์ง์ ์ ๊ทผํ ์ ์๊ฒ ํด์ฃผ๋ ๋ฆฌ์กํธ์ ํน๋ณํ ๊ฐ ๊ฐ์ฒด์ ๋๋ค.state
์๋ ๋ค๋ฅด๊ฒref
๋ ๊ฐ์ด ๋ณ๊ฒฝ๋์ด๋ ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ๋ ๋๋งํ์ง ์์ต๋๋ค.useRef()
๋ฅผ ํตํด ์ฐธ์กฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์์ผ๋ฉฐ, ์ด ๊ฐ์ฒด๋.current
์์ฑ์ ๊ฐ์ง.
//refs ์์ฑ
const playerName = useRef();
// jsx์์์ ์ฐ๊ฒฐ
<input ref={playerName} />
// ์ฐธ์กฐ๊ฐ ์ฌ์ฉ current.value๋ฅผ ํตํด ์ฐ๊ฒฐ๋ input ์์์ ํ์ฌ ๊ฐ์ ์ ๊ทผ ๊ฐ๋ฅ
const handleClick = () => {
const enteredValue = playerName.current.value;
setEnteredPlayerName(enteredValue);
};
useRef
์ useState
์ ์ฐจ์ด์
ํญ๋ชฉ | state | ref |
---|---|---|
์ฉ๋ | ์ปดํฌ๋ํธ UI์ ์ง์ ์ํฅ์ ์ฃผ๋ ๊ฐ | DOM ์ ๊ทผ ๋๋ UI์ ๋ฌด๊ดํ ๋ด๋ถ ๊ฐ ์ ์ฅ |
๊ฐ ๋ณ๊ฒฝ ์ | ์ปดํฌ๋ํธ ์ฌ๋ ๋๋ง ๋ฐ์ | ์ปดํฌ๋ํธ ์ฌ๋ ๋๋ง ๋ฐ์ํ์ง ์์ |
์ ๊ทผ ์์ | ํญ์ ์ต์ ๊ฐ ๋ณด์ฅ | ์ด๊ธฐ ๋ ๋๋ง ์งํ์๋ ์ฐ๊ฒฐ๋์ง ์์ undefined ์ผ ์ ์์ |
์ฌ์ฉ ์์น | JSX ๋ด ์ํ ๊ด๋ฆฌ์ ์ฃผ๋ก ์ฌ์ฉ | DOM ์์ ์ฐธ์กฐ, ์์ ๊ฐ ์ ์ฅ ๋ฑ์ ์ฌ์ฉ |
ref๋ฅผ ์๋ชป ์ฌ์ฉํ ๊ฒฝ์ฐ ์๊ธฐ๋ ๋ฌธ์
const playerName = useRef();
console.log(playerName.current.value); // โ ์๋ฌ ๋ฐ์ ๊ฐ๋ฅ
- ์ปดํฌ๋ํธ ์ต์ด ๋ ๋๋ง ์์ ์๋
ref
์ฐ๊ฒฐ์ด ๋์ง ์์playerName.current
๋undefined
- ๋ฐ๋ผ์
playerName.current.value
์ ๊ทผ ์ ์๋ฌ ๋ฐ์
๋ฌธ์ ๊ฐ์
๊ฐ๊ฐ์ ํ์ด๋จธ๋ฅผ ์์ํ๋ค๊ฐ ์ค์งํ์์๋ ๋ถ๊ตฌํ๊ณ setTimeout()
์ ์คํ ๊ฒฐ๊ณผ๋ก "์ก์ต๋๋ค"
๊ฐ์ ๋ฉ์์ง๊ฐ ์ฌ์ ํ ์ถ๋ ฅ๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํจ. ์ด๋ ํ์ด๋จธ๋ฅผ ์ ์ฅํ ๋ณ์(timer) ๊ฐ ๊ฐ ์ปดํฌ๋ํธ ์ธ์คํด์ค๋ง๋ค ๊ณ ์ ํ์ง ์๊ธฐ ๋๋ฌธ.
let timer; // ์ปดํฌ๋ํธ ํจ์ ์ธ๋ถ์ ์์น
- ๋ฌธ์ : ์ด ๋ณ์๋ ๋ชจ๋ ์ปดํฌ๋ํธ ์ธ์คํด์ค ๊ฐ์ ๊ณต์ ๋จ
- A ์ธ์คํด์ค์์ ํ์ด๋จธ๋ฅผ ์ค์ ํ๊ณ B ์ธ์คํด์ค์์ ๋ค์ ์ค์ ํ๋ฉด, ๊ธฐ์กด A์ ํ์ด๋จธ ID๊ฐ ๋ฎ์ด์ฐ๊ธฐ๋จ
- ์ค์ง ์์ฒญ ์, ์ค๋ฅ๊ฐ ์๋ ํ์ด๋จธ ID๋ฅผ ์ค์งํ๊ฒ ๋์ด
"์ก์ต๋๋ค"
๋ฉ์์ง๊ฐ ๋ํ๋จ
const timer = useRef();
- ๊ฐ ์ปดํฌ๋ํธ ์ธ์คํด์ค๋ง๋ค ๋
๋ฆฝ์ ์ธ
ref
๋ฅผ ๊ฐ์ง useRef
๋ HTML ์์ ์ ๊ทผ๋ฟ ์๋๋ผ ์ํ๋ก ๊ด๋ฆฌํ๊ธฐ ๋ถ์ ์ ํ ๊ฐ ์ ์ฅ์๋ ์ ์ฉ- ์ปดํฌ๋ํธ๊ฐ ์ฌ์คํ๋์ด๋
ref
๊ฐ์ ์ ์ง๋๋ฉฐ, ์ปดํฌ๋ํธ ์ธ์คํด์ค๋ง๋ค ๊ณ ์ - ์ํ์ฒ๋ผ UI ๊ฐฑ์ ์ ์ ๋ํ์ง ์๊ณ , ๋ณ์์ฒ๋ผ ๋จ๊ธฐ ์ ์ฅ์ ์ญํ ์ ํจ
- ํ์ด๋จธ ID, ์ด์ ๊ฐ, ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ธ์คํด์ค ๋ฑ์ ๋ณด์กดํ ๋ ์ต์ ์ ์ ํ
์ปค์คํ ์ปดํฌ๋ํธ๋ก Refs(์ฐธ์กฐ) ์ ๋ฌ
๋ถ๋ชจ ์ปดํฌ๋ํธ(TimerChallenge
)์์ ์์ ์ปดํฌ๋ํธ(ResultModal
)์ <dialog>
DOM ์์์ ์ ๊ทผํ์ฌ showModal()
๋ฉ์๋๋ฅผ ํธ์ถํ๊ณ ์ถ์ ์ํฉ
๋ถ๋ชจ ์ปดํฌ๋ํธ (TimerChallenge
)์์ ref
์์ฑ
const dialog = useRef(); // dialog DOM ์ฐธ์กฐ์ฉ ref ์์ฑ
์์ ์ปดํฌ๋ํธ (ResultModal
)์ ref
์ ๋ฌ
<ResultModal ref={dialog} />
์์ ์ปดํฌ๋ํธ (ResultModal
)์์ ref
์ถ์ถ
function ResultModal({ ... }, ref) {
return <dialog ref={ref}>...</dialog>;
}
โ ์ฃผ์: ์ด ๋ฐฉ์์ ์ต์ React์์๋ง ์๋ํฉ๋๋ค (React 18 ์ด์, ํนํ React 19๋ถํฐ ๋ ๊ณต์ํ๋จ)
React ๊ตฌ๋ฒ์ (17 ์ดํ)
React๋ ์ผ๋ฐ์ ์ธ props๋ก๋ ref
๋ฅผ ์ง์ ์ ๋ฌ๋ฐ์ง ๋ชปํฉ๋๋ค. ์ด๋๋ ๋ค์์ฒ๋ผ ํด๊ฒฐํฉ๋๋ค.
forwardRef() ์ฌ์ฉ๋ฒ (React ๋ฒ์ ์ ์๊ด์์ด ์๋)
forwardRef()
๋ก ์์ ์ปดํฌ๋ํธ ๊ฐ์ธ๊ธฐ forwardRef
๋ ref
๋ฅผ ๋ ๋ฒ์งธ ์ธ์๋ก ์ปดํฌ๋ํธ์ ์ ๋ฌํจ
import React, { forwardRef } from "react";
const ResultModal = forwardRef(function ResultModal(props) {
return <dialog ref={ref}>...</dialog>;
},ref);
export default ResultModal;
ํฌํธ(Portal)์ด๋?
ํฌํธ์ JSX๋ก ์์ฑ๋ UI ์์๋ฅผ ํ์ฌ ์ปดํฌ๋ํธ ํธ๋ฆฌ ์ธ๋ถ์ DOM ๋ ธ๋์ ๋ ๋๋งํ ์ ์๋๋ก ํ๋ React์ ๊ธฐ๋ฅ์ ๋๋ค.
์ ํฌํธ์ ์ฌ์ฉํ๋์?
๊ธฐ์กด ๊ตฌ์กฐ์์๋ ๋ชจ๋ฌ(dialog) ๊ฐ์ UI ์์๊ฐ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ๋ ๋๋ง๋์ด, DOM ํธ๋ฆฌ์์ ๋ค๋ฅธ ์์๋ค๊ณผ ์ค์ฒฉ๋๊ฒ ๋ฉ๋๋ค. ์ด๋ฐ ๋ฐฉ์์ ๋ฌธ์ ์
- ์๊ฐ์ ์ผ๋ก๋ ๊ด์ฐฎ์ ๋ณด์ฌ๋,
- ์ค์ ๋ก๋ HTML ๊ตฌ์กฐ๊ฐ ์์ผ์ ์ ๊ทผ์ฑ ๋ฌธ์ ๋ฐ์ ๊ฐ๋ฅ
- CSS ์ถฉ๋์ด๋ z-index ๋ฌธ์ , ๋ ์ด์์ ๊นจ์ง ๋ฐ์ ๊ฐ๋ฅ์ฑ
- ๊น์ด ์ค์ฒฉ๋ ์์ ์์ ๋ชจ๋ฌ์ ์๋๋๋ก ๋์ํ์ง ์์ ์ ์์ โ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ชจ๋ฌ ๊ฐ์ UI ์์๋ฅผ body ๋ฐ๋ก ๋ฐ ๋ฑ ์ต์๋จ์ ๋ ๋๋งํ ์ ์๋๋ก ํฌํธ์ ์ฌ์ฉํจ
ํฌํธ ๊ตฌํ ๋ฐฉ๋ฒ
index.html์ ๋ชจ๋ฌ์ฉ DOM ๋ ธ๋ ์ถ๊ฐ
<!-- public/index.html -->
<body>
<div id="root"></div>
<div id="modal"></div> <!-- ํฌํธ ๋ ๋๋ง ์์น -->
</body>
React์์ ํฌํธ ๊ธฐ๋ฅ import
import { createPortal } from 'react-dom';
JSX๋ฅผ ํฌํธ๋ก ์ด๋
return createPortal(
<dialog>๋ชจ๋ฌ ๋ด์ฉ</dialog>,
document.getElementById('modal') // ๋ชจ๋ฌ div๋ก ์ด๋
);
- createPortal(JSX, DOM ์์)
- ์ฒซ ๋ฒ์งธ ์ธ์: ๋ ๋๋งํ UI
- ๋ ๋ฒ์งธ ์ธ์: ๋ ๋๋ง ์์น
- ์ฆ ํ๋ฉด์์๋ ๊ทธ๋๋ก, ์ฝ๋์ ๊ตฌ์กฐ๋ ๊ฐ์ ๋จ
๐ Reference
- ใํ๊ธ์๋งใ React ์๋ฒฝ ๊ฐ์ด๋ 2025 with React Router & Redux | Udemy
- ์ด๋ฏธ์ง ์ถ์ Freepik | ์ฌ์ธ์ AI ํฌ๋ฆฌ์์ดํฐ๋ธ ํด