CRDT 기반 실시간 화이트보드. 다중 커서, 동시 편집, 오프라인 동기화까지 지원하는 협업 도구.
Notion, Figma처럼 여러 사용자가 동시에 편집할 수 있는 화이트보드를 구현했습니다. OT(Operational Transformation) 대신 CRDT(Conflict-free Replicated Data Type)를 선택하여 서버 의존도를 낮추고, 오프라인 상태에서도 편집 후 재연결 시 자동 병합되는 구조를 설계했습니다.
User Flow:
사용자 → 보드 생성/참여 → 실시간 캔버스 편집 (도형, 텍스트, 이미지) → 다른 참여자 커서/선택 영역 실시간 표시 → 오프라인 시 로컬 저장 → 재연결 시 자동 머지
Yjs를 CRDT 엔진으로 사용하고, Hocuspocus를 WebSocket 서버로 두어 awareness(커서 위치, 사용자 정보)를 실시간 브로드캐스트합니다.
Canvas 렌더링 성능 — 수백 개의 오브젝트가 있는 보드에서 매 프레임 전체를 다시 그리면 60fps를 유지할 수 없었습니다. 특히 다른 사용자의 커서 움직임이 초당 수십 번 업데이트되면서 불필요한 리렌더링이 폭증.
Undo/Redo + CRDT 충돌 — Yjs의 UndoManager가 로컬 변경만 되돌리는데, 다른 사용자가 같은 영역을 수정한 경우 Undo 결과가 사용자 기대와 달라지는 문제.
오프라인 → 온라인 전환 시 대량 업데이트 — 오프라인에서 쌓인 수백 개의 변경사항이 한꺼번에 동기화되면서 UI가 수 초간 멈추는 현상.
Dirty Region 렌더링 — 변경된 영역만 추적하여 부분 리드로잉. 커서 레이어를 별도 Canvas로 분리하여 오브젝트 레이어에 영향을 주지 않도록 구성. 결과적으로 1,000개 오브젝트 보드에서도 안정적 60fps 유지.
UndoManager에 커스텀 TrackedOrigin 적용 — 로컬 origin과 리모트 origin을 분리하고, Undo 스택에서 리모트 변경과 인터리빙된 로컬 변경만 선택적으로 되돌리도록 구현.
Chunk 기반 점진적 동기화 — 오프라인 변경사항을 50개 단위 청크로 분할하여 requestIdleCallback으로 순차 적용. 동기화 진행률을 UI에 표시하여 사용자에게 피드백 제공.