대상: Notion을 “수동 입력용 문서”가 아니라, Python 스크립트로 DB를 자동 생성/관리하고 싶은 개발자
환경:
- Notion 계정 + 워크스페이스
- Notion API(Integration) 사용 권한
- Python 3.8+
- 라이브러리:
notion-client,python-dotenv
1. 문제/주제 요약
- Notion에서 매번 “새 데이터베이스 → 컬럼 추가 → 옵션 설정” 하는 게 귀찮다
- Python 코드로 특정 페이지 아래에 DB를 자동 생성하고 싶다
- 나아가 나중에는 이 DB에 row(페이지)를 자동으로 추가/수정하는 자동화도 하고 싶다
이 글에서는 다음을 목표로 합니다.
- Notion Integration 생성 후 Python에서 API 연결
notion-client를 이용해 새 데이터베이스를 자동 생성- 생성된 DB에 간단한 아이템(페이지) 하나까지 추가하는 예제
2. 배경/원리 설명
2-1. Notion API 동작 방식 간단 정리
- Notion의 공식 REST API는 Integration(연결)을 통해 워크스페이스에 접근합니다.
- Integration을 만들면 Secret Token을 발급받고, 이 토큰으로 HTTP 요청을 보냅니다. (Notion API Documentation)
- Python에서는 공식 JS SDK 대신 Python용 클라이언트 라이브러리
notion-client(notion-sdk-py) 를 쓰면 편합니다. (PyPI)
2-2. “데이터베이스 자동 생성”의 핵심
Notion API에서 데이터베이스 생성은 다음과 같이 동작합니다. (Notion API Documentation)
- parent: “어느 페이지 아래에 DB를 만들지” 지정
parent = { "type": "page_id", "page_id": "<부모 페이지 ID>" }
- title: 데이터베이스 이름(리치 텍스트 배열)
- properties: 컬럼 스키마 정의
- 최소 1개의
title타입 속성이 반드시 필요 - 예:
{"Name": {"title": {}}}"Tags"컬럼:multi_select"Due"컬럼:date…
- 최소 1개의
Python 클라이언트를 쓰면 이걸 notion.databases.create(...) 한 번으로 호출할 수 있습니다. (Velog)
3. 단계별 설정 및 예제 코드
3-1. Notion Integration 생성 & 토큰 발급
- 브라우저에서 Notion → Settings → Connections → Develop or manage integrations로 이동
- New integration 클릭 후 이름/권한 설정
- 생성 후 나오는 화면에서 Internal Integration Token 복사 (Notion API Documentation)
이 토큰이 나중에 Python 코드의 NOTION_TOKEN이 됩니다.
3-2. Integration에 권한 줄 페이지 준비
- Notion에서 DB를 만들고 싶은 위치에 빈 페이지 하나 생성 (예:
API 테스트페이지) - 그 페이지 우측 상단 Share 버튼 클릭 → 방금 만든 Integration을 초대 (Invite)
- Integration이 초대된 페이지/DB만 API에서 접근 가능
- URL에서 page_id를 추출
- URL 예:
https://www.notion.so/workspace/API-테스트-페이지-1234567890abcdef1234567890abcdef?pvs=4 - 여기서
1234567890abcdef1234567890abcdef부분이 page_id - 하이픈이 섞인 경우도 있는데, 보통 라이브러리에서 자동으로 처리해 줍니다. (문송한투자자)
- URL 예:
이 page_id를 나중에 PARENT_PAGE_ID로 사용합니다.
3-3. Python 환경 세팅
필요 라이브러리 설치:
pip install notion-client python-dotenv
프로젝트 구조 예:
notion_db_auto_create/
├─ main.py
├─ .env
.env 파일 내용(직접 생성):
NOTION_TOKEN=여기에_발급받은_시크릿_토큰_붙여넣기
NOTION_PARENT_PAGE_ID=여기에_부모_페이지_ID_붙여넣기
3-4. Python에서 Notion 클라이언트 연결
main.py에 기본 연결 코드 작성:
# main.py
import os
from dotenv import load_dotenv
from notion_client import Client
# .env 파일 로드
load_dotenv()
NOTION_TOKEN = os.getenv("NOTION_TOKEN")
PARENT_PAGE_ID = os.getenv("NOTION_PARENT_PAGE_ID")
if NOTION_TOKEN is None or PARENT_PAGE_ID is None:
raise RuntimeError("NOTION_TOKEN 또는 NOTION_PARENT_PAGE_ID 가 설정되어 있지 않습니다.")
# Notion 클라이언트 생성
notion = Client(auth=NOTION_TOKEN)
여기까지 실행해 보고, 에러 없이 넘어가면 토큰/페이지 ID 설정은 OK입니다.
3-5. 데이터베이스 자동 생성 함수 작성
이제 notion.databases.create()를 이용해서 실제 DB를 만듭니다.
예시: “할 일 관리용 DB”를 자동으로 생성해 보는 코드입니다. (Velog)
def create_todo_database():
# 데이터베이스 제목 (리치 텍스트 배열)
title = [
{
"type": "text",
"text": {
"content": "자동 생성 ToDo DB",
},
}
]
# 컬럼(프로퍼티) 정의
properties = {
# 필수: title 타입 컬럼 (DB 이름/row 이름 역할)
"이름": {
"title": {}
},
# 상태 선택(select)
"상태": {
"select": {
"options": [
{"name": "Todo", "color": "red"},
{"name": "Doing", "color": "yellow"},
{"name": "Done", "color": "green"},
]
}
},
# 마감일(date)
"마감일": {
"date": {}
},
# 태그(multi_select)
"태그": {
"multi_select": {
"options": [
{"name": "개발", "color": "blue"},
{"name": "문서화", "color": "purple"},
{"name": "리뷰", "color": "orange"},
]
}
},
# 우선순위(number)
"우선순위": {
"number": {
"format": "number"
}
},
}
# API 호출
db = notion.databases.create(
parent={
"type": "page_id",
"page_id": PARENT_PAGE_ID,
},
title=title,
properties=properties,
)
print("새 데이터베이스 생성 완료!")
print("DB ID:", db["id"])
return db["id"]
전체 main.py 예시는 아래와 같이 정리할 수 있습니다.
# main.py
import os
from dotenv import load_dotenv
from notion_client import Client
load_dotenv()
NOTION_TOKEN = os.getenv("NOTION_TOKEN")
PARENT_PAGE_ID = os.getenv("NOTION_PARENT_PAGE_ID")
if NOTION_TOKEN is None or PARENT_PAGE_ID is None:
raise RuntimeError("NOTION_TOKEN 또는 NOTION_PARENT_PAGE_ID 가 설정되어 있지 않습니다.")
notion = Client(auth=NOTION_TOKEN)
def create_todo_database():
title = [
{
"type": "text",
"text": {
"content": "자동 생성 ToDo DB",
},
}
]
properties = {
"이름": {"title": {}},
"상태": {
"select": {
"options": [
{"name": "Todo", "color": "red"},
{"name": "Doing", "color": "yellow"},
{"name": "Done", "color": "green"},
]
}
},
"마감일": {"date": {}},
"태그": {
"multi_select": {
"options": [
{"name": "개발", "color": "blue"},
{"name": "문서화", "color": "purple"},
{"name": "리뷰", "color": "orange"},
]
}
},
"우선순위": {
"number": {"format": "number"}
},
}
db = notion.databases.create(
parent={"type": "page_id", "page_id": PARENT_PAGE_ID},
title=title,
properties=properties,
)
print("새 데이터베이스 생성 완료!")
print("DB ID:", db["id"])
return db["id"]
if __name__ == "__main__":
create_todo_database()
이 스크립트를 실행하면, PARENT_PAGE_ID로 지정한 페이지 아래에 “자동 생성 ToDo DB” 라는 이름의 DB가 생기고, 설정한 컬럼들이 자동으로 만들어집니다.
3-6. 생성된 DB에 Row(페이지) 자동 추가 예제
“DB만 생기면 끝”보다는, Row까지 하나 넣어보면 전체 흐름을 이해하기 쉽습니다.
DB에 Row를 추가하는 것은 “페이지 생성 + parent를 database_id로 지정”입니다. (Notion API Documentation)
def add_sample_todo(database_id: str):
new_page = notion.pages.create(
parent={"database_id": database_id},
properties={
"이름": {
"title": [
{
"text": {"content": "API로 만든 할 일 1"},
}
]
},
"상태": {
"select": {"name": "Todo"}
},
"마감일": {
"date": {"start": "2025-11-30"}
},
"태그": {
"multi_select": [
{"name": "개발"},
{"name": "문서화"},
]
},
"우선순위": {
"number": 1
},
},
)
print("새 Row(페이지) 추가 완료!")
print("Page ID:", new_page["id"])
main을 조금 수정해서 DB 생성 후 바로 Row를 넣어보면:
if __name__ == "__main__":
db_id = create_todo_database()
add_sample_todo(db_id)
이제 스크립트를 실행하면:
- 부모 페이지 아래에 ToDo DB가 생성되고
- 그 DB 안에 “API로 만든 할 일 1”이라는 Row가 자동으로 들어갑니다.
4. 추가 팁 / 자주 하는 실수
- Integration을 페이지에 초대 안 함
- 토큰만 만들고, 실제 페이지에서 Share → Integration 초대를 안 하면
404,403에러가 나거나, 해당 페이지/DB를 못 찾습니다. (Notion API Documentation)
- 토큰만 만들고, 실제 페이지에서 Share → Integration 초대를 안 하면
- title 컬럼 누락
- DB 스키마에서
title타입 컬럼이 최소 1개는 있어야 합니다. - 위 예제에서
"이름": {"title": {}}가 그 역할입니다. 이거 안 넣으면 400 에러. (pynotion.com)
- DB 스키마에서
- 환경 변수/토큰 하드코딩
- 직접 코드에
NOTION_TOKEN = "..."라고 쓰기 시작하면 나중에 깃에 올라가서 사고 납니다. .env + python-dotenv조합으로 관리하는 습관을 들이는 게 좋습니다. (Velog)
- 직접 코드에
- API 버전/스키마 변경
- Notion API는 2025-09-03 버전 이후 데이터베이스/데이터 소스 분리 등 변경이 진행 중입니다. (Notion API Documentation)
- 공식 문서
Create a database/Working with databases를 수시로 확인하면서, 프로퍼티 스키마나 엔드포인트가 바뀌었는지 체크하는 것이 안전합니다. (Notion API Documentation)
- 대량 호출 시 rate limit
- 짧은 시간에 너무 많은 DB/페이지를 만들면
429 Too Many Requests가 떨어질 수 있습니다. (Notion API Documentation) - 이 경우
time.sleep()으로 간단히 딜레이를 주거나, retry 로직을 넣어야 합니다.
- 짧은 시간에 너무 많은 DB/페이지를 만들면
5. 정리
- Notion API에서는 Integration 토큰 + parent page id만 준비되면, Python에서
notion-client로 손쉽게 데이터베이스를 생성할 수 있습니다. (PyPI) - 핵심은
notion.databases.create(parent, title, properties)호출 시 최소 1개의title컬럼과 원하는 속성 스키마를 올바른 JSON 형식으로 넘기는 것입니다. - 그 다음에는
notion.pages.create(parent={"database_id": ...})를 이용해 Row를 자동으로 추가/업데이트하면서, Notion을 사실상 “간단한 클라우드 DB”처럼 사용할 수 있습니다.