back

notion 200b blocks

Notion이 2000억 개 노트를 처리하는 방법 (크래시 없이)

이 글은 위의 Notion 엔지니어링 팀 공식 블로그 포스트와 기술 커뮤니티 분석 자료를 바탕으로 작성되었습니다.

들어가며

Notion은 단순한 노트 앱이 아니다. 실시간 협업 데이터베이스가 미니멀한 UI로 포장된 것이다. 2021년 200억 개의 블록에서 시작해 2024년 현재 2000억 개 이상의 블록을 처리한다. 압축된 상태에서도 수백 테라바이트에 달하는 데이터다.

어떻게 이런 규모의 데이터를 크래시 없이 처리할 수 있을까? 답은 블록 기반 아키텍처, 데이터베이스 샤딩, 그리고 데이터 레이크에 있다.

블록(Block) 기반 아키텍처

모든 것이 블록이다

Notion에서 보이는 모든 것은 블록이다:

각 블록은 PostgreSQL에 다음과 같은 구조로 저장된다:

CREATE TABLE blocks (
    id UUID PRIMARY KEY,
    type VARCHAR(50), -- 'paragraph', 'checkbox', 'image' 등
    parent_id UUID,   -- 부모 블록 (중첩 구조)
    workspace_id UUID, -- 샤딩 키
    properties JSONB  -- 유연한 콘텐츠 저장
);

블록의 특징

--- title: Concept of Blocks in Notion --- flowchart TD Block[Block<br/>기본 블록] Page[Page<br/>페이지 블록] List[List<br/>리스트 블록] Image[Image<br/>이미지 블록] Block --> Page Block --> List Block --> Image Page ~~~ Description List ~~~ Description Image ~~~ Description Description[A block can be of different types.<br/>It is rendered on the UI based on its type] style Block fill:darkorange,color:white style Description fill:none,stroke:none,color:#666

데이터베이스 샤딩 전략

초기 문제점

2020년 중반까지 Notion은 단일 PostgreSQL 인스턴스를 사용했다. 5년간 10,000배 성장(4 orders of magnitude)을 견뎌냈지만 한계가 보였다:

샤딩 설계

워크스페이스 ID를 샤딩 키로 선택

샤딩 구성

480이라는 숫자를 선택한 이유:

마이그레이션 전략

3단계 마이그레이션 프로세스

  1. 더블 라이트 (Double Write)

    • 모든 새 쓰기 작업을 기존 DB와 새 샤드에 동시 적용
    • 직접 쓰기 대신 감사 로그 사용으로 일관성 보장
  2. 백필 (Backfill)

    • 96 CPU 머신으로 기존 데이터 마이그레이션
    • 3일간 지속적인 데이터 이전 작업
  3. 검증 및 전환

    • 검증 스크립트: 랜덤 UUID 샘플링으로 데이터 무결성 확인
    • 다크 리드: 구 DB와 신 DB 동시 쿼리 후 결과 비교
    • 최종 전환: 5분 다운타임으로 완전 전환

Redis 태스크 큐 시스템

대규모 비동기 처리 인프라

Notion은 12개의 Redis 서버로 구성된 클러스터를 운영하며, 상시 약 1억 개의 태스크를 관리하고 있다. 초당 최대 10,000개의 태스크를 큐에 추가하는 처리 능력을 보유한다.

주요 활용 사례

아키텍처 개선 2024년 큐 프록시 서비스 도입으로 관찰 가능성과 확장성을 크게 향상시켰다:

성능 최적화 기술

연결 풀링 최적화

PgBouncer 클러스터링

해결책

실시간 데이터 처리

Apache Kafka 활용

전체 인프라 아키텍처

아래 다이어그램은 Notion 사용자 요청을 실시간으로 처리하는 핵심 서비스들을 보여줍니다:

