Skip to content

필사 모드: リアルタイム協業 & CRDT 2026 ディープダイブ — Liveblocks・PartyKit・Yjs・Automerge・Loro・ShareDB・Replicache・Fluid・Tldraw sync

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

プロローグ — 2026年、「一緒に編集する」とはどういうことか

2010年にGoogle Docsが一般ユーザーに「同じ文書を同時に編集する」を届けたとき、その技術はOT(Operational Transform)だった。ある人の編集操作を別の人の編集操作に合わせて「変換」する方式である。動作はしたが、サーバ中心であり、オフラインは難しく、誤った変換関数は永遠にデバッグを強いた。

2026年5月、風景は完全に逆転した。**CRDT(Conflict-free Replicated Data Type)** がウェブ協業の基本単位になった。Figmaのマルチプレイヤー基盤、Linearのローカルファースト同期、Notionのライブカーソル、tldrawのリアルタイムキャンバス、Excalidrawのルーム同期 — これらすべてがCRDTまたはその変種の上に成り立っている。

そしてさらに大きな変化が二つある。

- **2025年11月**、VercelがLiveblocksとPartyKitを相次いで密接なパートナーとして取り込み、「Vercel for Realtime」というポジショニングを固めた。

- **Ink & Switch研究所**が発表した「Local-first software」のマニフェストはもはや学術的好奇心ではない。Automerge 2.x・Loro・Yrs(YjsのRustポート)が実サービスに乗った。

本稿は2026年のリアルタイム協業スタックを一気通貫で整理する。理論(CRDT vs OT、ベクタークロック、Lamport)からライブラリ比較(Yjs vs Automerge vs Loro)、SaaS比較(Liveblocks vs PartyKit vs Hocuspocus)、運用パターン(WebSocket vs WebRTC、awareness、永続化)まで。

第1章 · 同時編集の本質 — 同じ文書、別の時間線

まず問題を定義しよう。二人の人が同じ文書を同時に編集するというのは、計算機科学的には「同じ状態に二つの独立した操作が加わる」ことを意味する。

時刻 t0: "Hello" (サーバ = クライアントA = クライアントB)

時刻 t1: クライアントAが位置5に ", world" を挿入

時刻 t1: クライアントBが位置0に "Say: " を挿入

(互いに知らない)

時刻 t2: 二つの操作がサーバで出会う

-> 結果はどうあるべきか?

答えは二つある。**OT**は「二つの操作を互いの座標系に合うように変換する」。**CRDT**は「座標を最初から絶対的・一意のIDで打ち、操作をそのまま適用する」。

OTはサーバという単一の真実の源を仮定するが、CRDTはサーバ無しでもすべてのクライアントが最終的に同じ状態に収束する(これを**eventual consistency**と呼ぶ)。ローカルファーストソフトウェアの前提条件は、まさにこれだ。

第2章 · CmRDT vs CvRDT — 操作か状態か

CRDTは大きく二種類に分かれる。

- **CmRDT(Operation-based)**: 操作(operation)を伝播する。「位置5に 'x' を挿入」というメッセージを送る。メッセージサイズは小さいが、**正確に一回配送(exactly-once)** または因果順序(causal order)の保証が必要。

- **CvRDT(State-based)**: 状態(state)全体または一部を伝播する。同期時にマージ関数が二つの状態を結合する。マージ関数は**可換・結合・冪等(commutative, associative, idempotent)** でなければならない。

YjsとAutomergeはどちらもop-basedで始まったが、2026年のLoro・Y-CRDT・Automerge 2.xは**delta-state**またはハイブリッドモデルへ進化した。差分のみを送るが、冪等に適用できる形で。

| 種類 | メッセージサイズ | ネットワーク保証 | 代表的ライブラリ |

| --- | --- | --- | --- |

| CmRDT | 小 | 因果順序 + at-least-once | 初期 Treedoc, RGA |

| CvRDT | 大 | best-effort, 冪等 | 初期 Riak DT |

| Delta-state | 中 | 冪等 + 因果メタ | Yjs, Automerge 2.x, Loro |

第3章 · OT vs CRDT — なぜCRDTが勝ったのか

| 基準 | OT | CRDT |

| --- | --- | --- |

| 中央サーバ要否 | 実質必要 | 不要(P2P可能) |

