본문 바로가기
Frontend/React

React: portal에 대해서

by 코딩쥐 2024. 8. 29.

Portal은 부모컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 방법이라고 소개한다. 즉, React 컴포넌트에서 DOM 트리 상에서의 위치를 변경할 수 있도록 하는 기능이다. 모달, 알림, 드롭다운 메뉴 등과 같은 컴포넌트를 독립적인 위치에서 렌더링 할 수 있으며 독립된 스타일링을 유지할 수 있다. 하지만 많이 사용하게 되면 코드의 난독화 및 성능 저하가 발생할 수도 있다.

  • ReactDom.createPortal(child, container) 
    - child : 엘리먼트, 문자열 혹은 fragment와 같은 렌더링 할 수 있는 React 자식요소
    - container : DOM 엘리먼트

 

Portal을 사용해 모달창 만들기

1. index.html에 모달 컴포넌트를 렌더링 할 DOM요소를 생성한다. 

<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Vite + React</title>
</head>

<body>
  <div>
    <div id="root"></div>
    <div id="modal-root"></div>
  </div>
  <script type="module" src="/src/main.jsx"></script>
</body>

</html>

 

2. Modal.jsx를 생성한다.

modalOpen이 true일 때, react portal 생성한다. <div>안에 <h1>과 <button>이 있는 React 자식을 "modal-root"라는 id를 가진 DOM 요소에 렌더링한다.

import { useState } from "react";
import ReactDOM from "react-dom";  // 올바른 이름으로 수정
import style from "./Modal.module.css";

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

    const handleOpenModal = () => {
        setModalOpen(true);
    };

    const handleCloseModal = () => {
        setModalOpen(false);
    };

    return (
        <>
            <p>아래 버튼 클릭 시에 모달창이 활성화됩니다.</p>
            <button onClick={handleOpenModal}>open</button>

            {modalOpen && ReactDOM.createPortal(
                <div className={style.modal}>
                    <h1>모달 오픈</h1>
                    <button onClick={handleCloseModal}>close</button>
                </div>,  
                document.getElementById("modal-root")
            )}
        </>
    );
}

 

<<Modal.module.css>>

더보기
.modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: white;
    padding: 50px;
}

리액트 포탈에 생성되지 않은 요소들은 index.html의 '#root'에 렌더링이 된 모습을 볼 수 있다. open 버튼을 클릭하게 되면 modalOpen이 true로 변경되면서 모달창이 렌더링된다.  

모달창의 렌더링이 '#modal-root'에 렌더링 된 모습을 볼 수 있다. 이렇게 DOM 트리 상에서의 위치를 리액트 포탈을 사용하여 변경할 수 있다.