프로그래밍/ReactJS

React Portals: 컴포넌트 렌더링의 자유를 위한 열쇠

shimdh 2025. 10. 6. 11:18
728x90

React 개발자라면 누구나 UI를 구성하는 데 있어 컴포넌트의 유연성이 얼마나 중요한지 잘 알고 있을 것입니다. 특히 모달, 툴팁, 드롭다운과 같이 다른 요소 위에 나타나야 하는 UI 요소를 다룰 때, 부모 컴포넌트의 DOM 계층 구조가 때로는 제약으로 다가올 수 있습니다. 하지만 React에는 이러한 제약을 우아하게 해결해주는 강력한 기능, 바로 포털(Portals) 이 있습니다. 오늘은 React Portals가 무엇이며, 왜 사용해야 하는지, 그리고 어떻게 활용할 수 있는지 깊이 있게 알아보겠습니다.

728x90

포털이란 무엇인가요?

본질적으로 React 포털은 자식 컴포넌트를 부모 컴포넌트와 다른 DOM 트리의 다른 부분에 렌더링하도록 허용하는 기능입니다. 이는 ReactDOM.createPortal() 메서드를 사용하여 수행되며, 이 메서드는 두 가지 인수를 받습니다.

  1. 렌더링하려는 자식 컴포넌트: 포털을 통해 렌더링될 React 엘리먼트입니다.
  2. 마운트될 DOM 노드: 이 자식 컴포넌트가 실제로 렌더링될 실제 DOM 노드입니다. 이 노드는 부모 컴포넌트의 DOM 계층 구조 외부에 있을 수 있습니다.

이 기능을 통해 개발자들은 CSS 스타일링 및 레이아웃과 관련된 특정 제약 사항을 극복할 수 있습니다. 예를 들어, overflow: hidden과 같은 CSS 속성 때문에 모달이나 툴팁이 잘려 보이는 문제를 해결할 수 있습니다.

왜 포털을 사용해야 할까요?

포털이 React 애플리케이션 개발에 있어 유용할 수 있는 몇 가지 핵심적인 이유는 다음과 같습니다.

1. 시각적 분리 (Visual Separation)

컴포넌트를 부모 컨테이너 외부에 렌더링함으로써, overflow: hidden과 같은 CSS 속성으로 인해 발생할 수 있는 오버플로 또는 위치 지정 문제의 영향을 받지 않도록 합니다. 이는 UI 요소가 의도한 대로 정확하게 표시되도록 보장하여, 사용자 경험을 크게 향상시킵니다. 특히 전체 화면을 덮는 모달이나 페이지 상단에 고정되어야 하는 알림 바와 같은 요소에 매우 유용합니다.

2. 이벤트 버블링 (Event Bubbling)

포털 내부에서 트리거된 이벤트는 마치 컴포넌트가 일반적인 컴포넌트 흐름 내에서 렌더링된 것처럼 부모 계층을 통해 계속 버블링됩니다. 이는 포털이 시각적으로는 분리되어 있어도 React의 논리적 컴포넌트 트리는 그대로 유지됨을 의미합니다. 결과적으로 이벤트가 예상대로 동작하면서도 UI를 유연하게 배치할 수 있는 강력한 이점을 제공합니다. 개발자는 복잡한 이벤트 핸들링 로직을 걱정할 필요 없이 자유롭게 UI를 배치할 수 있습니다.

3. 유연성 (Flexibility)

사용자 상호 작용 또는 애플리케이션 상태에 따라 특정 UI 요소가 렌더링되는 위치를 동적으로 제어할 수 있으며, 앱의 전체 구조를 변경할 필요가 없습니다. 이는 개발자가 복잡한 UI를 훨씬 더 쉽게 만들 수 있도록 돕습니다. 예를 들어, 특정 조건에서만 나타나야 하는 에러 메시지나 사용자 환경 설정에 따라 위치가 바뀌는 요소 등을 포털을 통해 효율적으로 관리할 수 있습니다.

포털 사용 예시: 모달 대화 상자 구축하기

포털의 가장 일반적이고 유용한 사용 사례 중 하나는 모달 대화 상자를 만드는 것입니다. 다음은 간단한 모달 컴포넌트를 포털을 사용하여 구현하는 예시입니다.

1. Modal.js 컴포넌트

import React from 'react';
import ReactDOM from 'react-dom';
import './Modal.css'; // 기본 모달 스타일이 있다고 가정

const Modal = ({ isOpen, onClose }) => {
  if (!isOpen) return null; // 모달이 열려있지 않으면 아무것도 렌더링하지 않음

  return ReactDOM.createPortal(
    <div className="modal-overlay">
      <div className="modal-content">
        <h2>모달 제목</h2>
        <p>포털을 사용한 간단한 모달입니다!</p>
        <button onClick={onClose}>닫기</button>
      </div>
    </div>,
    document.getElementById('modal-root') // index.html에 id "modal-root"를 가진 div가 있다고 가정
  );
};

export default Modal;

위 코드에서 주목할 점은 ReactDOM.createPortal()의 사용입니다. isOpentrue일 때, 모달 콘텐츠는 document.getElementById('modal-root')로 식별된 DOM 요소에 렌더링됩니다. 이 modal-root 요소는 일반적으로 index.html 파일의 <body> 태그 내부에 존재하며, 애플리케이션의 루트 DOM 노드와는 별개입니다.

2. App.js (메인 애플리케이션 컴포넌트)

import React, { useState } from 'react';
import Modal from './Modal';

const App = () => {
  const [isModalOpen, setIsModalOpen] = useState(false); // 모달의 가시성 상태 관리

  const openModal = () => setIsModalOpen(true);
  const closeModal = () => setIsModalOpen(false);

  return (
    <div>
      <h1>안녕하세요!</h1>
      <button onClick={openModal}>모달 보기</button>
      <Modal isOpen={isModalOpen} onClose={closeModal} /> {/* 모달 컴포넌트 사용 */}
    </div>
  );
};

export default App;

이 메인 애플리케이션 컴포넌트에서는 useState 훅을 사용하여 모달의 가시성 상태를 관리합니다. "모달 보기" 버튼을 클릭하면 isModalOpen 상태가 true로 설정되고, Modal 컴포넌트가 렌더링되면서 포털을 통해 지정된 modal-root DOM 노드에 모달이 나타나게 됩니다.

결론

React Portals는 이벤트 처리 및 라이프사이클 메서드를 그대로 유지하면서 DOM 트리의 다른 지점에 컴포넌트를 렌더링하기 위한 우아하고 강력한 솔루션을 제공합니다. 이는 특히 모달이나 툴팁과 같은 기능을 구축할 때 복잡한 UI 내에서 유연성을 크게 향상시켜, 개발자가 기능이나 성능을 저해하지 않으면서 더 많은 창의적 자유를 누릴 수 있도록 합니다.

포털을 언제 어떻게 활용해야 하는지 이해하는 것은 React 애플리케이션을 다루는 개발자로서의 능력을 크게 향상시킬 것입니다. UI의 제약을 넘어, 더 자유롭고 유연하며 사용자 친화적인 웹 애플리케이션을 구축하는 데 포털을 적극적으로 활용해 보세요.

728x90