| オフライン編集 | 難しい | 自然 |

| 変換関数の検証 | 非常に困難(TP2問題) | 不要 |

| メモリ使用量 | 小 | 大(メタデータ蓄積) |

| テキストCRDTの成熟度 | 2000年代に検証済 | 2020年代に検証済 |

| 代表的な採用 | Google Docs(歴史的) | Figma, Linear, Notion ライブカーソル |

Google Docsは今もOTを使う(レガシー + 検証済みインフラ)。しかし2020年代以降の新規協業アプリはほぼすべてCRDTを選んだ。最大の理由は**オフライン対応**と**P2P可能性**である。

第4章 · ベクタークロックとLamport timestamp — 分散時間の二つの顔

分散システムには絶対時間が無い。そこで二つの道具が使われる。

- **Lamport timestamp**: すべてのイベントに単調増加する整数を付与する。二つのノードの時間を比較するにはmax + 1。全順序(total order)は作れるが、二つのイベントが同時(concurrent)かは分からない。

- **Vector clock**: ノード別カウンターをすべて持ち歩く。`[A:3, B:2, C:1]`。二つのベクトルを比較すれば「先行/後行/同時」の三つから一つを確定できる。

Yjsは**各クライアントが一意IDを持ち、ID + 単調シーケンス**の組み合わせで操作を識別する(実質Lamport + client-id)。Automergeはアクター(actor) IDとシーケンス番号の組み合わせ(ベクタークロックの変種)を使う。Loroもactor + counterモデル。

第5章 · テキストCRDTの理論 — Yjs Y.Textの内部

テキストはCRDTの中で最も難しい。「位置5に 'x' を挿入」というインデックスベースの操作は同時編集で崩れる(他人が位置4に何か入れたら位置5は位置6になる)。だからCRDTは**一意ID基盤の位置指定**を使う。

YjsのY.Textはすべての文字に `(clientID, clock)` ペアを付与し、それを**双方向連結リスト(double-linked list of Items)** で繋ぐ。挿入は「このIDの次に入れろ」となり、削除はtombstone(削除マーク)として残る。同位置の同時挿入はclientIDで決定論的順序を作る。

// Yjs: 同じ文書を二人で編集する

// クライアントA

const docA = new Y.Doc()

const textA = docA.getText('content')

textA.insert(0, 'Hello')

// クライアントB(オフラインで)

const docB = new Y.Doc()

const textB = docB.getText('content')

Y.applyUpdate(docB, Y.encodeStateAsUpdate(docA))

textB.insert(5, ', world')

// 同時に、クライアントAでも

textA.insert(0, 'Say: ')

// 両方の差分を相互に伝達

Y.applyUpdate(docA, Y.encodeStateAsUpdate(docB))

Y.applyUpdate(docB, Y.encodeStateAsUpdate(docA))

// 二つの文書が同じ状態へ収束する

console.log(textA.toString()) // "Say: Hello, world"

console.log(textB.toString()) // "Say: Hello, world"

このコードの核は `encodeStateAsUpdate` と `applyUpdate` である。どの順序で、何回、どの経路で適用しても結果は同じ。冪等で、可換で、結合的だ。

第6章 · Yjsの内部構造 — Itemリンクドリストと GC

Yjsの中心的データ構造は `Item` である。各Itemは:

- `id: { client: number, clock: number }` — 一意識別子

- `origin: ID | null` — 「このItemはどのItemの次に挿入されたか」

- `rightOrigin: ID | null` — 同時挿入衝突解決用

- `content: ContentString | ContentEmbed | ...` — 実際の値

- `deleted: boolean` — tombstoneフラグ

メモリ爆発を防ぐためYjsは**GC**を行う。すべてのクライアントが見届けた削除は実際にtombstoneから消去される。また隣接する同一クライアントのItemを**ブロック単位で圧縮**する(例: 一度に 'Hello' と打った5個のItemを一つに)。

ベンチマークではYjsは一貫して最速のテキストCRDTの一つだ。100万文字の文書でもメモリ・CPUが実用水準に収まる。

第7章 · Automerge — JSON CRDTの標準

AutomergeはYjsとほぼ同時期に始まったが、**JSON文書全体**をCRDTとして扱うことに焦点を当てる。テキストも対応するが(`Automerge.Text` → 最近はsplice ベースAPI)、強みは深くネストしたオブジェクトツリーのマージだ。

