Notion API를 사용한 Next.js 페이지 만드는 방법 feat. react-notion-x

Notion API 사용법을 알아보고 Notion 데이터베이스 연동, react-notion-x를 사용해 Next.js 페이지에 적용하는 방법을 알아봅니다.


Summary

Notion API를 사용하여 Notion 페이지를 Next.js 페이지에 렌더링하는 방법을 알아봅니다. react-notion-x를 사용하여 Notion 페이지를 실제 나의 웹사이트에 notion의 스타일 처럼 렌더링하는 방법을 알아봅니다.

본 포스트는 Next.js 14 버전 App router 기반으로 작성되었습니다.

목차

1. Notion 설정

1.1 데이터베이스 설정

이미 설정된 데이터베이스가 있다면 이 단계를 건너뛰어도 됩니다.

Notion 페이지를 추가하고 데이터베이스를 생성합니다.

notion database

notion database

notion api를 사용한다면 notion을 사용할 줄 아는것으로 가정하여 자세한 설명은 생략합니다.

데이터베이스의 각 페이지에 대한 정보가 있다고 가정합니다.

1.2 API 설정

생성한 데이터베이스 페이지에서 상단 우측 더보기 (···) 버튼을 클릭합니다.

더보기 - 연결관리

더보기 - 연결관리

더보기 -> 연결 항목 -> 연결 관리를 클릭합니다.

새 연결찾기 화면

새 연결찾기 화면

새 연결 찾기 화면에서 API 연결 개발 또는 관리를 클릭합니다.

API 연결 개발 또는 관리로 이동하면 내 API 통합 페이지가 나타납니다.

새 API 통합 만들기 버튼을 클릭합니다.

새 API 통합 만들기

새 API 통합 만들기

기본 정보에서 연결할 워크스페이스를 선택한 뒤, 이름을 입력하고 제출 버튼을 클릭합니다.

secret

secret

API 키 페이지에서 생성된 키를 잘 복사해두세요.

이후 데이터베이스 연결시에 사용됩니다.

외부에 노출되지 않게 잘 관리해야 합니다.

이제 다시 데이터베이스 페이지로 돌아가서 상단 우측 더보기 (···) 버튼에서 연결 항목 중 생성한 API를 연결합니다.

API 연결

API 연결

이름은 본인이 설정한 이름으로 되어있습니다. 저는 API TEST로 설정했습니다.

클릭후 나타나는 모달창에서 확인을 클릭합니다.

이제 데이터베이스 페이지에 API 연결이 완료되었습니다.

2. Next.js 설정 및 notion SDK 설치

next js 프로젝트에서 notion SDK를 설치합니다.

notion의 데이터베이스를 연동하기위해 @notionhq/client를 설치합니다.

그리고 notion 페이지를 가져오기 위해 notion-client를 설치합니다.

두가지 모두 설치해야 합니다. 사용하는 용도가 다릅니다.

npm install @notionhq/client
npm install notion-client

2.1 notion 페이지 데이터 가져오기

notion 페이지 가져오는 방법은 웹사이트 게시후 공유된 웹에서 가져올 수 있습니다. notion 데이터베이스 아이디와 API 키는 필요하지 않을 수 있습니다.

notion.ts 파일을 생성하고 아래와 같이 설정합니다.

notion.ts
import { NotionAPI } from 'notion-client';
 
export const notion = new NotionAPI();
 
export async function getData(rootPageId: string) {
  return await notion.getPage(rootPageId);
}

개별 페이지에 NotionAPI를 불러와도 됩니다. notion api를 구분짓기 위해 notion.ts 파일을 생성하여 사용하였습니다.

2.2 notion 페이지 설정 및 페이지 아이디 가져오기

페이지 아이디는 해당 페이지의 주소표시줄에서 확인할 수 있습니다.

우선 페이지를 웹에 게시해야 합니다.

게시하지 않으면 API로 데이터를 가져올 수 없습니다. 반드시 공유된 페이지만 가져올 수 있습니다.

