블록 컴포넌트
import {
TextBlock,
HeadingBlock,
CodeBlock,
ImageBlock,
// ... 모든 named export
} from "@noxion/notion-renderer";
모든 Notion 블록 타입은 독립적인 React 컴포넌트입니다. 모두 클라이언트 컴포넌트("use client")이며 useNotionRenderer()를 통해 렌더러 컨텍스트를 사용합니다.
NotionBlock과 NotionBlockList
내부 디스패치 컴포넌트입니다. 직접 사용할 필요는 드물지만, 커스텀 블록 래퍼를 만들 때 유용합니다.
NotionBlock
import { NotionBlock } from "@noxion/notion-renderer";
recordMap에서 ID로 블록을 조회하고, 적절한 컴포넌트(내장 또는 오버라이드)를 선택하여 자식과 함께 렌더링합니다.
interface NotionBlockRendererProps {
blockId: string; // Notion 블록 ID
level: number; // 중첩 깊이 (0 = 루트)
}
선택 우선순위:
components.blockOverrides[blockType](커스텀 오버라이드)blockType에 대한 내장 컴포넌트null(프로덕션) 또는 개발 경고<div>(개발 환경)
NotionBlockList
ID 목록으로 블록들을 순서대로 렌더링합니다:
import { NotionBlockList } from "@noxion/notion-renderer";
<NotionBlockList blockIds={["id1", "id2", "id3"]} level={0} />
NotionBlockProps
모든 블록 컴포넌트가 받는 Props:
interface NotionBlockProps {
block: Block; // notion-types의 전체 Notion 블록 객체
blockId: string; // 블록의 ID 문자열
level: number; // 중첩 깊이 (0 = 루트 페이지)
children?: ReactNode; // 미리 렌더링된 자식 블록
}
블록 레퍼런스
TextBlock
Notion 타입: text
단락을 렌더링합니다. 모든 리치 텍스트 데코레이션(굵기, 기울임, 코드, 링크, 색상, 인라인 수식, 멘션)을 지원합니다.
<p class="noxion-text">{리치 텍스트 콘텐츠}</p>
빈 텍스트 블록은 Notion 간격을 유지하기 위해 <p class="noxion-text noxion-text--empty"> </p>로 렌더링됩니다.
HeadingBlock
Notion 타입: header (H1), sub_header (H2), sub_sub_header (H3)
앵커 링크를 위해 자동으로 생성된 URL 안전 ID와 함께 제목을 렌더링합니다. ID는 generateHeadingId()를 통해 생성되며, headingIds 컨텍스트 세트를 사용하여 페이지 내에서 자동으로 중복이 제거됩니다.
각 제목에는 호버 시 표시되는 HeadingAnchor 컴포넌트가 포함되어 있으며, 클릭 시 제목 링크를 클립보드에 복사합니다.
<h2 id="my-heading" class="noxion-heading noxion-heading--2">
<a class="noxion-heading-anchor" href="#my-heading" aria-label="Link to heading my-heading">#</a>
{텍스트}
</h2>
제목 ID는 다음 규칙을 따릅니다:
- 소문자로 변환
- 공백을 하이픈으로 대체
- 특수 문자 제거 (한글은 보존됨)
- 중복된 경우
-1,-2접미사 추가
BulletedListBlock
Notion 타입: bulleted_list
글머리 기호 목록 항목을 렌더링합니다. 연속된 글머리 기호 목록 항목은 CSS의 인접 형제 선택자를 통해 공유 <ul>로 래핑됩니다.
<li class="noxion-bulleted-list">{텍스트}</li>
NumberedListBlock
Notion 타입: numbered_list
BulletedListBlock과 동일하지만 CSS <ol> 래퍼와 함께 <li>를 렌더링합니다.
<li class="noxion-numbered-list">{텍스트}</li>
ToDoBlock
Notion 타입: to_do
체크박스 항목을 렌더링합니다. 체크박스는 disabled(읽기 전용)이며 Notion의 체크 상태를 반영합니다. 키보드 접근성이 포함되어 있어 Enter와 Space 키로 체크박스 시각적 피드백을 트리거할 수 있습니다.
<div class="noxion-to-do [noxion-to-do--checked]"
role="checkbox" aria-checked="true|false"
tabindex="0" onkeydown="handleKeyboardActivation">
<input type="checkbox" disabled [checked] />
<span class="noxion-to-do__label">{텍스트}</span>
</div>
QuoteBlock
Notion 타입: quote
왼쪽 보더가 있는 인용 블록을 렌더링합니다.
<blockquote class="noxion-quote">{텍스트}</blockquote>
CalloutBlock
Notion 타입: callout
block.format.page_icon의 이모지 또는 커스텀 아이콘이 있는 콜아웃 박스를 렌더링합니다.
<div class="noxion-callout">
<div class="noxion-callout__icon">{이모지}</div>
<div class="noxion-callout__content">{텍스트}</div>
</div>
DividerBlock
Notion 타입: divider, breadcrumb에도 사용
<hr class="noxion-divider" />
ToggleBlock
Notion 타입: toggle
useState를 사용하여 접을 수 있는 토글을 렌더링하는 클라이언트 컴포넌트("use client")입니다. 전체 키보드 접근성이 포함되어 있어 Enter와 Space 키로 콘텐츠를 토글할 수 있습니다.
<div class="noxion-toggle" aria-expanded="true|false">
<div class="noxion-toggle__summary" role="button" tabindex="0"
aria-controls="toggle-content-{blockId}">
{요약 텍스트}
</div>
<div class="noxion-toggle__content" id="toggle-content-{blockId}">
{자식}
</div>
</div>
토글 상태는 클라이언트 사이드에서 관리됩니다. aria-expanded 속성과 콘텐츠 가시성이 동적으로 업데이트됩니다.
,
PageBlock
Notion 타입: page
Notion 하위 페이지로의 링크를 렌더링합니다. URL은 mapPageUrl(blockId)로 생성됩니다.
<div class="noxion-page">
<a href="{url}" class="noxion-page__link">
<span class="noxion-page__icon">{아이콘}</span>
<span class="noxion-page__title">{제목}</span>
</a>
</div>
EquationBlock
Notion 타입: equation
katex.renderToString()을 통해 서버 사이드에서 블록 레벨 KaTeX 수식을 렌더링합니다. @noxion/notion-renderer/katex-css를 임포트해야 합니다.
<div class="noxion-equation noxion-equation--block">
<!-- KaTeX HTML 출력 -->
</div>
렌더링 오류 시 <code class="noxion-equation-error">{원본 수식}</code>으로 폴백됩니다.
CodeBlock
Notion 타입: code
선택적 Shiki 구문 강조가 있는 코드 블록을 렌더링합니다. 성능을 위해 highlightCode 결과는 useMemo로 메모이제이션됩니다. highlightCode가 제공되지 않으면 일반 <pre><code>로 폴백됩니다.
<div class="noxion-code">
<div class="noxion-code__header">
<span class="noxion-code__language">{언어}</span>
</div>
<!-- Shiki 사용 시: -->
<div class="noxion-code__body">{shiki HTML}</div>
<!-- Shiki 미사용 시: -->
<pre class="noxion-code__body">
<code class="noxion-code__content language-{lang}"
role="code"
aria-label="{언어} 코드 블록">{코드}</code>
</pre>
<!-- 선택적 캡션: -->
<figcaption class="noxion-code__caption">{캡션}</figcaption>
</div>
스크린 리더의 정확성을 위해 aria-label은 외부 래퍼가 아닌 <code> 엘리먼트에 배치됩니다. 구문 강조 설정은 Shiki를 참조하세요.
,
ImageBlock
Notion 타입: image
이미지를 렌더링합니다. URL 변환에 컨텍스트의 mapImageUrl()을 사용합니다. next/image 통합을 위해 components.Image 오버라이드를 지원합니다.
<figure class="noxion-image [noxion-image--full-width] [noxion-image--page-width]">
<img
src="{매핑된 url}"
alt="{alt}"
width="{width}"
height="{height}"
loading="lazy"
decoding="async"
class="noxion-image__img"
/>
<figcaption class="noxion-image__caption">{캡션}</figcaption>
</figure>
components.Image가 설정된 경우 <img> 대신 해당 컴포넌트를 렌더링합니다.
VideoBlock
Notion 타입: video
YouTube, Vimeo 등은 <iframe>으로, 직접 파일 URL은 <video>로 렌더링합니다.
AudioBlock
Notion 타입: audio
<div class="noxion-audio">
<audio src="{url}" controls class="noxion-audio__player" />
</div>
EmbedBlock
Notion 타입: embed, gist, figma, typeform, replit, codepen, excalidraw, tweet, maps, miro, drive, external_object_instance
모든 임베드 타입을 <iframe>으로 렌더링합니다.
BookmarkBlock
Notion 타입: bookmark
block.properties의 제목, 설명, URL로 풍부한 링크 미리보기를 렌더링합니다.
<a href="{url}" class="noxion-bookmark" target="_blank" rel="noopener noreferrer">
<div class="noxion-bookmark__content">
<div class="noxion-bookmark__title">{제목}</div>
<div class="noxion-bookmark__description">{설명}</div>
<div class="noxion-bookmark__url">{url}</div>
</div>
</a>
TableBlock
Notion 타입: table
Notion 표를 렌더링합니다. block.content를 사용하여 table_row 자식을 찾습니다.
ColumnListBlock / ColumnBlock
Notion 타입: column_list, column
ColumnListBlock은 CSS Grid 컨테이너를 렌더링합니다. ColumnBlock은 개별 열을 렌더링합니다.
<div class="noxion-column-list">
<div class="noxion-column">{열 콘텐츠}</div>
<div class="noxion-column">{열 콘텐츠}</div>
</div>
TableOfContentsBlock
Notion 타입: table_of_contents
페이지의 모든 제목 블록을 수집하고 탐색 가능한 목록을 렌더링합니다.
<nav class="noxion-toc">
<ul class="noxion-toc__list">
<li class="noxion-toc__item noxion-toc__item--1">
<a href="#heading-id">{제목 텍스트}</a>
</li>
...
</ul>
</nav>
CollectionViewBlock
Notion 타입: collection_view, collection_view_page
Notion 데이터베이스의 대화형 테이블 뷰를 렌더링합니다. 성능을 위해 대화형 컴포넌트는 createLazyBlock을 통해 지연 로딩되며, 컬렉션 뷰 블록이 나타날 때만 로드됩니다.
기능:
- 테이블 렌더링 — 컬렉션 데이터를 정렬 가능한 테이블로 표시합니다.
- 열 정렬 — 열 헤더를 클릭하여 오름차순/내림차순으로 정렬합니다.
- 필터링 — 열 값으로 행을 필터링합니다.
- 지연 로딩 — 대화형 컴포넌트는
React.lazy+ Suspense를 통해 필요할 때 로드됩니다.
<!-- 로딩 중: -->
<div class="noxion-loading-placeholder">로딩 중...</div>
<!-- 로드 후: -->
<div class="noxion-collection-view">
<table class="noxion-collection-view__table">
<thead>...</thead>
<tbody>...</tbody>
</table>
</div>
1단계에서는 테이블 뷰만 지원합니다. 다른 데이터베이스 뷰(갤러리, 보드, 캘린더, 리스트)는 아직 구현되지 않았습니다.
레거시 CollectionViewPlaceholder 컴포넌트는 하위 호환성을 위해 여전히 익스포트됩니다.