본문 바로가기
C.W.K.
Stream
Lesson 02 of 08 · published

공동 편집

~13 min · app, collab, ot, crdt

Level 0Poller
0 XP0/60 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

동시 편집이라는 도전

사용자 둘이 같은 문서를 동시에 편집하면 충돌이 생겨. 단순히 마지막 쓰기를 이기게 하면 데이터가 사라져. 운영 수준에서는 Operational Transforms(OT)Conflict-free Replicated Data Types(CRDT) 두 접근이 대표적이야.

한 단락으로 비교하는 OT 와 CRDT

Google Docs 가 쓰는 OT 는 중앙 서버가 필요해. 각 편집은 정수 리비전을 가진 연산이고 서버는 들어오는 연산을 동시에 일어난 다른 연산과 변환해 일관된 결과를 만들어. Figma 와 Notion 이 쓰는 CRDT 는 중앙 권위가 없어도 돼. 각 문자가 전역 고유 ID 와 순서 메타데이터를 가지고, 연산 순서와 무관하게 자료구조가 수학적으로 같은 결과에 수렴해. CRDT 는 추론하기 쉽고 OT 는 대역폭 효율이 좋아.

직접 만들지 말고 라이브러리를 써

둘 중 하나를 정확히 구현하는 데는 몇 달이 걸리고 독창성을 발휘할 자리도 아니야. CRDT 의 대표 JavaScript 라이브러리는 Yjs 이고 주요 경쟁자는 Automerge 야. 둘 다 WebSocket 전송 어댑터가 있어. 연결한 뒤 시간은 알고리즘이 아니라 사용자 경험에 써.

Code

개념: CRDT 형태의 삽입·javascript
// Each character gets a globally unique id.
// Order is determined by ids, not local indices.
ws.send(JSON.stringify({
  type: 'doc.insert',
  data: {
    id: 'user1-1705312000-0',  // globally unique
    char: 'H',
    after: null,                // position reference
  },
}));

// On the receiving side, all operations from all users
// merge into the same final state regardless of order.
WebSocket 위 Yjs — 운영에 쓸 수 있는 길·javascript
import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';

const ydoc = new Y.Doc();
const provider = new WebsocketProvider(
  'wss://api.example.com/yjs',
  'document-id-here',
  ydoc,
);

const ytext = ydoc.getText('content');
ytext.observe(event => {
  // event.changes — apply to your editor view
});

// Local edit
ytext.insert(0, 'Hello');

External links

Exercise

공유 방에 브라우저 탭 두 개를 Yjs 로 연결해. 한쪽에서 입력하면 다른 쪽에 나타나는지 봐. 탭 A 를 끊은 채 양쪽에서 편집하고 다시 연결해 두 편집이 손실 없이 합쳐지는지 확인해. 같은 위치에 동시에 삽입하거나 삽입한 글자를 삭제하며 깨뜨려 봐도 라이브러리가 모두 처리해야 해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.