Post

React Portal ์‚ฌ์šฉํ•˜๊ธฐ

๐Ÿ“Œ์‹œ์ž‘ํ•˜๋ฉฐ

์ตœ๊ทผ ๊ฐ•์˜๋ฅผ ์ˆ˜๊ฐ•ํ•˜๋ฉฐ ํ•™์Šต์šฉ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ ์ค‘์ด๋‹ค. ๊ฐ•์˜ ๋‚ด์šฉ ์ค‘์— React Portal์„ ์‚ฌ์šฉํ•ด Modal์„ ๋งŒ๋“œ๋Š” ๋ถ€๋ถ„์ด ๋‚˜์˜ค๋Š”๋ฐ, ํ•ด๋‹น ๊ธฐ๋Šฅ์˜ ์กด์žฌ๋Š” ์•Œ๊ณ ์žˆ์—ˆ์ง€๋งŒ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณด๋Š” ๊ฑด ์ฒ˜์Œ๋ผ์„œ, ๊ฐ•์˜ ๋‚ด์šฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์Šค์Šค๋กœ ํ•™์Šตํ•œ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•ด ์ •๋ฆฌํ•ด๋ณด๊ณ ์ž ํ•œ๋‹ค.

โœ…React Portal ์ด๋ž€

๊ณต์‹๋ฌธ์„œ์—์„œ๋Š” ์ด ๊ธฐ๋Šฅ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๋ช…ํ•œ๋‹ค.

Portal์€ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์˜ DOM ๊ณ„์ธต ๊ตฌ์กฐ ๋ฐ”๊นฅ์— ์žˆ๋Š” DOM ๋…ธ๋“œ๋กœ ์ž์‹์„ ๋ Œ๋”๋งํ•˜๋Š” ์ตœ๊ณ ์˜ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๊ธ€๋กœ๋งŒ ๋ณด๋ฉด ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šด๋ฐ, ์ฝ”๋“œ๋กœ ๋ณด๋ฉด ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๋‹ค. React์˜ index.htmlํŒŒ์ผ์„ ์‚ดํŽด๋ณด์ž. ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

1
2
3
4
<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>
</body>

๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“œ๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์€ <div id="root"></div>์˜ ์•ˆ์—์„œ ๋ Œ๋”๋ง ๋˜๊ฒŒ ๋œ๋‹ค. ํ•˜์ง€๋งŒ Portal์„ ์“ฐ๋ฉด ์ด ๋‚ด๋ถ€์—์„œ ๋ Œ๋”๋ง ๋˜๋Š”๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์™ธ๋ถ€ DOM ์š”์†Œ์— ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•์‹์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, Modal์„ ๋งŒ๋“ค ๋•Œ id=โ€™rootโ€™์š”์†Œ์— ์ž์œ ๋กœ์›Œ์ง€๋ฏ€๋กœ ๋‹ค๋ฅธ ์š”์†Œ๋“ค์˜ z-index๋‚˜ ๋ถ€๋ชจ ์š”์†Œ๋กœ๋ถ€ํ„ฐ์˜ ์Šคํƒ€์ผ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์•„, ํ›จ์”ฌ ํŽธ๋ฆฌํ•˜๊ฒŒ Modal์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>
  <div id="portal"></div>
</body>

โœ…React Portal ์‚ฌ์šฉํ•˜๊ธฐ

โžก๏ธ์™ธ๋ถ€ DOM์š”์†Œ ์ƒ์„ฑํ•˜๊ธฐ

๋จผ์ € index.html์— ์™ธ๋ถ€ DOM ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค.

1
2
3
4
5
<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>
  <div id="portal" ๐Ÿ‘ˆ></div>
</body>

โžก๏ธcreatePortal์„ ์‚ฌ์šฉํ•ด ๋ Œ๋”๋ง ํ•˜๊ธฐ

๐Ÿ’ŸcreatePortal์ด๋ž€?

