Collaborative Editing

[동시 협업 툴-4] 간단한 Yjs사용한 앱 코드 분석 (2. Yjs Docs 살펴보기)

아직개구리 2023. 1. 19. 01:16

Awareness & Presence

https://docs.yjs.dev/getting-started/adding-awareness

  • Propagating awareness information such as presence & cursor locations
  • Awareness features는 collaborative applications에 필수적인 파트이다. 
  • users가 함께 일할 때 더 많은 info를 사용하여 커뮤니케이션 할 수 있다. cursor locations 이라던지, presence info같은 것들을 공유하면서 좀 더 active하게 협업할 수 있게 만들 수 있다. 대부분의 application 들이 사용자에게 unique한 이름과 색깔을 부여한다. 이런 정보들은 Awareness info로 분류한다. 이것은 다른 유저들이 현재 어떤 동작을 하고 있는지에 대한 hint를 줄 수 있다. 우리는 mouse position나 다른 유저의 live video recording 같은 awareness info를 제공할 수 있지만, 너무 많은 정보를 제공했을 때 일을 하던 사용자의 집중을 분산시킬 수 있기 때문에 적당한 balance가 중요하다. 
  • Awareness info는 Yjs document에 저장되지 않는다. session동안 유지될 필요가 없기 때문이다. 대신에 tiny state-based Awareness CRDT를 사용하여 JSON object를 모든 유저에게 전파시킨다. offline이라면, awareness state는 자동으로 삭제되고, 다른 유저들은 너가 offline이 된지 알림을 받을 것이다. 이 feature는 선택할 수 있지만, network provider가 awareness protocol을 구현해서 provider를 바꾸기 쉽도록 하는것을 추천한다. 우리의 모든 network provider 는 Awareness CRDT를 구현하고 있다. 

흥미로운 feature: Observing changes  (ex: yarray) 

  • yarray.observe:  change observer를 register한다. 이 obsesrver는 shared type이 modified 될때 동시에 불린다. 해당 타입이 observer call 안에서 바뀌면, event listener가 또 불리게 되는데 이는 현재 event listener가 return 되고 난 후에 불린다. yarray.unobserve하면 change observer를 unregister할 수 있다.  
  • yarray.observe는 Y.ArrayEvent events 를 발생시키는데, 사용자들은 transaction 동안에 발생하는 변화들을 산정하는 데 사용한다. (아래의 코드 처럼) 
yarray.observe(yarrayEvent => {
  yarrayEvent.target === yarray // => true

  // Find out what changed: 
  // Log the Array-Delta Format to calculate the difference to the last observe-event
  console.log(yarrayEvent.changes.delta)
})

Y.Doc API 

  • const ydoc = new Y.Doc(): Yjs document holds the shared data 
    • ydoc.transact(function(Transaction): void): shared document의 모든 변화는 transaction 안에서 일어난다.  그렇기 때문에 안에 들어가는 JSON을 직접 수정하는 것은 안된다. (ex: ymap.get(0).val = 1 -> highly discouraged) Observer call과 update event는 각각의 tx뒤에 불린다. change 모두를 bundling 해서 event call을 줄일 수 있다. 여기서 origin 의 쓰임은? 
  • provider = new IndxeddpPersistence('doc-name', ydoc): y-indexeddb persistence provider를 생성한다. doc-name as a unique string that identifies this document. 
    • provider.on('synced', function()): synced event 는 database와의 연결이 established되고 모든 가용한 content들이 loaded되었을 때 발생한다. 아무 content가 없을 때도 발생한다. 
  • ydoc.getText() / new Y.Text : 전자는 top-level type을 정의하는 것, 후자는 Yjs document 에 포함될 수 있는 nested type을 정의하는 것이다.  ydoc.getText(string)는 안에 들어가는 string의 이름을 가지는 Y.Text객체를 정의하는 것이다. 이 이름을 가지게 정의하는 모든 peer는 이 peer와 content 를 동기화시키게 된다. 
  •  y-websocket : websocket provider for Yjs that ships with a extendable server implementation. authentication과 authorization을 관리하는 central source가 필요할 때 websocket provider는 유일한 선택지이다. 

참고: WebRTC vs WebSocket

  • WebSocket은 client-server computer communication protocol이고, WebRTC는 peer-to-peer protocol 이다. WebSocket은 TCP위에서 작동하고, WebRTC는 TCP도 되지만 주로 UDP위에서 작동된다.
  • Data Integrity가 중요하다면, websocket이 TCP의 reliability를 이용할 수 있기 때문에 더 좋은 선택지이다. 반면에 speed가 더 중요하고, packet을 몇개 잃어버리는 게 상관 없다면 UDP 사용을 권장한다. 
    • (참고) TCP는 수신가능한지 확인을 하고 보내고, 수신이 잘못되었다면 재전송 요청까지 가능한 프로토콜이기 때문에 신뢰도 높은 데이터를 보내야 할 때 주로 사용된다. 응답이 필수적이기 때문에 시간이 지연되고 속도가 느려지고, CPU의 소모량이 많아져서 성능의 저하로 이어진다. 반면에 UDP 는 독립적인 패킷을 단위로 하여 통신하는데, 최소한의 오류만을 검증하기 때문에 패킷의 손실이 상대적으로 많은 편이다. UDP는 WebRTC를 이용한 실시간 스트리밍을 통해서 음성, 동영상 데이터를 전송하는 등 신뢰성보다 연속성이나 속도 등이 더 중요한 경우에 널리 사용된다.
    • RTP(Real-time Transport Protocol) 데이터 전송의 프로토콜이 아니라 이 패킷들을 해석하는 방법에 대한 프로토콜이다. UDP 위에서 작동하는 RTP는 문제가 생겼을 때 해결하는 메커니즘을 가진다. RTCP 는 RTP Control Protocol으로 RTP와 쌍으로 사용된다. RTP세션의 통계 및 제어 정보를 제공하여 참여자들에게 피드백을 제공함.
  • WebRTC는 Audio, video communication / File sharing app /screen sharing app/ broadcasting live events/ IoT device에 사용되며, WebSocket은 communication이 단방향이고, server가 low-latency 로 streaming하는 그런 실시간 업데이트를 해야하는 환경에서 사용되고, client와 server간의 bidirectional communication 이 필요할때도 사용된다. WebSockets can also be used to underpin multi-user synchronized collaborative functionality, such as multiple people editing the same document simultaneously. 
  • WebRTC는 peer-to-peer communcation을 허용하지만, 여러 communication을 동시에 잘 수행하기 위해서 server를 필요로 한다. 이 프로세스를 signaling 이라한다. signaling 은 media metadata(codec이나 media type같은 것), network data(host's ip address and port)그리고 communcation의 시작과 끝을 위한 control message등을 전달하는 과정을 포함한다. WebRTC는 standard signaling 구현을 제공하지 않기 때문에 다른 protocol을 사용해야하고, 이때 WebSocket Protocol 이 보통 webRTC application을 위한 signaling mechanism으로 사용된다. peer가 network 와 media metadata를 실시간으로 교환할 수 있도록 하기 위해 쓰인다.