페이지 웹에 게시하는 방법

페이지 웹에 게시하는 방법

페이지에서 우측 상단의 공유 버튼을 클릭후 게시 버튼을 클릭합니다.

그러면 주소가 나타납니다. 주소에서 페이지 아이디를 확인할 수 있습니다.

예시)

https://lilac-hare-5d2.notion.site/1-b9d4dfd97c8d41cba06bde5fa54cdc32?pvs=4
 
이 부분에서 https://lilac-hare-5d2.notion.site/1- 와 pvs=4 뒤에 있는 문자열이 페이지 아이디입니다.
 
b9d4dfd97c8d41cba06bde5fa54cdc32 이게 페이지 아이디입니다.

찾기 어렵다면 해당 페이지에서 브라우저 주소 표시줄을 봅니다.

데이터베이스에서 페이지를 열었다면 주소 표시줄에서 p= 이후 문자열이 페이지 아이디입니다.

또는 해당 페이지를 연상태라면 주소표시줄에서 1- (숫자는 다를수 있음) 다음 문자열이 페이지 아이디입니다.

2.3 Next.js 페이지에 notion 페이지 렌더링

Next.js 페이지에서 notion 데이터를 가져와 렌더링하는 방법을 알아봅니다.

app/about/page.tsx
import { getData } from '../../lib/notion';
 
const pageId = '페이지 아이디';
 
const About = async () => {
  const data = await getData(pageId);
  console.log(data);
 
  return <main></main>;
};
 
export default About;

console.log로 데이터를 가져오면 성공입니다!

이제 데이터를 화면에 렌더링하면 됩니다.

2.4 react-notion-x 사용하기

react-notion-x를 사용하면 notion 페이지를 더 쉽게 렌더링할 수 있습니다.

설치

npm install react-notion-x

notion용 컴포넌트를 만들어 사용합니다.

next js app router에서 사용하기 위해 client를 사용합니다. 반드시 클라이언트 컴포넌트를 사용해야합니다. page에서 'use client'를 사용하기엔 서버 컴포넌트를 포기해야하니 client 컴포넌트를 만들어서 사용하는게 좋습니다.

components/notion/Renderer.tsx
'use client';
 
import Link from 'next/link';
import { NotionRenderer } from 'react-notion-x';
 
interface RendererProps {
  recordMap: any; // 임의로 any
  rootPageId: string;
}
 
export const Renderer = ({ recordMap, rootPageId }: RendererProps) => {
  return (
    <div className="notion__container">
      <Link href="/">뒤로가기</Link>
      <NotionRenderer
        recordMap={recordMap}
        fullPage={true}
        darkMode={false}
        rootPageId={rootPageId}
        previewImages
      />
    </div>
  );
};
 
export default Renderer;

이제 about 페이지에서 다음과 같이 notion 페이지를 렌더링합니다.

app/about/page.tsx
import Renderer from '@/components/notion/renderer';
import { getData } from '@/lib/notion';
 
const pageId = '페이지 아이디';
 
const About = async () => {
  const data = await getData(pageId);
 
  return (
    <main>
      <Renderer recordMap={data} rootPageId={pageId} />
    </main>
  );
};
 
export default About;

about 페이지에서 notion 페이지를 렌더링 한것을 확인할 수 있습니다.

이제 스타일링을 위해 about 페이지에 css를 추가해줍니다.

app/about/page.tsx
import Renderer from '@/components/notion/renderer';
import { getData } from '@/lib/notion';
 
import 'react-notion-x/src/styles.css';
import 'prismjs/themes/prism-tomorrow.css';
import 'katex/dist/katex.min.css';
 
const pageId = '페이지 아이디';
 
// ... 생략

스타일을 추가하면 notion 스타일과 비슷한 스타일로 렌더링됩니다.

다음과 같이 notion 페이지를 렌더링할 수 있습니다.

notion에서 가져온 완성된 페이지

