노트

React Portal

Portals

프런트엔드#react · 연결된 개념 5개

쉽게 말하면

포털은 아이 방 장난감을 거실에 꺼내 놓아도 주인은 여전히 그 아이인 것과 같아요. 모달처럼 부모 상자에 잘리면 안 되는 요소를 body 같은 다른 DOM 자리에 그리면서도, React에서는 원래 부모 아래에 둬요.

비유가 깨지는 곳 그래서 기준이 둘로 갈려요. Context와 이벤트 버블링은 React 트리를 따라 원래 부모로 가지만, CSS 상속과 z-index는 옮겨진 DOM 위치를 따라가요. 그래서 스타일은 포털 안에서 직접 줘야 해요.

포털(Portal)은 자식 요소를 부모 컴포넌트의 DOM(Document Object Model) 계층 밖에 있는 다른 DOM 노드에 렌더하는 React 기능이다(createPortal(child, container)). DOM 위치만 옮겨지고 React 트리에서의 위치는 그대로다.

function Modal({ children }) {
  return createPortal(<div className="modal">{children}</div>, document.body)
}
  • 주 용도: 모달, 툴팁, 드롭다운처럼 부모의 overflow: hidden이나 쌓임 맥락(Stacking Context)에 잘리면 안 되는 오버레이(쌓임 순서와 z-index, 모달과 다이얼로그)
  • Context는 그대로 동작한다. React 트리상 원래 위치에 있기 때문이다
  • 이벤트는 React 트리를 따라 버블링한다. body로 옮겨진 버튼을 클릭해도 원래 부모의 onClick이 실행된다. DOM 기준으로 생각하면 놀라는 지점이다(이벤트 버블링·캡처링과 위임)
  • CSS(Cascading Style Sheets)는 DOM 기준이다. 부모의 상속 스타일이 적용되지 않으니 필요한 스타일은 포털 안에서 준다. 여러 포털이 겹치면 z-index도 직접 관리한다
  • 대상 노드가 실제로 있는지 확인하고, 직접 만든 컨테이너는 정리 함수에서 제거한다
  • 모달이라면 포커스 가두기(Focus Trap), Esc 닫기, ARIA(Accessible Rich Internet Applications) 속성 같은 접근성은 직접 챙겨야 한다. 요즘은 네이티브 dialog 요소도 대안이다

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • React 엘리먼트와 JSX

    React 엘리먼트(React Element)는 "화면에 무엇을 그릴지"를 설명하는 불변의 평범한 JavaScript 객체다. JSX(JavaScript XML)는 이 객체를 만드는 문법이고, 컴파일하면 createElement(새 JSX 변환에서는 jsx()) 호출이 된다.

  • Virtual DOM

    Virtual DOM(가상 DOM, Document Object Model)은 화면이 어떻게 생겨야 하는지를 메모리에 적어 둔 가벼운 JavaScript 객체 트리다. React에서는 React 엘리먼트 트리가 그것이다. 상태가 바뀌면 새 트리를 만들어 이전 트리와 비교하고, 달라진 부분만 실제 DOM에 반영한다.

  • React의 규칙과 렌더 순수성

    Rules of React는 React가 올바르게 동작하고 최적화하기 위해 코드가 지켜야 하는 규칙으로, 공식 문서가 세 가지로 정리한다. 핵심은 렌더가 순수한 계산이어야 한다는 것이다.

  • React Testing Library

    React Testing Library(RTL)는 컴포넌트를 jsdom 같은 테스트용 DOM(Document Object Model) 환경에 렌더하고, 사용자가 실제로 쓰는 방식으로 요소를 찾고 조작하게 해 주는 테스트 도구다. 내부 구현(state, 메서드)이 아니라 화면에 보이는 동작을 검증하라는 철학을 강하게 가진 라이브러리다.

  • React 서버 컴포넌트(RSC)

    React 서버 컴포넌트(React Server Components, RSC)는 서버에서만 실행되고, 컴포넌트 코드가 아니라 실행 결과(직렬화된 엘리먼트 트리)만 클라이언트로 보내는 컴포넌트다. Next.js App Router에서는 'use client'를 붙이지 않은 컴포넌트가 기본으로 서버 컴포넌트다.

보기 옵션