> OSSCA Yorkie(2) - 15분 만에 동시편집 에디터 구현하기
Crescent
Table of Contents
00. 서론
- Yorkie를 사용해서 에디터를 만드는 영상이 있어서 이를 따라해보며 정리를 해보았다.
- 영상에 나오는 내용이 내가 지금 할 때랑 다른 환경 상태도 있어서 정리할 겸,,,
- 참고하기 좋은 문서: yorkie-js-sdk/examples/index.html
01. CodeMirror 에디터 만들기
- 디렉토리에
index.html
만들기 - https://cdnjs.com/libraries/codemirror 들어가서
js
,css
코드 복사 <textarea/>
을<body/>
에 추가 →id="codemirror"
로 만들어준다main.js
만들기
- 이러고
index.html
을 실행시키면 잘 나온다!
02. Yorkie Client, Document 생성
Yorkie JS SDK
받고 서버 실행
- 클론!
compose
를 이용해Docker
를 띄움- Yorkie가
DB
도 사용하고 있고,grpc-web
을 써서Envoy
같은 것들이 뜰 수 있다고 한다.
Yorkie JS SDK
빌드 → 빌드 안해도 됩니다! https://cdnjs.com/libraries/yorkie-js-sdk
- 스크립트? 데려오기만 하면 되는
cdnjs
에서 데려와서 추가하기
- Yorkie Client 생성, 활성화 & Yorkie Document 생성 & Text 생성
- 영상에서는
yorkie.creativeClient()
인데yorkie.Client()
이어야 한다.constructor Client cannot be invoked without 'new'
라고 해서 앞에new
를 붙여야 한다.yorkie.createDocument
→yorkie.Document
, 앞에new
를 붙여야 함
- document는 적당한 이름인
doc
await
을 썼기 때문에async await
을 해줘야 함 → 함수를 만들었음- 이러면 Yorkie 쪽에 문서가 붙어서 클라이언트에 붙어서 만들어져야 한다
Text
데이터 타입을 만들어 CodeMirror의 변경사항들이Yorkie
에 저장될 수 있도록 한다.content
라는 키: 없을 때만 만들어준다Text
데이터 타입을content
라는 키로 만들게 되었다root.createText('context')
→root.content = new yorkie.Text()
03. CodeMirror와 Yorkie 서로 연동(바인드)
- CodeMirror와 Yorkie Document사이에서 바인드(bind) 되어 서로 주고 받아줘야 함
- 서로 주고 받으려면
Handler
가 필요함Handler
: 특정 유형의 데이터에 특화되어 있거나 특정 특수 작업에 초점을 맞춘 루틴/기능/태그
Document
: 응용프로그램의 모델이 표현되는 CRDT 기반 데이터 유형. 클라이언트는 오프라인 상태에서도 편집할 수 있다.
CodeMirror to Yorkie / Yorkie to CodeMirror
- CodeMirror to Yorkie: CodeMirror의 변경사항이 Yorkie쪽으로 전달되게 하는 부분
- Yorkie to CodeMirror: Yorkie쪽 변경 사항을 CodeMirror로 반영되게 하는 부분
> phase 1
- CodeMirror 에디터 쪽에
Handler
를 추가한다.
change
를 받아 추가change
를 console로 찍어본다
- Yorkie 쪽에서도
Handler
를 추가한다
Text
쪽에서도changes
를 받아 처리Text
가 Yorkie Document쪽에content
라는 이름이 있음changes
를console.log
에 넣어 출력
Handler
가 제대로 붙었는지 확인하려면index.html
파일 열어서 편집을 했을 때 콘솔이 찍히는지 확인한다
- 잘 찍히면
Handler
가 제대로 달린 것이다! CodeMirror
쪽console.log
가 나온 것으로 생각
> phase 2
- 변경사항들이 Yorkie 변경 사항과 CodeMirror 변경 사항이 서로 핑퐁 될 수 있기 때문에 필터 조건을 넣어야 한다.
change.origin === 'yorkie'
,change.origin === setValue
yorkie
나setValue
라는 이름으로 변경이 일어날 때도 필터링
- CodeMirror에서 사용하는
Pos
라는 타입이 있는데 커서의 위치 같은 것을 나타낸다.
- 이 것을 숫자 인덱스를 바꿔야 한다 →
indexFromPos
를 사용해서 변경 - 수정을 할 때 영역을 잡아서 편집할 수 있기 때문에
range
로from
,to
로 만들어 준다
- CodeMirror에서
Text
가 여러 줄일 때 배열로 와서 처리를 해야 한다. - Yorkie Document를 업데이트
root.content.edit
호출
> phase 3
Yorkie to CodeMirror 핸들러 구현
changes
가 배열로 오기 때문에 반복문을 만든다.- 자신의 편집을 반영할 필요는 없으니 본인을 필터하고 컨텐츠 변경이 아닌 경우 필터링
Pos
를index
로 바꿨는데 이번엔index
를Pos
로 바꿔야 한다.
editor.posFromIndex
사용range
이여서 영역을 잡아줘야 한다
- CodeMirror에서는
replaceRange
라는 것으로 스크립트로 변경사항을 넣어줄 수 있다.
- Yorkie에서 변경한 것이기 때문에 origin을
yorkie
로 한다.
- CodeMirror의
replaceRange
가 원격 편집을 고려하지 않은 경우,,,
- 해당 이슈
- 괜찮은 방법이 없는 것 같다?
yorkie-js-sdk
예제도 이 코드를 사용 중 editor.replaceRange(text, from, to, 'yorkie');
←yorkie
넣어야 한다.- 아무튼 이것을
function main()
앞에 추가
- 괜찮은 방법이 없는 것 같다?
> phase 4
- 새로고침을하면 저장된 내용들이 반영이 안된다.
- CodeMirror에서 제공하는 메소드를 호출해 초기값을 넣어준다.
TypeError: e.split is not a function
에러 →toString()
붙이기
04. 결론
- 얏호