대상: 앞에서 설계한 Notion
공부 로그 / 에러 로그 / ChatGPT 대화 로그DB에, Python 코드로 직접 기록을 남기고 싶은 개발자
환경: Notion 워크스페이스 + Notion API 사용 가능, Python 3.x,requests라이브러리 사용
앞에서 Notion 안에
- 공부 로그 DB
- 프로젝트 DB
- 에러/문제 로그 DB
- ChatGPT 대화 로그 DB
를 설계하고, Make 같은 자동화 툴로 워크플로우를 구상해봤다.
이제 개발자 입장에서는 자연스럽게 이런 생각이 든다.
“이거 그냥 Python으로 직접 Notion API 호출해서 기록하면 안 되나?”
당연히 된다. 오히려 내가 원하는 로직을 가장 유연하게 넣을 수 있는 방법이기도 하다.
이 글에서는:
- Notion API 연동 준비 (토큰, DB ID 찾기)
- Python +
requests로 Notion DB에 페이지 생성하는 최소 예제 - 앞에서 설계한
공부 로그구조에 맞게 필드 매핑하는 코드 - “ChatGPT가 요약해 준 공부 내용”을 Python 스크립트로 Notion에 넣는 흐름 예시
까지를 한 번에 정리해볼 거야.
1. Notion API 연동 준비 – 토큰과 database_id
Python 코드로 Notion에 글을 쓰려면 최소 두 가지가 필요하다.
- Integration Token (비밀 키)
- Database ID (어느 DB에 페이지를 만들지)
1-1. Integration 만들고 토큰 발급
Notion 설정 화면에서:
Settings & members→Connections또는My integrations메뉴 쪽에서- 새 Integration을 만든다. (Internal integration 기준)
- 생성 후 나오는 “Internal Integration Secret” 값을 복사해 둔다.
이 값이 바로 Python 코드에서 Authorization: Bearer ...로 넣을 토큰이다.
이 토큰은 절대 깃허브, 블로그 등 외부에 올리면 안 된다.
.env파일이나 환경 변수에 넣어 사용하는 걸 추천.
1-2. Database ID 찾기
앞에서 만든 공부 로그 DB 페이지를 브라우저에서 열고,
URL을 보면 대략 이런 형태일 거다.
https://www.notion.so/workspace-name/공부-로그-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
마지막에 붙은 긴 문자열(하이픈이 있거나 없을 수 있음)이 database_id다.
- 하이픈이 포함된 경우:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - Notion API는 하이픈이 있든 없든 대부분 처리해 준다.
이 값을 Python 코드에서 database_id로 사용하면 된다.
2. Python 환경 세팅 – 폴더 구조와 라이브러리
어디서든 상관 없지만, 예시로:
mkdir -p ~/dev/notion-logger
cd ~/dev/notion-logger
python3 -m venv venv
source venv/bin/activate
pip install requests python-dotenv
python-dotenv는 .env 파일에 토큰을 넣고 사용하는 데 편하다.
2-1. .env 파일에 비밀 값 넣기
프로젝트 폴더에 .env 파일을 만들고:
NOTION_TOKEN=secret_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
NOTION_STUDY_DB_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
NOTION_TOKEN: Integration SecretNOTION_STUDY_DB_ID:공부 로그DB의 ID
이렇게 해두면 코드 안에서는 하드코딩하지 않고 환경 변수로 읽을 수 있다.
3. Notion API에 페이지 생성하는 최소 Python 예제
이제 Python 코드로 Notion에 한 줄 기록을 보내보자.
notion_study_logger.py 파일을 만들고 아래 코드를 넣는다.
import os
import requests
from datetime import datetime
from dotenv import load_dotenv
# .env 파일 로드
load_dotenv()
NOTION_TOKEN = os.getenv("NOTION_TOKEN")
STUDY_DB_ID = os.getenv("NOTION_STUDY_DB_ID")
NOTION_API_URL = "https://api.notion.com/v1/pages"
NOTION_VERSION = "2022-06-28" # Notion API 버전
if NOTION_TOKEN is None or STUDY_DB_ID is None:
raise RuntimeError("NOTION_TOKEN 또는 NOTION_STUDY_DB_ID 환경 변수가 설정되어 있지 않습니다.")
def create_study_log(
title: str,
date: datetime,
topics: list[str],
tags: list[str],
summary: str,
detail: str | None = None,
):
"""
Notion '공부 로그' DB에 새 페이지를 생성하는 함수.
:param title: 공부 세션 제목
:param date: 공부한 날짜/시간
:param topics: 주제(리눅스, 시리얼, OpenCV 등) 리스트
:param tags: 태그(회사 업무, 시험, 블로그 초안 등) 리스트
:param summary: 한 줄 요약
:param detail: 상세 내용 (옵션)
"""
headers = {
"Authorization": f"Bearer {NOTION_TOKEN}",
"Content-Type": "application/json",
"Notion-Version": NOTION_VERSION,
}
# Notion DB 속성 이름은 실제 DB에 맞게 수정해야 한다.
# 예: "제목", "날짜", "주제", "태그", "요약", "상세 내용" 등
payload = {
"parent": {"database_id": STUDY_DB_ID},
"properties": {
"제목": { # Title 타입
"title": [
{
"text": {
"content": title,
}
}
]
},
"날짜": { # Date 타입
"date": {
"start": date.isoformat(),
}
},
"주제": { # Multi-select 타입
"multi_select": [{"name": t} for t in topics],
},
"태그": { # Multi-select 타입
"multi_select": [{"name": t} for t in tags],
},
"요약": { # Rich text 타입
"rich_text": [
{
"text": {
"content": summary,
}
}
]
},
},
}
# 상세 내용이 있다면 페이지 본문으로 넣기 (간단 버전: 'children' 블록 사용)
if detail:
payload["children"] = [
{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [
{
"type": "text",
"text": {
"content": detail,
},
}
]
},
}
]
response = requests.post(NOTION_API_URL, headers=headers, json=payload)
if response.status_code != 200:
print("[ERROR] Notion API 요청 실패")
print("Status:", response.status_code)
print("Body:", response.text)
else:
data = response.json()
page_id = data.get("id")
print("[INFO] 공부 로그 페이지 생성 완료")
print("Page ID:", page_id)
if __name__ == "__main__":
# 사용 예시: 우분투 18.04 시리얼 포트 공부 기록
create_study_log(
title="우분투 18.04 시리얼 포트 권한 에러 정리",
date=datetime.now(),
topics=["리눅스", "시리얼"],
tags=["회사 업무", "블로그 초안"],
summary="ttyUSB0 permission denied 에러 원인과 dialout 그룹 해결 과정을 정리.",
detail=(
"1) dmesg로 포트 이름 확인
"
"2) ls -l /dev/ttyUSB0로 권한 및 그룹 확인
"
"3) usermod -aG dialout $USER로 dialout 그룹 추가
"
"4) 재로그인 후 권한 문제 해결"
),
)
여기서 중요한 포인트는:
properties안의 각 키("제목","날짜","주제"등)를
실제 Notion DB 속성 이름과 똑같이 맞춰야 한다는 것.- 타입도 Title / Date / Multi-select / Rich text에 맞는 구조로 보내야 한다는 것.
앞에서 설계한 구조에 맞게 이미 DB를 만들어 두었다면,
속성 이름만 잘 맞춰 넣으면 바로 동작한다.
4. ChatGPT 요약 내용을 Python으로 Notion에 넣는 흐름 예시
실제 사용 시에는 이런 패턴이 자연스럽다.
- ChatGPT에서 공부/에러/시험 관련 대화를 한다.
- 대화 끝에 ChatGPT에게 “Notion 공부 로그에 기록할 요약”을 요청한다.
- 예:
제목, 주제 리스트, 태그 리스트, 한 줄 요약, 상세 설명을 각각 한 줄씩 출력해줘.
- 그 결과를 복사해서 Python 스크립트에 넘긴다. (CLI 인자, 파일, 입력 프롬프트 등)
4-1. 간단한 입력 프롬프트 버전
위의 create_study_log() 함수를 재활용해서,
사용자 입력을 받아 Notion에 기록하는 작은 스크립트를 만들어 보자.
# 파일명: notion_study_cli.py
import os
from datetime import datetime
from dotenv import load_dotenv
from notion_study_logger import create_study_log # 위에서 만든 함수 임포트
load_dotenv()
if __name__ == "__main__":
print("=== Notion 공부 로그 기록 ===")
title = input("제목: ").strip()
topics_raw = input("주제 (쉼표로 구분, 예: 리눅스, 시리얼): ").strip()
tags_raw = input("태그 (쉼표로 구분, 예: 회사 업무, 블로그 초안): ").strip()
summary = input("한 줄 요약: ").strip()
print("상세 내용(여러 줄 입력 후 Ctrl+D 로 종료):")
print("-------------------------------------------")
# 여러 줄 입력 받기
lines = []
try:
while True:
line = input()
lines.append(line)
except EOFError:
pass
detail = "
".join(lines)
topics = [t.strip() for t in topics_raw.split(",") if t.strip()]
tags = [t.strip() for t in tags_raw.split(",") if t.strip()]
create_study_log(
title=title,
date=datetime.now(),
topics=topics,
tags=tags,
summary=summary,
detail=detail if detail else None,
)
이제:
python notion_study_cli.py
를 실행하면,
- ChatGPT가 정리해 준 요약 내용을 복붙해서
- Notion
공부 로그DB에 바로 쌓을 수 있다.
5. ChatGPT 대화 로그 DB에 직접 기록하는 코드 구조
ChatGPT 대화 로그 DB도 같은 방식으로 만들 수 있다.
차이점은 필드 구성뿐이다.
예를 들어, 이런 필드가 있다고 하자.
제목(Title)날짜/시간(Date)카테고리(Select)세부 주제(Multi-select)요약(Rich text)질문/답변 핵심 정리(Rich text)잘한 점(Rich text)아쉬운 점(Rich text)
그렇다면 Python 함수는 이렇게 생긴다.
def create_chatgpt_log(
db_id: str,
title: str,
category: str,
topics: list[str],
summary: str,
detail: str,
good: str | None = None,
improve: str | None = None,
):
headers = {
"Authorization": f"Bearer {NOTION_TOKEN}",
"Content-Type": "application/json",
"Notion-Version": NOTION_VERSION,
}
payload = {
"parent": {"database_id": db_id},
"properties": {
"제목": {
"title": [{"text": {"content": title}}],
},
"날짜/시간": {
"date": {"start": datetime.now().isoformat()},
},
"카테고리": {
"select": {"name": category},
},
"세부 주제": {
"multi_select": [{"name": t} for t in topics],
},
"요약": {
"rich_text": [{"text": {"content": summary}}],
},
"질문/답변 핵심 정리": {
"rich_text": [{"text": {"content": detail}}],
},
},
}
# 선택 필드
if good:
payload["properties"]["잘한 점"] = {
"rich_text": [{"text": {"content": good}}],
}
if improve:
payload["properties"]["아쉬운 점"] = {
"rich_text": [{"text": {"content": improve}}],
}
response = requests.post(NOTION_API_URL, headers=headers, json=payload)
if response.status_code != 200:
print("[ERROR] ChatGPT 로그 생성 실패:", response.status_code)
print(response.text)
else:
print("[INFO] ChatGPT 로그 생성 완료")
이제 ChatGPT에게:
“이번 대화에 대해 아래 JSON 구조에 맞게 정리해줘.”
라고 하고, 그 JSON을 Python 코드에서 파싱해서
이 함수에 넣어주면 된다.
6. Make vs Python – 언제 무엇을 쓰면 좋을까?
앞에서 Make로 워크플로우를 설계했고,
이번 글에서는 Python으로 직접 API를 호출하는 예제를 만들었다.
둘 다 장단점이 있다.
- Make 쪽이 좋은 경우
- 코드 없이도 빠르게 “이런 흐름이 있으면 좋겠다”를 실험하고 싶을 때
- 여러 서비스(슬랙, 이메일, 폼 등)를 연결할 때
- 시간 기반 스케줄링(매일/매주 리포트)을 설정할 때
- Python 직접 호출이 좋은 경우
- 복잡한 로직, 조건 분기, 텍스트 처리(파싱, 포맷팅 등)이 많을 때
- Git으로 버전 관리하고, 테스트 코드도 같이 작성하고 싶을 때
- 내부 시스템, 사내 서버/스크립트와 긴밀하게 연동해야 할 때
실제로는:
“외부 트리거 + 간단한 연동”은 Make가,
“핵심 로직/가공”은 Python이 담당하는 하이브리드 구조
가 가장 현실적인 조합인 경우가 많다.
7. 정리 – 이제 Notion에 직접 “코드로 글을 쓰는” 단계까지 도달
이번 글에서 한 일을 정리해보면:
- Notion Integration 생성 → 토큰 발급
공부 로그DB의database_id를 찾고- Python +
requests로pagesAPI를 호출해서- 제목 / 날짜 / 주제 / 태그 / 요약 / 상세 내용을
실제 Notion DB 속성에 매핑하는 코드를 작성했다.
- 제목 / 날짜 / 주제 / 태그 / 요약 / 상세 내용을
- ChatGPT가 만들어 준 공부 요약/대화 요약을
- Python 스크립트에 입력해서,
- Notion에 자동으로 기록하는 흐름을 만들 수 있는 기반을 마련했다.
이제부터는:
- “그냥 좋은 대화/공부/삽질 결과가 지나가버리는 것”이 아니라
- Notion에 구조화된 로그로 남고,
- 필요하면 Python/자동화로 다시 꺼내서 재가공할 수 있는 상태가 된다.
앞으로 확장 아이디어로는:
- 특정 프로젝트와 자동으로 Relation 연결하기
- 정보처리기사/리눅스 시험 대비 전용 오답노트 DB와 연동하기
- 우분투/시리얼/카메라 샘플 코드를 Notion 코드블록으로 자동 업로드하기
같은 것들이 있고,
이제는 “API로 직접 쓸 수 있는 코드 기반”이 있으니
원할 때마다 천천히 하나씩 붙여나가면 된다.