// Automerge: 同じJSON文書を二人で編集する

// 初期文書

let doc1 = from({

title: 'Realtime collab notes',

todos: [{ done: false, text: 'Write CRDT post' }],

})

// シリアライズして他クライアントへ

const binary = save(doc1)

let doc2 = load(binary)

// 両側で同時編集

doc1 = change(doc1, (d) => {

d.todos.push({ done: false, text: 'Add references' })

d.title = 'Realtime collab notes (draft)'

})

doc2 = change(doc2, (d) => {

d.todos[0].done = true

})

// 両方向にマージ

const merged1 = merge(doc1, doc2)

const merged2 = merge(doc2, doc1)

// 二つの結果は同一

console.log(JSON.stringify(merged1) === JSON.stringify(merged2)) // true

Automerge 2.xはRustで書き直され(`automerge-rs`)、WASMでブラウザ・Node・Electronすべてで走る。メモリ・速度が1.x比で一桁向上した。

第8章 · Loro — 2024-2026のダークホース

Loroは中国発の新興CRDTライブラリで、2024年に1.0を達成し、2026年にはYjs・Automergeと並んで「ビッグ3」に数えられる。特徴は:

- 最初からRust + WASM

- **タイムトラベル(time travel)** を一級機能に — 任意時点の文書状態へ巻き戻し

- リッチテキストマークCRDT(スタイル範囲)を別データ構造で精密に処理

- ツリーCRDT(親子関係の同時移動)を真剣に扱う

ベンチマークによればLoroは特定のワークロード(特にツリー・リッチテキスト)でYjsより速い。一方Yjsはテキスト単純編集・エコシステム・教材で依然優位。

第9章 · Liveblocks — CRDT-as-a-Serviceの第一人者

Liveblocks(パリ拠点)は「**マルチプレイヤー基盤をSaaSで**」という命題を最初に捉えた。2026年時点の主機能:

- `LiveObject`・`LiveList`・`LiveMap` — 独自CRDT(Yjsとは別)

- `useStorage` / `useMutation` — Reactフックで状態同期

- **Awareness/Presence** — カーソル・名前・選択範囲のリアルタイム共有

- **Comments・Threads** — 文書上にコメントを付ける別モジュール

- **Yjsアダプタ** — 既存Yjsアプリ(Tiptap・BlockNote・Lexical Yjs)もLiveblocksトランスポートで同期可能

// Liveblocks: useStorageフックで共有状態を読み書き

function Todos() {

const todos = useStorage((root) => root.todos)

const addTodo = useMutation(({ storage }, text: string) => {

const list = storage.get('todos')

list.push({ id: crypto.randomUUID(), text, done: false })

}, [])

const toggle = useMutation(({ storage }, id: string) => {

const list = storage.get('todos')

const idx = list.findIndex((t) => t.id === id)

if (idx >= 0) {

const item = list.get(idx)

list.set(idx, { ...item, done: !item.done })

}

}, [])

return (

{todos.map((t) => (

{t.done ? 'X' : 'O'} {t.text}

))}

)

}

Liveblocksの強みは**運用の簡潔さ**と**Reactに最適化されたDX**。弱点は価格(席単位・MAU単位課金)と独自CRDTへのロックイン(完全な自己ホスティングは難しい)。

第10章 · PartyKit — Cloudflare Durable Objects上の協業

PartyKit(2023年Sunil Pai創業、2024年Cloudflare買収)は別の道を行く。**各協業ルームが一つのDurable Object**で、その中に任意のコード(Yjs・Automerge・独自ロジック)を走らせる。

// PartyKit: サーバコード (server.ts)

export default class YjsServer implements Party.Server {

constructor(readonly room: Party.Room) {}

async onConnect(conn: Party.Connection) {

// y-partykitがYjs同期を自動処理

return onConnect(conn, this.room, {

persist: { mode: 'snapshot' },

})

}

}

PartyKitの強みは**ユーザコードをエッジで実行**できる点。ルーム単位で認証・権限・永続化・ゲームロジックを自由に書ける。弱点はCloudflareロックイン(2026年現在ではむしろ強みでもある — グローバルエッジ分散が無料)。

第11章 · 自己ホスティング — Hocuspocus + Yjs