notion에서 가져온 완성된 페이지

css를 잘 다룰 수 있다면 커스텀도 가능합니다.

여기까지 Notion API를 사용한 Next.js 페이지 만드는 방법을 알아봤습니다.

이제 Notion 데이터베이스를 가져오는 방법을 설명해보겠습니다.


API 설정 에서 소개한 API 키를 사용하여 데이터베이스를 가져오는 방법을 알아봅니다.

3. 데이터베이스 가져오기

notion 데이터베이스를 가져오기 위해서 API 설정에서 생성한 API 키를 사용합니다.

API 키는 외부에 노출되면 안되기때문에 환경변수로 설정합니다.

.env 파일을 생성하고 API 키를 추가합니다.

.env
NOTION_SECRET="API 키"

이제 데이터베이스 아이디를 가져옵니다.

데이터 베이스 아이디는 notion에서 생성한 데이터베이스 페이지의 주소에서 확인할 수 있습니다.

데이터베이스의 주소가 다음과 같다면

https://www.notion.so/cd519594776be96...?v=b4c06936e7ff46a7b...

주소 다음 앞자리 문자열인 cd519594776be96...가 데이터베이스 아이디입니다. 32자리 문자열입니다. v= 뒤에 있는 문자열은 버전입니다.

만약 페이지에서 테이블만 있다면 표 이름에 마우스를 올리면 (···) 버튼이 나타납니다. 버튼을 클릭해서 데이터 보기로 이동하여 주소 표시줄에 있는 데이터베이스 아이디를 사용해야합니다.

데이터베이스의 아이디도 외부에 노출되어서는 안되기때문에 환경변수로 설정합니다.

.env 파일에 데이터베이스 아이디를 추가합니다.

.env
NOTION_DATABASE_ID=cd519594776be96... (데이터베이스 아이디)

다음 데이터베이스를 가져오기 위해 notion.ts 파일을 수정합니다.

notion.ts
import { Client } from '@notionhq/client';
 
export const notionDatabase = new Client({
  auth: process.env.NOTION_SECRET,
});
 
// ... 생략

본페이지는 간략히 app/page.tsx에서 불러오겠습니다.

app/page.tsx
import { notionDatabase } from '@/lib/notion';
 
export default async function Home() {
  if (!process.env.NOTION_DATABASE_ID) {
    throw new Error('데이터베이스 아이디가 없습니다.');
  }
  const db = await notionDatabase.databases.query({
    database_id: process.env.NOTION_DATABASE_ID,
  });
 
  console.log(db);
 
  console.log(db.results);
 
  return <main></main>;
}

위 코드를 입력하고 콘솔창을 확인 후 데이터를 가져온것이 확인되면 성공입니다.

db.results를 사용하여 각 페이지의 아이디와 정보를 가져올 수 있습니다.

이를 이용해 페이지 아이디를 사용하여 앞서 소개한 페이지 랜더링 방법으로 notion 페이지를 렌더링 및 다이나믹 라우팅을 구현할 수 있습니다.


에러 처리

Notion API를 호출하는 방법을 알아봤으며, 이제 추가해야 할 부분은 에러처리입니다.

notion은 간혹 서버에러가 발생할 수 있습니다. 이를 처리하기 위해 에러처리를 추가합니다.

app/page.tsx
// 에러 처리 예시
import { notionDatabase } from '@/lib/notion';
 
export default async function Home() {
  let db;
 
  try {
    if (!process.env.NOTION_DATABASE_ID) {
      throw new Error('데이터베이스 아이디가 없습니다.');
    }
    db = await notionDatabase.databases.query({
      database_id: process.env.NOTION_DATABASE_ID,
    });
  } catch (error) {
    console.error(error);
    return <main>에러가 발생했습니다.</main>;
  }
 
  return <main></main>;
}

에러 처리 예시이며, 각 페이지에서 본인의 스타일로 에러 처리를 하면 되겠습니다.


참고


관련 태그