createPortal(children, domNode, key?) portal์„ ์ƒ์„ฑํ•˜๋ ค๋ฉด createPortal์„ ํ˜ธ์ถœํ•˜๋ฉด ๋œ๋‹ค. createPortal์€ 2๊ฐ€์ง€ ์ธ์ž์™€ 1๊ฐ€์ง€ ์˜ต์…˜์„ ๊ฐ–๋Š”๋‹ค. |๊ฐ’|์„ค๋ช…| |โ€“|โ€“| |children|element, component ๋“ฑ React๋กœ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฒƒ| |domNode|document.getElementById()๋ฅผ ํ†ตํ•ด ์–ป์„ ์ˆ˜ ์žˆ๋Š” DOM ๋…ธ๋“œ.
์ฆ‰, ํ•ด๋‹น ๋…ธ๋“œ๋Š” ์ด๋ฏธ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค.
์—…๋ฐ์ดํŠธ ์ค‘์— ๋‹ค๋ฅธ DOM ๋…ธ๋“œ๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ํฌํ„ธ ์ฝ˜ํ…์ธ ๊ฐ€ ๋‹ค์‹œ ์ƒ์„ฑ๋œ๋‹ค.| |key(์˜ต์…˜)|ํฌํ„ธ์˜ ํ‚ค๋กœ ์‚ฌ์šฉํ•  ๊ณ ์œ ํ•œ ๋ฌธ์ž์—ด ๋˜๋Š” ์ˆซ์ž|

๐Ÿ’Ÿ์‚ฌ์šฉ์˜ˆ์ œ

์œ„์—์„œ index.html์— ์™ธ๋ถ€ DOM ์š”์†Œ์ธ <div id="portal" ๐Ÿ‘ˆ></div>๋ฅผ ์ƒ์„ฑํ•ด ๋‘์—ˆ์œผ๋ฏ€๋กœ, ์ด๊ฒƒ๊ณผ ํ•จ๊ป˜ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด ๋‘” Modal ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์‚ฌ์šฉํ•ด๋ณด์ž.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { createPortal } from "react-dom"
import MainContent from "@component/MainContent"
import Modal from "@component/Modal"

const modalDiv = document.getElementById("portal")

export default function App() {
  return (
    <>
      <MainContent />
      {createPortal(<Modal />, modalDiv)}
    </>
  )
}

์ถ”๊ฐ€์ ์œผ๋กœ, Modal์˜ ์—ด๊ณ  ๋‹ซ๋Š” ๊ฒƒ์„ ๊ด€๋ฆฌํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { createPortal } from "react-dom"
import MainContent from "@component/MainContent"
import Modal from "@component/Modal"

const modalDiv = document.getElementById("portal")

export default function App() {
  const [modalOpen, setModalOpen] = useState(false)

  const openModal = () => {
    setModalOpen(true)
  }

  const closeModal = () => {
    setModalOpen(false)
  }

  return (
    <>
      <MainContent />
      {modalOpen && createPortal(<Modal onClose={closeModal} />, modalDiv)}
    </>
  )
}

๐Ÿ“ฉ๋งˆ๋ฌด๋ฆฌ

์ด๋ ‡๊ฒŒ portal์„ ์ด์šฉํ•ด์„œ ๋ชจ๋‹ฌ์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ดค๋‹ค. ๊ด€๋ จ ๋‚ด์šฉ์„ ๊ฒ€์ƒ‰ํ•˜๋‹ค๊ฐ€ <dialog> ํƒœ๊ทธ๋ฅผ ์•Œ๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ ์ด๊ฑด ์ด์–ด์„œ ๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ ์ •๋ฆฌํ•˜๊ณ ์žํ•œ๋‹ค.

๐Ÿ—‚๏ธ์ฐธ๊ณ  ์‚ฌ์ดํŠธ

  • https://ko.legacy.reactjs.org/docs/portals.html
  • https://react.dev/reference/react-dom/createPortal
This post is licensed under CC BY 4.0 by the author.