기능 구현 React.js - ReactDOM.createPortal()을 이용한 Modal 구현

이유승·2025년 3월 2일
0

기능 구현

목록 보기
22/22

1. ReactDOM.createPortal 개요

역할

ReactDOM.createPortal은 컴포넌트의 자식 요소들을 현재 DOM 계층 구조와 별도로, 지정한 다른 DOM 노드(예: document.body 또는 별도의 modal-root)에 렌더링할 수 있도록 해줍니다. 이를 통해 모달, 툴팁, 드롭다운 등 부모 요소의 스타일이나 레이아웃 영향 없이 UI를 구현할 수 있습니다.

주요 이점

  • 스타일 격리: 부모의 CSS 속성(overflow, z-index 등)과 독립적으로 렌더링되어 모달이 화면 전체에 올바르게 노출됨
  • DOM 구조 분리: 모달이 별도의 DOM 트리에 존재함으로써 이벤트 버블링 등에서 부모 컴포넌트와의 간섭을 줄일 수 있음

2. 문법 및 기본 사용법

기본 문법

ReactDOM.createPortal(child, container)
  • child: 렌더링할 React 요소(컴포넌트, JSX 등)
  • container: 해당 요소가 삽입될 실제 DOM 노드 (예: document.getElementById('modal-root'))

해당 요소가 삽입될 실제 DOM 노드

  • document.body : 모달 요소가 애플리케이션의 최상위 DOM 요소인 body의 자식으로 추가하도록 하는 방법.

  • 별도의 컨테이너를 만들 필요가 없어 사용이 더 간편하다. 다만 모달 로직이 복잡해지거나 여러 종류의 모달을 다루게 될 경우 관리가 어려워질 수 있다.

<body>
  <div id="root"></div>
  <div id="modal-root"></div>
</body>
  • 따라서 프로젝트 최상단에서 Modal이 출력될 별도의 컨테이너를 제공하여 관리하는 방법도 있다.

사용 예제 (Modal.jsx)

아래는 간단한 Modal.jsx 구현 예제입니다.

// Modal.jsx
import React from 'react';
import ReactDOM from 'react-dom';

const Modal = ({ isOpen, onClose, children }) => {
  // 모달이 렌더링될 DOM 컨테이너 (보통 index.html에 미리 정의된 div)
  const modalRoot = document.getElementById('modal-root');

  // 모달이 닫혀있으면 렌더링하지 않음
  if (!isOpen) return null;

  return ReactDOM.createPortal(
    <div className="modal-overlay">
      <div className="modal-content">
        {/* 모달 닫기 버튼 */}
        <button onClick={onClose}>닫기</button>
        {children}
      </div>
    </div>,
    modalRoot
  );
};

export default Modal;

설명

  • 조건부 렌더링: isOpenfalse면 모달이 렌더링되지 않음
  • Portal 적용: ReactDOM.createPortal을 통해 모달 콘텐츠가 modalRoot에 렌더링됨
  • 유지보수: 모달의 overlay, content 스타일은 별도의 CSS로 관리하여 부모 컴포넌트와 격리

3. 동작 원리 및 주의 사항

DOM 분리

  • createPortal을 사용하면, Modal 컴포넌트는 부모 컴포넌트 트리 외부의 DOM에 삽입됩니다.
  • 하지만 React의 이벤트 버블링은 부모 트리로 전파되므로 이벤트 처리를 일관되게 유지하면서도 시각적 위치는 독립적으로 제어할 수 있습니다.

접근성 및 포커스 관리

  • 모달은 종종 포커스 관리가 필요하므로, 포커스 트랩(focus trap) 이나 키보드 내비게이션 처리를 추가로 구현하는 것이 좋습니다.

스타일 관리

  • 별도의 DOM 컨테이너에 렌더링되므로, CSS를 통해 부모 요소의 영향을 받지 않도록 명확한 z-indexposition 속성을 설정해야 합니다.

4. 3줄? 요약

  • ReactDOM.createPortal모달과 같이 부모 DOM 계층 외부에 렌더링해야 하는 UI 컴포넌트 구현에 유용합니다.
  • 기본 문법은 ReactDOM.createPortal(child, container)이며, 이를 통해 모달 콘텐츠를 미리 정의된 DOM 노드(예: <div id="modal-root"></div>)에 삽입합니다.
  • Modal.jsx 예제에서 조건부 렌더링, 닫기 기능, 그리고 자식 요소 전달 방식을 통해 모달의 기본 동작을 구현할 수 있습니다.
profile
프론트엔드 개발자를 준비하고 있습니다.

0개의 댓글