コスト・ロックインが負担なら**Hocuspocus**が答え。Tiptapチームが作ったYjsバックエンドで、Node.jsで動き、Postgres・SQLite・Redisで永続化する。

// Hocuspocusサーバ

const server = new Server({

port: 1234,

extensions: [

new Database({

fetch: async ({ documentName }) => {

// DBからYjsバイナリをロード

const row = await db.documents.findUnique({ where: { name: documentName } })

return row?.state ?? null

},

store: async ({ documentName, state }) => {

// DBへ保存

await db.documents.upsert({

where: { name: documentName },

update: { state, updatedAt: new Date() },

create: { name: documentName, state },

})

},

}),

],

async onAuthenticate({ token, documentName }) {

// JWT検証など

if (!verifyToken(token)) throw new Error('Unauthorized')

return { userId: extractUserId(token) }

},

})

server.listen()

運用を自前で握れデータ主権が確保される。代わりにスケーリング・HA・モニタリングは自前。Notion・Linear級になると結局自社インフラを書くことになる。

第12章 · ShareDB — OT陣営の生存者

ShareDB(旧derby-share)は**OTベース**の自己ホスティングライブラリだ。Yjs以前の時代(2015年前後)の協業アプリで広く使われ、今もOTに慣れたチームでは現役だ。

- 文書をJSONで表現し、JSON OT操作を伝播

- MongoDB・Postgresに永続化

- テキストOT(`json0`・`json1` タイプ)は検証済

- 弱点: P2P・オフラインがCRDTほど自然ではない

2026年の新規プロジェクトならCRDT(Yjs/Automerge/Loro)を選ぶのが一般的な推奨だが、**既にShareDBで順調に動いているシステム**を無理に置き換える理由は無い。

第13章 · Replicache・Zero — 「ローカルファースト同期エンジン」の別解

RocicorpのReplicache(2020-)と後継のZero(2025-)はCRDTではない。**mutator方式の同期 + サーバ権威 + 楽観UI**というモデルだ。

- クライアントが「mutator」関数を定義する(例: `addTodo(text)`)

- mutatorをローカルで即実行しUIを更新

- 同じmutatorリクエストをサーバへ送り、サーバで権威的に再実行

- サーバ結果が届いたらローカル結果が上書きされる(ロールバック可能)

CRDTが「複数の真実が最終的に収束」なら、Replicacheは「サーバが最終真実、クライアントは楽観的推測」。Linearがこのモデルで有名になった。

第14章 · Fluid Framework — Microsoftのエンタープライズ解

Fluid FrameworkはMicrosoft 365(Office Online・Loop)のリアルタイム協業エンジン。CRDTではないが**シーケンスベース**の独自同期モデルだ。

- **SharedString**・**SharedMap**・**SharedTree**などの分散データ構造(DDS)

- Azure Fluid Relay上で動くサービス

- 外部開発者には扱いにくく(公式SDKはある)、実質Microsoft内部エンジン

2026年に外部新規アプリがFluidを採用する可能性は低いが、Office連携・Microsoft Graph上で協業を組むなら知っておく価値がある。

第15章 · ホワイトボード協業 — TldrawとExcalidraw

tldraw(@steveruizok・@orta)はホワイトボード・ダイアグラムライブラリで、マルチプレイヤーsyncエンジンを自社開発した。内部的にはYjsに似たop-basedモデルだが、キャンバスデータ構造(シェイプツリー)に最適化されている。`@tldraw/sync` パッケージでReact + WebSocketサーバでルーム同期し、Cloudflare Durable Objects上で動くリファレンス実装があり、シェイプ単位の最終書き込み者優先(LWW)で描画ツールの意味論に合わせている。

一方Excalidrawは手描きホワイトボードの代名詞で、協業ルーム機能は**暗号化されたFirebase Realtime Database**上で動く。CRDTを正式には使わず、単純なLWWとクライアント側変更マージで処理する。意外と合理的だ。ホワイトボードは短いセッションの間に少数のシェイプを同時編集する。CRDTのメタデータオーバーヘッドが不要なドメインだ。

tldrawの教訓: **CRDTはデータ構造によって異なる設計が必要だ。** テキストCRDT(Yjs Y.Text)とキャンバスCRDT(tldraw)は同じ理論の上に立っていても実装ディテールは全く異なる。すべての協業アプリがフルCRDTを敷く必要はないということ。

