React createPortal로 모달 만들기

2025년 10월 22일 수요일
593글자
3분

React의 createPortal을 사용해서 모달을 제작하는 방법에 대해서 알아보려고 합니다.

0️⃣ createPortal?

createPortal은 컴포넌트를 DOM의 다른 부분으로 렌더링 할 수 있도록 하는 함수입니다.

typescript
createPortal(children, domNode, key?)

위의 코드처럼 다른 부분으로 이동시킬 children, 배치되는 곳을 나타내는 domNode, 그리고 선택 옵션으로 portal의 고유한 키를 지정해주는 key 옵션이 있습니다.


1️⃣ createPortal 사용하기

실제 사용하는 방법은 다음과 같습니다.

typescript
return createPortal(
  <p>모달입니다</p>
  document.body
);

<p>태그로 작성된 요소를 <body>태그 안에 넣게됩니다.

<body>태그 안에 직접 넣는 것이 싫다면 프로젝트의 루트 부분에 따로 <div id="id">로 원하는 id의 요소 안으로 이동시킬 수 있습니다.

typescript
// RootLayout
return (
  <html>
    <body>
      <div id="modal-root"></div>
    </body>
  </html>
);

// Modal
return createPortal(
  <p>모달입니다</p>
  document.getElementById("modal-root");
);

getElementById()로 가져온 <div>요소를 모달의 요소와 치환 하는 것이 아니라 각각의 child divcreatePortal요소가 생기게 됩니다.

만약 치환하는 방식이었다면 이미 다른 모달이 열려 있을 경우에 문제가 발생할 수도 있기 때문에 children이 추가되는 방식으로 더 안전하게 접근할 수 있습니다.


3️⃣ <dialog>로 모달 쉽게 만들기

HTML 요소 중 <dialog>라는 태그가 있습니다.
해당 태그는 모달을 open 속성, showModal() 함수 사용 방식 중 어떤 방법을 사용하는지에 따라 동작이 달라집니다.

<dialog open>방식으로 표출되면 비모달 방식으로 동작하게 됩니다.
뒷 배경이 어둡게 표출되는 backdrop도 생기지 않습니다.

따라서 모달 요소로 표출하기 위해서는 showModal()함수를 사용합니다.

해당 함수를 사용하면 backdrop이 표출되고 ESC키를 누르는 동작으로 모달창을 닫히게 할 수 있습니다.
이제 createPortal<dialog>를 사용해서 모달을 쉽고 간편하게 만들어 보겠습니다.

typescript
const Modal = ({ ref, className, onCancel, children }: ModalProps) => {
  return createPortal(
    <dialog
      className={cn(
        "flex flex-col gap-6 bg-white",
        "rounded-2xl border border-gray-200",
        "shadow-[0_16px_32px_-4px_rgba(12,12,13,0.1)]",
        className
      )}
      ref={ref}
      onCancel={onCancel}
    >
      {children}
    </dialog>,
    document.body
  );
};
dialog_modal

참조
[리액트] createPortal과 createRoot
createPortal


게시글 제목:React createPortal로 모달 만들기

작성자:huui

게시글 링크:https://huuitae.github.io/posts/make_modal_with_createportal [복사]

마지막 수정일:


상업적 복제의 경우, 웹마스터에게 허가를 요청하십시오. 비상업적 복제의 경우, 본 기사의 출처와 링크를 명시해 주십시오. 본 저작물은 어떤 형태로든, 어떤 매체로든 자유롭게 복제 및 배포할 수 있으며, 수정 및 제작도 가능합니다. 단, 2차 저작물을 배포할 경우에도 동일한 라이선스 계약을 적용해야 합니다.
이 게시글은 다음을 채택합니다.CC BY-NC-SA 4.0의 허가를 받아야 합니다.