Notion 페이지를 마크다운 파일로 자동 백업하는 방법

Notion API와 notion-to-md 라이브러리를 활용하면 노션 페이지를 마크다운 형식으로 변환해서 자동으로 백업할 수 있어요. macOS 환경에서 파이썬이나 Node.js로 간단한 스크립트를 만들어 정기적인 백업 시스템을 구축하는 방법을 알아볼게요.

폴더와 문서 간 양방향 데이터 동기화를 나타내는 아이콘 일러스트

notion-to-md 라이브러리로 시작하기


노션 공식 API는 마크다운 직접 내보내기를 지원하지 않기 때문에 notion-to-md 같은 서드파티 라이브러리를 사용해야 해요. 이 라이브러리는 노션 페이지의 블록 구조를 분석해서 마크다운 문법으로 변환해주는 역할을 해요.


먼저 필요한 패키지를 설치해요. macOS 터미널을 열고 다음 명령어를 실행하세요.


# Node.js 환경
npm install @notionhq/client notion-to-md

# Python 환경
pip install notion-client notion-to-md


Node.js로 기본 변환 스크립트 만들기


Node.js 환경에서 간단한 변환 스크립트를 만들어볼게요. 

프로젝트 폴더에 notion-backup.js 파일을 생성하고 다음 코드를 작성해요.


import { Client } from '@notionhq/client';
import { NotionToMarkdown } from 'notion-to-md';
import fs from 'fs/promises';

const notion = new Client({ 
  auth: process.env.NOTION_SECRET_KEY 
});

const n2m = new NotionToMarkdown({ notionClient: notion });

async function fetchArticleContent(pageId) {
  try {
    const mdBlocks = await n2m.pageToMarkdown(pageId);
    const mdString = n2m.toMarkdownString(mdBlocks);
    
    // 파일로 저장
    const fileName = `backup_${Date.now()}.md`;
    await fs.writeFile(fileName, mdString, 'utf-8');
    
    console.log(`백업 완료: ${fileName}`);
    return mdString;
  } catch (error) {
    console.error('백업 실패:', error);
  }
}

// 사용 예시
fetchArticleContent('YOUR_PAGE_ID');


환경 변수로 Notion API 키를 설정해야 해요. macOS에서는 터미널에서 다음과 같이 설정할 수 있어요.


export NOTION_SECRET_KEY="your-notion-api-key"
node notion-backup.js


파이썬으로 자동화 스크립트 구현하기


파이썬을 선호한다면 다음과 같은 방식으로 구현할 수 있어요. notion_backup.py 파일을 만들고 아래 코드를 작성해요.


from notion_client import Client
from notion_to_md import NotionToMarkdown
import os
from datetime import datetime

# Notion 클라이언트 초기화
notion = Client(auth=os.environ["NOTION_API_KEY"])
n2m = NotionToMarkdown(notion)

def backup_notion_page(page_id, output_dir="backups"):
    # 백업 디렉토리 생성
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    
    # 페이지를 마크다운으로 변환
    md_blocks = n2m.page_to_markdown(page_id)
    md_string = n2m.to_markdown(md_blocks)
    
    # 파일명 생성 (타임스탬프 포함)
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"{output_dir}/backup_{timestamp}.md"
    
    # 파일로 저장
    with open(filename, "w", encoding="utf-8") as f:
        f.write(md_string)
    
    print(f"백업 완료: {filename}")
    return filename

# 여러 페이지 백업
pages_to_backup = [
    "page_id_1",
    "page_id_2",
    "page_id_3"
]

for page_id in pages_to_backup:
    backup_notion_page(page_id)


서브페이지까지 포함한 재귀적 백업


노션 페이지 안에 있는 서브페이지들까지 모두 백업하려면 재귀적으로 페이지를 탐색해야 해요. 다음은 서브페이지를 포함한 전체 백업 스크립트예요.


import asyncio
from notion_client import AsyncClient
from notion_to_md import NotionToMarkdown

async def backup_page_recursive(notion, n2m, page_id, output_dir, level=0):
    # 현재 페이지 백업
    md_blocks = await n2m.page_to_markdown(page_id)
    md_string = n2m.to_markdown(md_blocks)
    
    # 들여쓰기로 계층 구조 표현
    indent = "  " * level
    filename = f"{output_dir}/{indent}page_{page_id[:8]}.md"
    
    with open(filename, "w", encoding="utf-8") as f:
        f.write(md_string)
    
    # 현재 페이지의 모든 블록 가져오기
    blocks = await notion.blocks.children.list(block_id=page_id)
    
    # child_page 타입 블록 찾아서 재귀 호출
    for block in blocks["results"]:
        if block["type"] == "child_page":
            await backup_page_recursive(
                notion, n2m, 
                block["id"], 
                output_dir, 
                level + 1
            )