第16章 · Figmaのマルチプレイヤーアーキテクチャ

Figmaは2016-2017年に独自マルチプレイヤーエンジンを作った。CRDTの一変種で、ノード・属性単位でLWWを適用する。核は:

- ドキュメント = ノードツリー、各ノードは属性辞書(property bag)

- 各属性に最新変更の `(timestamp, clientID)` を付与

- 衝突 = より大きなtimestamp勝利(LWW)、同点はclientIDの大きい方

- ツリー構造変更(親変更、順序変更)は別ツリーCRDTロジック

FigmaのエンジニアEvan Wallaceが2019年のブログでこのアーキテクチャを公開し、その後多くの協業アプリが類似パターンを採った。tldrawも一部影響を受けた。

第17章 · Google DocsとOTの歴史

Google Docsは2010年のWritely買収から始まり、同年に同時編集を正式リリースした。エンジンは**Jupiter(Google内部名)OT**。核となるアイディア:

- すべての編集は (revision, operation) ペア

- クライアントはサーバにopを送り、サーバは他のopと変換して返す

- TP1(Transformation Property 1): `op1 \* (op2 transformed against op1) == op2 \* (op1 transformed against op2)` が成立しなければならない

OTの変換関数を正確に書くのは悪名高く難しい。Googleが十数年かけて磨いたこのコードは2020年代の新規アプリには追従コストが高すぎて、業界はCRDTへ移動した。

第18章 · Presence / Awareness — 「誰がどこで何を見ているか」

協業のもう半分は**presence**だ。誰がオンラインで、どこにカーソルがあって、何を選択していて、何色で表示されるか。

Yjsは `y-protocols/awareness` で標準化した。CRDT本体とは別の短命状態(ephemeral state)だ。メタデータ:

- `clientID`(Y.Docと共有)

- `name`、`color`、`cursor`、`selection`等の自由JSON

- ハートビートで生存表示、切断時は自動クリーンアップ

LiveblocksはawarenessをファーストクラスシチズンとしてもたらしUseOthers()・useUpdateMyPresence()で公開する。PartyKitも独自broadcastで実装可能。どちらにせよ**presenceは永続化しないのが原則** — ルームが閉じれば消える。

第19章 · WebSocket vs WebRTC — トランスポートの選択

CRDT同期のトランスポートは二つに分かれる。

| 基準 | WebSocket | WebRTC (DataChannel) |

| --- | --- | --- |

| サーバ要否 | 必要 | NAT越え用のSTUN/TURNのみ |

| レイテンシ | サーバラウンドトリップ | 直通P2P(より速い場合あり) |

| 拡張性 | サーバがファンアウト | メッシュトポロジならN^2 |

| 永続化 | 自然 | サーバミラー必要 |

| ファイアウォール | 通常通る | TURN無しだとブロック可能性 |

| 標準ライブラリ | y-websocket, y-partykit | y-webrtc |

2026年の一般推奨: **WebSocketを基本**にしつつ、真のP2Pが必要なドメイン(セキュリティ、オフラインメッシュ)、またはサーバ負荷を分散したい時にWebRTCを補助で使う。

第20章 · CRDTライブラリ比較

| ライブラリ | 言語 | 強み | 弱み | 代表的採用 |

| --- | --- | --- | --- | --- |

| Yjs | JS/TS(+Yrs Rustポート) | 成熟・エコシステム・テキスト性能 | 本体メモリやや大 | Tiptap, BlockNote, Lexical Yjs |

| Automerge | Rust/WASM | JSONツリーマージ強い | テキスト性能はYjsより弱い | PushPin, Trail Runner |

| Loro | Rust/WASM | リッチテキスト・ツリー・タイムトラベル | エコシステム新興 | 新規アプリ |

| Yjs + Yrs | Rustポート | Rustネイティブバックエンド | Yjsとのワイヤ互換は部分的 | サーバサイドYjs |

| Diamond Types | Rust | 単一テキストCRDT性能チャンピオン | JSON非対応 | ベンチマーク用 |

| sjs (Synchronized JS) | 実験的 | TypeScript親和 | 新興 | 研究用 |

第21章 · SaaS vs 自己ホスティング比較

| 基準 | Liveblocks | PartyKit | Hocuspocus(自己) | Replicache | Fluid (MS) |

