Notion 백업은 실제로 어떻게 이루어지는가

백업은 백업을 위해 설계된 적이 없는 API에 긴 요청을 연달아 보내는 작업입니다. 그 API가 무엇을 돌려주고 무엇을 돌려주지 않는지 정확히 알아야 신뢰할 수 있는 사본을 얻습니다.

token에서 시작합니다

Notion은 인테그레이션으로 누가 무엇을 읽을 수 있는지 정합니다. 내부 인테그레이션을 만들면, 그 인테그레이션은 공유한 페이지와 데이터베이스만 읽습니다. 워크스페이스의 다른 내용은 읽지 않고, 공유하기 전에는 아무것도 읽지 않습니다. token은 그 인테그레이션을 식별합니다.

NotionManager가 쓰는 접근 모델은 이것이 전부입니다. Notion 비밀번호도, 모든 것을 읽을 수 있는 워크스페이스 단위 키도, 공유하지 않은 페이지에 대한 접근도 없습니다. 인테그레이션이 무엇을 읽을 수 있는지는 공유 목록이 정합니다. Notion은 다른 모든 도구에도 같은 규칙을 적용합니다. Notion에서 인테그레이션을 취소하면 이후의 모든 실행이 즉시 실패합니다.

다음은 API가 정합니다

Notion API는 block과 페이지를 향한, 페이지 단위로 나뉜 읽기 인터페이스입니다. 결과를 페이지당 최대 100개씩 돌려주고, 초당 보낼 수 있는 요청 수를 제한합니다. 표현할 수 있는 것은 온전히 돌려줍니다. 표현할 수 없는 것은 내용을 추측하지 않고 block만 알려줍니다.

페이지 나누기, 호출 제한, 돌려주지 못하는 내용이 모든 Notion 백업의 설계를 결정합니다. 그래서 백업은 한 번의 요청이 아니라 속도를 조절한 순회입니다. 큰 워크스페이스에서는 몇 분, 십여 분, 때로는 그 이상 걸립니다. NotionManager는 진행 상황을 실시간으로 보여 주므로 사본이 어디까지 왔는지 알 수 있습니다.

Notion은 결함을 고치고 기능을 더하고 데이터 구성 방식을 개선하기 위해 API를 계속 갱신합니다. NotionManager는 최신 버전의 API 위에 만들어졌으므로, 백업이 담을 수 있는 정보를 최대한 담습니다.

백업이 복사하는 데이터 모델

Notion의 모든 것은 block으로 만들어집니다. 문단, 제목, 할 일, 토글, 표의 한 행은 모두 block입니다. 페이지도 block이며 다른 block을 담습니다. 그래서 Notion에서 읽는 모든 것은 block 트리입니다. 백업도 같은 방식으로 이 트리를 읽습니다. 한 노드에서 시작해 자식을 읽고, 다시 반복합니다.

데이터베이스는 페이지를 담는 그릇입니다. 내용은 하나 이상의 데이터 소스에 있고, 데이터 소스의 각 행이 하나의 페이지이며 그 속성은 해당 데이터 소스가 정의합니다. 뷰는 데이터를 직접 담지 않습니다. 데이터를 어떻게 볼지 정의합니다. 어느 데이터 소스인지, 어떤 필터와 정렬을 쓰는지, 표·보드·캘린더·갤러리 중 무엇으로 보여 주는지입니다. Notion API는 뷰의 핵심 구조를 돌려주고 스타일은 돌려주지 않습니다.

NotionManager가 워크스페이스를 읽는 방식

위에서 아래로 한 번 순회하며, API가 더 이상 결과를 돌려주지 않을 때까지 이어집니다.

  1. 1

    공유한 것에서 시작합니다

    integration token은 공유한 최상위 페이지와 데이터베이스를 노출합니다. 이것이 순회의 출발점입니다.

  2. 2

    각 항목을 끝까지 읽습니다

    NotionManager는 각 출발점을 속성과 block까지 함께 가져오고, 페이지 나누기가 끝날 때까지 한 페이지씩 읽어 빠뜨리는 것이 없습니다.

  3. 3

    자식 페이지를 따라 내려갑니다

    가는 길에 만난 모든 자식 페이지를 차례로 재귀적으로 가져오고, 자식 페이지가 더 이상 없을 때까지 이어갑니다.

  4. 4

    구조를 다시 세우고, 다시 읽습니다

    NotionManager는 읽은 내용을 페이지, 데이터베이스, 관계로 다시 그립니다. 그 결과는 JSON 더미가 아니라, Notion과 거의 같은 감각으로 오프라인에서 넘겨 볼 수 있는 읽기 전용 사본입니다.