flowchart TD subgraph A[" "] direction TB A0[🌐 Client & API Layer] A1[Web Browser] A2[Mobile App] A3[Desktop App] A4[Load Balancer] A5["`**API Server** Node.js`"] A6[Redis Cache] A0 ~~~ A1 end subgraph B[" "] direction TB B0[💾 Database & Search] B2[Elasticsearch Search] B2 ~~~ BD subgraph BD[" "] B1["`PgBouncer Cluster 100 Instances`"] B3["`**PostgreSQL Shard** RDS x 24 (1-24)`"] B4["`**PostgreSQL Shard** RDS x 24 (25-48)`"] B5["`**PostgreSQL Shard** RDS x 24 (49-72)`"] B6["`**PostgreSQL Shard** RDS x 24 (73-96)`"] end B7["`480 Logical Shards 96 x 5`"] B0 ~~~ B1 end subgraph C[" "] direction TB C0[🚀 Redis Task Queue System] C1[Queue Proxy Service] C2[12 Redis Servers<br/>100M Tasks] C3[Queue Workers] C0 ~~~ C1 end A1 --> A4 A2 --> A4 A3 --> A4 A4 --> A5 A5 --> A6 A5 --> B1 A5 --> B2 A5 --> C1 B1 -->|"Connection Pool"| B3 B1 -->|"Connection Pool"| B4 B1 -->|"Connection Pool"| B5 B1 -->|"Connection Pool"| B6 B3 -.-> B7 B4 -.-> B7 B5 -.-> B7 B6 -.-> B7 C1 --> C2 C2 --> C3 style A0 fill:#3b82f6,stroke:#ffffff,stroke-width:2px,color:#ffffff style B0 fill:#10b981,stroke:#ffffff,stroke-width:2px,color:#ffffff style C0 fill:#f59e0b,stroke:#ffffff,stroke-width:2px,color:#ffffff style BD fill:none,stroke:#ff8c00,stroke-width:2px,stroke-dasharray: 5 5

핵심 컴포넌트 설명

1. API 계층

2. 데이터베이스 계층

3. 실시간 파이프라인

데이터 레이크 아키텍처

기존 시스템의 한계

Snowflake 기반 ETL 문제점

새로운 데이터 레이크 설계

PostgreSQL → Kafka → Apache Hudi → S3 → Snowflake

핵심 컴포넌트

성능 최적화

파티셔닝 전략

데이터 신선도

권한 시스템의 복잡성

트리 기반 권한 계산

블록의 권한은 워크스페이스 루트까지 트리를 순회하여 계산된다:

workspace_a
└── page_1
    └── page_2
        └── page_3
            ├── block_1
            ├── block_2
            └── block_3

각 블록은 부모와 조상으로부터 권한을 상속받는다. 수백억 개의 블록과 수십 단계의 깊이를 가진 트리에서 이런 계산은 매우 비용이 크다.

해결책: 비정규화된 뷰

결과와 성과

성능 개선

확장성 확보

핵심 교훈

1. 조기 샤딩 계획

성능 문제가 심각해지기 전에 샤딩을 시작하라. 위기 상황에서의 마이그레이션은 복잡도와 스트레스를 증가시킨다. Notion은 데이터베이스 과부하 상태에서 이상적인 마이그레이션 도구(논리적 복제, 스트리밍 복제 등) 사용이 불가능했고, 트랜잭션 ID 고갈이라는 시스템 전체 정지 위험 하에서 3일간 백필 작업을 수행해야 했다.

2. 워크스페이스 ID 샤딩 키

3. 보링 테크 선택

Notion의 벤더 락인 방지 전략:

이로 인해 Notion은 특정 벤더에 종속되지 않고 필요시 다른 클라우드 제공업체로 마이그레이션할 수 있는 유연성을 확보했다.

4. 단계적 마이그레이션

미래 전망

예상 확장 포인트

아키텍처 원칙

  1. 샤딩: 명확한 키로 조기 계획
  2. 데이터 레이크: OLTP와 분석 분리
  3. 오픈소스: 벤더 락인 방지

마무리

Notion의 성공 비결은 단순한 기술 스택이 아니라 점진적이고 신중한 확장 전략에 있다. 블록 기반 아키텍처, 워크스페이스 중심 샤딩, 그리고 업데이트 중심 워크로드에 최적화된 데이터 레이크가 핵심이다.

가장 중요한 것은 문제가 심각해지기 전에 미리 준비하는 것이다. Notion은 이를 통해 200억 개에서 2000억 개로 10배 성장하면서도 안정적인 서비스를 제공할 수 있었다.

참고 자료

Notion 공식 블로그

기술 분석 아티클

커뮤니티 토론