| --- | --- | --- | --- | --- | --- |

| CRDT種類 | 独自 + Yjsアダプタ | Yjs/Automerge自由 | Yjs | 非CRDT(楽観的) | DDS(非CRDT) |

| ホスティング | SaaS | Cloudflareエッジ | セルフ | セルフまたはRocicorp | Azure |

| 価格 | MAUベース | 使用量ベース | インフラ費のみ | 使用量 + SaaS | Azure単価 |

| 自己ホスト可能 | 部分(Edge Storageオプション) | 困難(CF依存) | 完全 | Replicacheは可能 | 困難 |

| データ主権 | 米・EUオプション | グローバルエッジ | 自由 | 自由 | Azureリージョン |

| Awarenessファースト | はい | 自作 | はい | 該当なし | 部分 |

| Comments/Threadsモジュール | はい | 無し | 無し | 無し | Loopが別途 |

第22章 · 韓国・日本の事例 — Notion、カカオ、サイボウズ、Sansan

**韓国**の協業市場は興味深い。**Notion韓国進出(2020)** 以降、Notion APIと自社ビルド協業の比率が急速に増えた(Notionは独自CRDTライクなモデルを使うが公開資料は少ない)。**カカオワーク / カカオトーク**のメッセージはCRDTではないが、カカオワークの掲示板・メモ協業はOTベース(公開発表)で、カカオエンタープライズが「リモート協業」を伸ばした時期に自社エンジンを作った。**ネイバー Line Works**は文書・表・カレンダー協業を提供し、Lineの日本市場と統合され、日本のエンタープライズで大きなシェアを持つ。**トス / トスペイメンツ**は内部協業ツール(アーカイブ・文書)でYjs + Tiptap組み合わせを採用した事例をカンファレンスで共有した。

**日本**も興味深い。**サイボウズ kintone**はビジネスアプリビルダーのフォーム・レコード協業で、同じレコードを複数ユーザが同時編集するときOTベースの変換を適用する。サイボウズは長いOTノウハウを持つ会社として有名だ。**Sansan**は名刺クラウドで、名刺データOCR結果を複数ユーザが同時に補正するワークフローでCRDT適用を発表したことがある。**楽天 RMS**は楽天モールの店長向け協業ツールで、内部的に独自同期エンジンを持つ。**Notion日本チーム**は英語圏と同じエンジンだが、日本語IMEとの協業衝突(変換中の文字)を扱うパッチが日本チームPM発表で公開された。

第23章 · CRDT導入意思決定マトリクス

いつCRDTが正解で、いつそうでないか。

| 状況 | 推奨 |

| --- | --- |

| テキスト同時編集(エディタ) | Yjs + Tiptap/BlockNote/Lexical-Yjs |

| ホワイトボード/キャンバス | tldraw sync または Yjs Y.Map |

| フォーム・テーブル(セル単位) | Yjs Y.Map + セル別キー、または ShareDB |

| ゲーム状態(時間決定的) | CRDTよりlock-stepまたは権威サーバ |

| チャットメッセージ | CRDT不要、append-onlyログ |

| 通知・リアルタイムカウンター | CRDT G-Counter(学術的だが)または Redis |

| オフライン最優先(ローカルファースト) | Automerge, Loro, Yjs IndexedDB persistence |

| サーバ権威が重要(決済・在庫) | Replicacheまたは伝統的トランザクション |

第24章 · 永続化戦略 — IndexedDB・Postgres・バイナリスナップショット

CRDTはどこかに保存される必要がある。

- **クライアント側**: Yjsの `y-indexeddb`、AutomergeのIndexedDBアダプタ。オフライン編集後の再接続時に自動同期。

- **サーバ側(Yjsバイナリ)**: Yjsは `encodeStateAsUpdate` で全状態をバイナリとして保存する。Postgres `bytea` カラム、S3オブジェクト、Redisなどどこでも可能。

- **サーバ側(デルタログ)**: 各アップデートをログに蓄積し、定期的にスナップショットに圧縮。大容量文書に有利。

- **ハイブリッド**: スナップショット + その後のデルタ。ロード時にスナップショット + デルタ累積。

