Skip to main content

페이지 렌더링

Notion 페이지를 React 앱에 렌더링하는 방법을 알아봅니다.

실제 동작 데모

tip

위 데모는 실제 동작하는 컴포넌트입니다. 전체 Storybook에서 더 많은 옵션을 테스트해보세요.


언제 쓰나요?

  • 블로그 글을 Notion에서 작성하고, 내 웹사이트에 보여주고 싶을 때
  • 문서/매뉴얼을 Notion으로 관리하고, 별도 페이지에 보여주고 싶을 때
  • Notion 페이지를 "새 창"이 아니라 내 앱 안에서 보여주고 싶을 때

방법 1: 전체 페이지 렌더링

가장 기본적인 방법입니다. Notion 페이지 하나를 통째로 React 컴포넌트로 렌더링합니다.

완성 코드 (복사해서 바로 사용)

// app/notion-page/page.tsx

import { NotionThemeProvider, NotionPage } from '@gendive/react-notion-renderer';

export default function NotionDemoPage() {
return (
<NotionThemeProvider>
<NotionPage
pageId="2baa76221f408089b1a9cfce9c133621"
token={process.env.NOTION_TOKEN!}
/>
</NotionThemeProvider>
);
}

환경변수 설정

.env.local 파일에 Notion API 토큰을 넣어주세요:

NOTION_TOKEN=ntn_xxxxx...

결과

Notion 페이지의 모든 블록(제목, 문단, 코드, 이미지, callout 등)이 React 컴포넌트로 렌더링됩니다.


방법 2: 데이터를 먼저 가져온 후 렌더링

더 세밀하게 제어하고 싶다면, 데이터를 먼저 가져오고 별도로 렌더링할 수 있습니다.

왜 이렇게 하나요?

  • 데이터를 캐싱하거나 가공하고 싶을 때
  • 페이지 제목만 따로 쓰고 싶을 때
  • 로딩 상태를 직접 관리하고 싶을 때

코드

// app/notion-page/page.tsx

import {
fetchNotionPage,
NotionThemeProvider,
NotionPageRenderer,
} from '@gendive/react-notion-renderer';

export default async function Page() {
// 1. 데이터 가져오기
const page = await fetchNotionPage(
'2baa76221f408089b1a9cfce9c133621', // 페이지 ID
process.env.NOTION_TOKEN!, // API 토큰
);

// 2. 렌더링
return (
<NotionThemeProvider>
<h1>{page.title}</h1> {/* 페이지 제목 따로 사용 가능 */}
<NotionPageRenderer page={page} />
</NotionThemeProvider>
);
}

fetchNotionPage 반환값

{
id: string; // 페이지 ID
title: string; // 페이지 제목
blocks: NotionBlock[]; // 블록 배열
}

방법 3: 모달로 페이지 보여주기

데이터베이스에서 카드를 클릭했을 때, 모달(팝업)로 페이지 내용을 보여주고 싶다면 NotionPageModal을 사용합니다.

동작 방식

  1. 사용자가 카드 클릭
  2. 모달이 열리면서 해당 페이지 데이터를 가져옴
  3. 모달 안에 페이지 내용 표시
  4. 모달 닫기 버튼 또는 바깥 클릭으로 닫기

단계별 설정

1단계: API Route 만들기

브라우저에서는 Notion API를 직접 호출할 수 없습니다.
Next.js API Route를 통해 서버에서 가져오도록 합니다.

// app/api/notion/page/[pageId]/route.ts

export { GET } from '@gendive/react-notion-renderer/api';

이 한 줄이면 /api/notion/page/[pageId] 엔드포인트가 만들어집니다.

2단계: 환경변수 확인

# .env.local
NOTION_TOKEN=ntn_xxxxx...

3단계: 모달 컴포넌트 사용

"use client";

import { useState } from 'react';
import { NotionPageModal } from '@gendive/react-notion-renderer';
import { fetchNotionPageClient } from '@gendive/react-notion-renderer/client';

export function PageModalDemo() {
const [selectedPageId, setSelectedPageId] = useState<string | null>(null);

return (
<div>
{/* 클릭하면 모달 열기 */}
<button onClick={() => setSelectedPageId('2baa76221f408089b1a9cfce9c133621')}>
페이지 보기
</button>

{/* 모달 */}
<NotionPageModal
pageId={selectedPageId}
onClose={() => setSelectedPageId(null)}
fetchPage={fetchNotionPageClient}
/>
</div>
);
}

NotionPageModal Props

Prop타입설명
pageIdstring | null표시할 페이지 ID. null이면 모달이 닫힘
onClose() => void모달을 닫을 때 호출되는 함수
fetchPageFunction페이지 데이터를 가져오는 함수

테마 설정

라이트/다크 모드

<NotionThemeProvider theme="dark">
<NotionPage pageId="..." token="..." />
</NotionThemeProvider>
설명
"light"밝은 테마
"dark"어두운 테마
생략시스템 설정 따름

지원하는 블록 타입

이 라이브러리가 렌더링할 수 있는 Notion 블록들입니다:

텍스트/구조

블록설명
paragraph일반 문단
heading_1, heading_2, heading_3제목
quote인용문
callout콜아웃 (아이콘 + 배경색)
toggle토글 (접기/펼치기)
divider구분선

리스트

블록설명
bulleted_list_item글머리 기호 목록
numbered_list_item번호 목록
to_do체크박스

미디어

블록설명
image이미지
video비디오
embed외부 콘텐츠 임베드 (iframe)
bookmark북마크 링크

코드/표

블록설명
code코드 블록 (복사 버튼 포함)
table

자세한 미디어 블록 사용법은 Embed & Media 문서를 참고하세요.


자주 묻는 질문

Q. 페이지 ID는 어디서 찾나요?

Notion 페이지 URL에서 찾을 수 있습니다:

https://www.notion.so/My-Page-Title-2baa76221f408089b1a9cfce9c133621
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
이 부분이 페이지 ID

Q. "Could not find page" 에러가 나요

Integration이 해당 페이지에 연결되어 있는지 확인하세요:

  1. Notion에서 페이지 열기
  2. ...Connections → Integration 선택

Q. 이미지가 안 보여요

Notion 이미지는 1시간 후 만료됩니다. 프로덕션에서는 이미지를 별도 스토리지에 저장하는 것을 권장합니다.