# 비동기 실행
async def main():
    notion = AsyncClient(auth=os.environ["NOTION_API_KEY"])
    n2m = NotionToMarkdown(notion)
    
    root_page_id = "YOUR_ROOT_PAGE_ID"
    await backup_page_recursive(notion, n2m, root_page_id, "backups")

asyncio.run(main())


macOS에서 정기 자동 백업 설정하기


스크립트를 만들었다면 이제 자동으로 실행되도록 설정해볼게요. macOS의 launchd를 사용하면 특정 시간마다 스크립트를 실행할 수 있어요.


먼저 실행 가능한 쉘 스크립트를 만들어요.


#!/bin/bash
# backup_notion.sh

# 환경 변수 설정
export NOTION_API_KEY="your-api-key"
export PATH="/usr/local/bin:$PATH"

# 프로젝트 디렉토리로 이동
cd /Users/username/notion-backup

# Python 가상환경 활성화 (필요한 경우)
source venv/bin/activate

# 백업 스크립트 실행
python3 notion_backup.py

# 백업 파일을 Git으로 커밋 (선택사항)
git add backups/
git commit -m "Auto backup: $(date)"
git push origin main


다음으로 launchd plist 파일을 생성해요. ~/Library/LaunchAgents/com.user.notion-backup.plist 파일을 만들고 다음 내용을 추가해요.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.user.notion-backup</string>
    
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>/Users/username/notion-backup/backup_notion.sh</string>
    </array>
    
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>9</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    
    <key>StandardOutPath</key>
    <string>/Users/username/notion-backup/backup.log</string>
    
    <key>StandardErrorPath</key>
    <string>/Users/username/notion-backup/error.log</string>
</dict>
</plist>


이 설정은 매일 오전 9시에 백업 스크립트를 실행해요. launchd에 등록하려면 터미널에서 다음 명령을 실행하세요.


launchctl load ~/Library/LaunchAgents/com.user.notion-backup.plist


Notion API 토큰 발급받기


스크립트를 실행하려면 Notion API 토큰이 필요해요. Notion 개발자 페이지에서 새 통합을 만들고 시크릿 키를 복사해요. 그 다음 백업하려는 노션 페이지에서 통합을 연결해야 해요.


페이지 우측 상단의 점 세 개 메뉴를 클릭하고 연결 추가에서 만든 통합을 선택하면 돼요. 이제 해당 페이지와 하위 페이지들에 API로 접근할 수 있어요.


변환 품질과 한계점 고려하기


notion-to-md는 대부분의 블록을 잘 변환하지만 몇 가지 한계가 있어요. 복잡한 데이터베이스 뷰나 일부 위젯, 임베드된 콘텐츠는 완벽하게 변환되지 않을 수 있어요.


이미지의 경우 노션에서 제공하는 임시 URL을 사용하기 때문에 시간이 지나면 링크가 만료될 수 있어요. 영구 백업을 원한다면 이미지를 로컬에 다운로드하는 추가 로직이 필요해요.


import requests
import re

def download_images(md_content, output_dir):
    # 마크다운에서 이미지 URL 추출
    image_pattern = r'!\[.*?\]\((https://.*?)\)'
    images = re.findall(image_pattern, md_content)
    
    for idx, img_url in enumerate(images):
        # 이미지 다운로드
        response = requests.get(img_url)
        filename = f"{output_dir}/image_{idx}.png"
        
        with open(filename, "wb") as f:
            f.write(response.content)
        
        # 마크다운 내용에서 URL을 로컬 경로로 변경
        md_content = md_content.replace(
            img_url, 
            f"./image_{idx}.png"
        )
    
    return md_content


macOS의 자동화 도구와 Python/Node.js 스크립트를 조합하면 노션 페이지를 안정적으로 백업할 수 있어요. 정기적인 백업으로 중요한 문서를 안전하게 보관하고, 필요할 때 마크다운 형식으로 활용할 수 있게 돼요.


파이썬 자동화로 구글 캘린더 반복 일정 쉽게 관리하기