永続化の落とし穴は**GC**だ。すべてのクライアントが見届けたtombstoneは消せるが、「すべてのクライアント」をどう判断するかが難しい。Yjsは保守的にGCを行い、運用者が定期的に明示的圧縮を呼ぶこともできる。

第25章 · セキュリティ・権限・エンドツーエンド暗号化

協業SaaSのセキュリティモデルは三つに分かれる。

- **サーバが平文を見る**(最も一般的): Liveblocks・Hocuspocus標準モデル。権限チェック・検索・コメントモデレーションが楽。

- **エンドツーエンド暗号化(E2EE)**: クライアントがYjsアップデートを暗号化してサーバへ送る。サーバはバイナリブロブのみを知り、意味を知らない。Excalidrawルームが類似モデル。弱点: 検索・コメント分析・サーバ側マージが不可能。

- **部分暗号化**: コンテンツはE2EE、メタデータ(ルームメンバー、presence)は平文。折衷案。

権限は通常**ルーム単位トークン** + **操作単位検証**の組み合わせ。誰がルームに入れるか(JWT)、入ってから何ができるか(Hocuspocusの `onAuthenticate` + `beforeHandleMessage`)。

第26章 · エピローグ — 2027年を見る

CRDTはもはや学術の領域を出て運用の領域にある。2027年に起こる変化を三つ。

1. **モバイル・ネイティブのファーストクラス市民化** — Yjs Swiftポート、Automerge Kotlin、Loro Flutterバインディングがすべて安定し、モバイル協業アプリが爆発する。ローカルファーストが本当に可能になる。

2. **AIエージェントが協業参加者になる** — Cursor・Claude Codeが同じ文書を同時編集するもう一人の「ユーザ」になり、awarenessが人とAIを区別する。

3. **標準化の始まり** — IETF・W3CレベルでCRDTワイヤフォーマット標準化の議論に入る。Yjs・Automerge・Loroのワイヤ互換性はまだ無いが、「標準テキストCRDT」の輪郭が見え始める。

最大の教訓はシンプルだ。**保存ボタンが消えた世界はすでに来ている。** 残るは、その上に何を建てるかだ。

References

- Shapiro, Marc et al. "Conflict-free Replicated Data Types." INRIA Research Report (2011). https://hal.inria.fr/inria-00609399v1

- Kleppmann, Martin and Beresford, Alastair R. "A Conflict-Free Replicated JSON Datatype." IEEE TPDS (2017). https://arxiv.org/abs/1608.03960

- Kleppmann, Martin et al. "Local-first software: You own your data, in spite of the cloud." Onward! 2019, Ink & Switch. https://www.inkandswitch.com/local-first/

- Kleppmann, Martin. "Designing Data-Intensive Applications." O'Reilly (2017) — レプリケーションとCRDTの章。

- Yjs documentation. https://yjs.dev および https://docs.yjs.dev

- Automerge documentation. https://automerge.org および https://github.com/automerge/automerge

- Loro documentation. https://loro.dev および https://github.com/loro-dev/loro

- Liveblocks documentation. https://liveblocks.io/docs

- PartyKit documentation. https://docs.partykit.io

- Hocuspocus documentation. https://tiptap.dev/docs/hocuspocus

- ShareDB. https://github.com/share/sharedb

- Replicache and Zero. https://replicache.dev および https://zero.rocicorp.dev

- Fluid Framework. https://fluidframework.com

- tldraw sync. https://tldraw.dev/docs/sync

- Excalidraw collaboration. https://github.com/excalidraw/excalidraw

- Evan Wallace, "How Figma's multiplayer technology works." Figma blog (2019). https://www.figma.com/blog/how-figmas-multiplayer-technology-works/

- Diamond Types — Seph Gentle. https://github.com/josephg/diamond-types

- Kleppmann, Martin et al. "Moving Elements in List CRDTs." PaPoC 2020. https://martin.kleppmann.com/papers/list-move-papoc20.pdf

- Yjs internals: Kevin Jahns, "Are CRDTs suitable for shared editing?" https://blog.kevinjahns.de/are-crdts-suitable-for-shared-editing/

현재 단락 (1/277)

2010年にGoogle Docsが一般ユーザーに「同じ文書を同時に編集する」を届けたとき、その技術はOT(Operational Transform)だった。ある人の編集操作を別の人の編集操作に合わ...

작성 글자: 0원문 글자: 15,036작성 단락: 0/277