Collaborative Editing

[동시 협업 툴-5] 간단한 Yjs사용한 앱 코드 분석 (3. y-websocket server with persistence)

아직개구리 2023. 1. 24. 20:23

기본적으로 주어지는 websocket server의 작동에 대해서 알아보자.

persistence 관련 

  1. y-leveldb: https://github.com/yjs/y-leveldb 
  2. bindState: 아래의 코드에서 하는 동작은 docName에 해당하는 것을 생성해서 param으로 들어온 ydoc을 db에 저장하고, 
    1. Y.encodeStateAsUpdate(Y.Doc, targetStateVector): Remote document에 적용될 수 있도록 document state를  single update message로 암호화 한다. target state vector를 넣게 되면 update message에 difference만 나타낼 수 있다. 
    2. persistence.storeUpdate('my-doc', Y.encodeStateAsUpdate(ydoc)): store document updates retrieved from other clients. 
    3. persistence.getYDoc('my-doc'): create Y.Doc instance with the data persisted in leveldb. 임시적으로 Yjs document를 만들어서 change 를 동기화하거나 data를 추출할 때 사용한다. 
    4. Y.applyUpdate(Y.Doc, update:Unit8Array, [transactionOrigin: any]): shared document Y.Doc에 document update를 적용한다. 그리고 선택적으로 transactionOrigin을 specify할 수 있다.  
bindState: async (docName, ydoc) => {
  const persistedYdoc = await ldb.getYDoc(docName)
  const newUpdates = Y.encodeStateAsUpdate(ydoc)
  ldb.storeUpdate(docName, newUpdates)
  Y.applyUpdate(ydoc, Y.encodeStateAsUpdate(persistedYdoc))
  ydoc.on('update', update => {
    ldb.storeUpdate(docName, update)
  })
}

 

WebSocket Server관련

이 예제에서 제공하는 건 서버의 형태는 아래에 나와있는 external HTTP/S server이다. (Https server는 웹서버에 SSL 암호화해서 중간에 다른 사람이 요청을 가로채더라도 내용을 확인할 수 없다. ) 일단 인증서가 필요 없는 http서버를 만드는 방식에 대해서 알아보겠다.  참고한 reference는 아래와 같다. 

const server = http.createServer();

// 서버에 요청이 오면 request event가 일어날 때 마다 내부 함수가 실행된다.
server.on('request', (request, response)=> {
	//request & response 처리 
})
  • Request
    • http.IncomingMessage 의 instance. request.method가 POST / PUT일 때  request의 body가 중요하다. request의 header에 접근하는 것보다 어렵다. request객체는 ReadableStream 인터페이스를 구현하고 있기 때문에 이 스트림에 eventlistener를 등록하여 해결이 가능하다. 이건 concat-stream이나 body 모듈로 쉽게 해결할 수 있음. 
    • request 스트림의 오류가 발생하면 stream에서 'error' 이벤트를 emit하면서 오류를 전달한다. 이 오류를 처리해서 response를 보내야함. 그렇지 않더라도 event를 listen해야함. 안그러면 nodejs 종료 될 수도 있음. 
  • Response
    • http.ServerResponse의 instance이면서 WritableStream이다. HTTP 상태 코드는 default가 200이다. 
    • response.writehead(statusCode[, statusMessage][, headers]): 응답에 대한 정보를 기록. statusCode는 3-digit HTTP status code이다.  status message는 header가 flushed 되었을 때, client에 보내진다. 응답에 대한 정보를 포함한다. 
      • { 'Content-Type': 'text/html; charset=utf-8' )}  : statusMessage에 컨텐츠의 형식을 나타낸다. 
    • response.write('<h1></h1>'): 클라이언트로 보낼 데이터
    • response.end() : param이 있다면 그 데이터도 클라이언트로 보냄. must be called on each response.
  • 예) request 객체에서 받은 stream을 그대로 다시 response로 보내는 echo 서버를 구현하고자 할 때, request.pipe(response) 를 통해서 한 스트림에서 다른 스트림으로 직접 연결 할 수 있음 request.pipe(response);