API가 하지 않는 일, 그리고 대신 일어나는 일

Notion API의 제한NotionManager의 대응
API는 요청 수를 제한하므로 백업이 더 오래 걸립니다NotionManager는 요청 속도를 조절하고 제한에 부딪히면 기다리므로 사본은 온전하게 유지됩니다
일부 block 유형은 API가 내용 없이 알려줍니다읽을 수 있는 원본 데이터는 모두 남기고, 렌더링할 때 빠진 부분을 표시합니다. 그래서 빈틈이 조용히 생기지 않고 눈에 보입니다
뷰의 복잡한 스타일: 색상, 레이아웃, 그룹화, 실제로 보는 보드나 갤러리NotionManager는 뷰 뒤의 데이터를 복사하고 속성에서 뷰를 다시 만듭니다. Notion의 동작을 최대한 비슷하게 재현합니다
변경 피드가 없습니다: API는 "이 세 페이지가 화요일 이후 바뀌었다"고 말할 수 없습니다증분·차분 백업은 아직 제공하지 않으므로, 매 실행이 모든 페이지와 모든 block을 순회합니다. 바뀌지 않은 block은 디스크 공간을 더 쓰지 않고, 외부 미디어 파일도 중복을 제거해 보관하므로 디스크 사용량은 관리됩니다
쓰기 되돌림이 없습니다: API가 워크스페이스를 복원해 줄 수 없습니다백업 복원은 직접 지원하지 않습니다. 복원을 내세우는 모든 백업 도구는 워크스페이스를 완전히 다시 만들며, 새 id, 사라진 관계 같은 큰 제약을 안고 갑니다. NotionManager는 설계상 복원을 지원하지 않습니다
인테그레이션에 공유하지 않은 모든 것아무것도 없습니다. 사본에는 공유한 페이지가 정확히 그대로 들어갑니다. NotionManager는 그중 일부로 범위를 더 좁힐 수 있지만, 그 범위를 넘을 수는 없습니다

NotionManager로 백업하세요

인테그레이션을 만들고 페이지나 데이터베이스를 공유한 다음, 첫 사본이 나타나는 것을 확인하세요.

다음에 볼 내용

자주 묻는 질문

NotionManager에 Notion 비밀번호가 필요한가요?

아니요. integration token을 사용하며, 그 인테그레이션은 명시적으로 공유한 내용만 읽을 수 있습니다. 워크스페이스 전체 자격 증명은 쓰지 않습니다.

백업에 왜 몇 분, 때로는 그 이상 걸리나요?

첫째, Notion API는 호출 속도를 엄격히 제한하므로 백업을 빠르게 하려는 시도는 동시 호출로 이어져 제한에 걸립니다. 둘째, 모든 백업은 전체 읽기입니다. 데이터를 다시 내려받을 필요가 없더라도 사본이 온전한지 확인하려면 모든 페이지와 모든 block을 순회해야 합니다.

바뀐 부분만 백업할 수 있나요?

Notion API는 마지막 백업 이후 바뀐 모든 것의 목록을 안정적으로 주지 않습니다. 그래서 매 실행이 전체 백업이며, NotionManager는 중복되는 데이터가 한 번만 저장되도록 처리합니다.

API가 설명하지 않는 block은 어떻게 되나요?

NotionManager는 그 block이 선언한 유형과 트리에서의 위치를 기록합니다. 그래서 빈틈은 페이지 한가운데 조용히 뚫린 구멍이 아니라, 넘겨 볼 수 있는 사본에서 눈에 보입니다.