React의 createPortal은 컴포넌트를 현재의 React 컴포넌트 계층 구조와는 다른 DOM 트리에 렌더링할 수 있도록 해주는 강력한 API입니다.
기본적으로 React 컴포넌트는 부모 컴포넌트의 DOM 트리에 자식으로 렌더링됩니다. 하지만 모달, 툴팁, 알림과 같은 특정 UI 요소는 스타일 충돌과 z-index 문제를 피하기 위해 DOM 구조 밖에서 렌더링될 필요가 있습니다.
createPortal은 이러한 UI 요소를 React 컴포넌트 계층 구조를 유지하면서도 다른 DOM 노드에 렌더링할 수 있도록 도와줍니다.
ReactDOM.createPortal(child, container)
모달과 같은 컴포넌트는 부모 요소의 스타일(예: overflow: hidden)에 영향을 받을 수 있습니다. 별도의 DOM 노드에 렌더링하면 이러한 문제를 방지할 수 있습니다.
컴포넌트가 다른 DOM 트리에 렌더링되더라도 React의 상태와 이벤트 흐름은 정상적으로 유지됩니다.
createPortal을 사용하면 레이아웃과 스타일 제약 없이 UI 요소를 구축할 수 있어 더욱 매끄러운 사용자 경험을 제공합니다.
포털 내부에서 발생한 이벤트는 React 컴포넌트 트리를 통해 전파됩니다. 따라서 React의 이벤트 시스템이 방해받지 않습니다.
const Modal = ({ children }) => {
const modalRoot = document.getElementById('modal-root');
return ReactDOM.createPortal(
<div className="modal" onClick={() => console.log('Modal clicked')}>
{children}
</div>,
modalRoot
);
};
const App = () => (
<div onClick={() => console.log('App clicked')}>
<h1>React Portal Example</h1>
<Modal>
<button>Click Me</button>
</Modal>
</div>
);
출력:
중요한 메시지 표시나 사용자 입력을 받는 UI 요소.
부모 컨테이너 스타일의 제약 없이 컨텍스트 정보를 제공.
스크롤이나 부모 요소의 잘림(clipping) 문제 없이 동작하는 메뉴 구현.
전역적으로 표시되는 알림을 DOM의 루트에 렌더링.
import React, { useState } from "react";
import ReactDOM from "react-dom";
const Modal = ({ isOpen, onClose, children }) => {
if (!isOpen) return null;
const modalRoot = document.getElementById("modal-root");
return ReactDOM.createPortal(
<div className="modal-overlay" onClick={onClose}>
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
{children}
</div>
</div>,
modalRoot
);
};
const App = () => {
const [isModalOpen, setModalOpen] = useState(false);
return (
<div>
<h1>React `createPortal` Example</h1>
<button onClick={() => setModalOpen(true)}>Open Modal</button>
<Modal isOpen={isModalOpen} onClose={() => setModalOpen(false)}>
<h2>Modal Content</h2>
<button onClick={() => setModalOpen(false)}>Close</button>
</Modal>
</div>
);
};
export default App;
<div id="root"></div>
<div id="modal-root"></div>
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}
.modal-content {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
React의 createPortal은 모달, 툴팁, 알림과 같은 유연하고 강력한 UI 컴포넌트를 구현하는 데 필수적인 API입니다. 이를 통해 DOM 계층 구조의 제약 없이 컴포넌트를 렌더링하면서도 React의 상태 및 이벤트 관리를 유지할 수 있습니다.
createPortal의 사용법과 사례를 이해하고 적절히 활용하여, 사용성 높은 웹 애플리케이션을 개발해 보세요.