hagi4u/tldraw-webrtc-example 포크. 원본은 WebRTC·y-webrtc 기반; 본 저장소는 WebSocket·SQLite·단일 포트 서빙 등으로 갈아탐.
패키지 설치 (Bun 필요)
bun install
개발환경 실행 (Vite + WebSocket/Yjs 서버 동시)
bun run dev
빌드 및 프로덕션 실행 (HTTP·WS 단일 프로세스)
bun run build
bun run serve
WebSocket/Yjs 서버만 별도로 실행
bun run ws:start
- TypeScript
- 자바스크립트의 정적 타입을 명시하여 타입 기반으로 코드를 작성할 수 있게 함
- React.js
- 화면을 그리기 위한 라이브러리
- tldraw
- 화이트 보드 인터페이스 구현
- yjs
- 실시간 공동 작업 구현을 위해 사용
- 내부 데이터 구조를 공유하여 CRDT(동시에 데이터를 수정할 때 발생되는 충돌 문제를 해결) 구현이 구현된 객체
- Y.Doc 를 통해 document 개념을 만들어 연결된 클라이언트들에게 sync 할 수 있게 처리
- 다양한 네트워크 프로바이더를 제공하며 (y-websocket 등) 별도의 추가기능 없이 적용만 하면 연결된 클라이언트 간 동일한 상태관리를 위해 데이터를 유지
- y-utility (YKeyValue)
- key-value pair 데이터를 저장하고 관리할 수 있게 해주는 역할
- 단순하고 직관적인 key-value pair 데이터를 관리할 때 유용함
- 데이터를 번갈아 반복작성 해야 하는 경우에 적합하여 사용
- Y.Map 은 잠재적인 충돌 요소를 방어하기 위해 기록된 모든 키를 유지 해야함
- 그리고 특정 키를 삭제 하더라도 데이터 용량에 변화가 없음
- y-websocket
- Yjs용 WebSocket 프로바이더, 중앙 서버와 SQLite로 방 단위 상태 동기화·저장
- Tailwind
- Utility Classname 기반의 스타일 라이브러리로 별도의 CSS Style 를 작성하지 않고 클래스 기반으로 간단한 UI 를 그리기 위해 사용
- uuid
- 피어가 방을 생성할 때 URL Path로 사용하기 위하여 사용
1. 상태
- storeWithStatus:
<TldrawEditor/>컴포넌트의 store prop 에 들어갈 상태 조합 - store
- yDoc 와의 실시간 데이터 동기화를 위한 처리
- 화이트 보드 내 record 정보 컬랙션
- 원격으로 받아온 데이터를 화이트보드에 병합
- 스키마 정보 관리
- yDoc
- 피어들간 상태 관리를 위한 Yjs 객체
- yStore
- key-value pair 의 데이터 관리를 위한 yjs store
- provider
- websocket provider
- 이벤트 관리
- meta
- yjs의 데이터 스키마를 가져오고, 메타 데이터를 관찰하기 위함
- 스키마 변경시 데이터를 일관성있게 유지하고, 맞지 않다면 페이지 새로고침을 통해 최신 스키마가 로딩될 수 있도록 관리 필요
2. 이벤트 처리 순서도
stateDiagram-v2
useEffect(React.js) --> WebsocketProvider.on('status')
WebsocketProvider.on('status') --> handleStatus : connected/disconnected
handleStatus --> WebsocketProvider.on('synced')
WebsocketProvider.on('synced') --> handleSyncPeers
handleSyncPeers
state WhiteboardUpdate{
handleSyncWhiteBoard
YjsStore.on(handleYStoreChange)
}
state SchemaUpdate {
handleSyncSchema
meta.observe(handleSyncMeta)
}
handleSyncPeers --> WhiteboardUpdate
handleSyncPeers --> SchemaUpdate
handleSyncPeers --> handleSyncAwareness
- 빌드 후
bun run serve또는 Docker로 띄우면 동일 네트워크에서http://<호스트>:3000접근 (WebSocket도 동일 포트)
Docker 이미지 빌드는 컨테이너 내부에서 npm으로 설치·빌드함(Bun 대신: better-sqlite3 등 네이티브 스크립트 호환). 재현성 위해 루트에 package-lock.json 두고 docker compose build 전에 npm install로 갱신 가능.
데스크탑 클라이언트에서 화이트 보드 변경 사항을 실시간으로 모바일 클라이언트에서 확인(1)


