Python으로 Notion API 연동해서 공부 로그 자동 기록하기

대상: 앞에서 설계한 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에 글을 쓰려면 최소 두 가지가 필요하다.

  1. Integration Token (비밀 키)
  2. Database ID (어느 DB에 페이지를 만들지)

1-1. Integration 만들고 토큰 발급

Notion 설정 화면에서:

  1. Settings & membersConnections 또는 My integrations 메뉴 쪽에서
  2. 새 Integration을 만든다. (Internal integration 기준)
  3. 생성 후 나오는 “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 Secret
  • NOTION_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에 넣는 흐름 예시

실제 사용 시에는 이런 패턴이 자연스럽다.

  1. ChatGPT에서 공부/에러/시험 관련 대화를 한다.
  2. 대화 끝에 ChatGPT에게 “Notion 공부 로그에 기록할 요약”을 요청한다.
    • 예:

제목, 주제 리스트, 태그 리스트, 한 줄 요약, 상세 설명을 각각 한 줄씩 출력해줘.

  1. 그 결과를 복사해서 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에 직접 “코드로 글을 쓰는” 단계까지 도달

이번 글에서 한 일을 정리해보면:

  1. Notion Integration 생성 → 토큰 발급
  2. 공부 로그 DB의 database_id를 찾고
  3. Python + requestspages API를 호출해서
    • 제목 / 날짜 / 주제 / 태그 / 요약 / 상세 내용을
      실제 Notion DB 속성에 매핑하는 코드를 작성했다.
  4. ChatGPT가 만들어 준 공부 요약/대화 요약을
    • Python 스크립트에 입력해서,
    • Notion에 자동으로 기록하는 흐름을 만들 수 있는 기반을 마련했다.

이제부터는:

  • “그냥 좋은 대화/공부/삽질 결과가 지나가버리는 것”이 아니라
  • Notion에 구조화된 로그로 남고,
  • 필요하면 Python/자동화로 다시 꺼내서 재가공할 수 있는 상태가 된다.

앞으로 확장 아이디어로는:

  • 특정 프로젝트와 자동으로 Relation 연결하기
  • 정보처리기사/리눅스 시험 대비 전용 오답노트 DB와 연동하기
  • 우분투/시리얼/카메라 샘플 코드를 Notion 코드블록으로 자동 업로드하기

같은 것들이 있고,
이제는 “API로 직접 쓸 수 있는 코드 기반”이 있으니
원할 때마다 천천히 하나씩 붙여나가면 된다.

댓글 남기기