2024.01.11. ~ 2024.02.24 (5주)
김병철 | 양혜림 | 이준용 | 황상필 |
BE, FE TL |
FE | FE | BE, FE |
|
|
|
|
-
포스트잇을 이용할 수 있습니다.
-
포스트잇 위에 스탬프를 찍어 투표를 진행할 수 있습니다.
-
투표 결과는 한 곳에서 확인 가능합니다.
-
돋보기 아이콘을 눌러 해당 포스트잇을 자세히 볼 수 있습니다.
실시간으로 여러 사용자가 동시적으로 작업을 수행해야 하므로 데이터 충돌 이슈 해결에 중점을 두고 기술을 선정했습니다.
OT | CRDT |
연산 기반 동기화 | 데이터 상태 기반 동기화 |
복잡한 충돌 해결 로직 필요 | 자동 충돌 해결 |
중앙 집중식 서버 / DB | Peer To Peer |
- 중앙 집중식 서버나 DB를 통해 데이터를 동기화하는 OT 알고리즘과 다르게
CRDT는 클라이언트 간의 연결을 통해 복잡한 알고리즘 없이 충돌을 해결하고 데이터를 병합합니다. - 따라서 CRDT 사용이 데이터의 일관적인 유지 및 구현에 적합하다 판단하여 채택했습니다.
User A가 객체를 그리는 과정이 모든 user에게 실시간으로 자연스럽게 동기화되어야 합니다.
그리는 과정이 실시간으로 동기화되지 않고 객체가 완전히 생성된 후에 동기화되었습니다.
드로잉 시 마우스가 움직이는 좌표를 계속적으로 추가하는 방식으로 동기화하여 문제를 해결했습니다.
드로잉에 대한 이벤트 발생이 빈번해 Throttling을 통한 일정 간격으로 이벤트를 구현하고 매끄럽지 않은 드로잉에 대해 보정 알고리즘으로 최적화를 구상했습니다.
User A가 텍스트를 작성 또는 수정 중일 때 모든 user에게 그 과정과 결과가 실시간으로 동기화되어야 합니다.
텍스트를 작성할 때 수정된 부분만 업데이트하는 것이 아니라 기존 텍스트를 삭제하고 업데이트 후 전체 텍스트를 동기화함으로써 텍스트 노드가 반짝이는 현상이 발생합니다.
LCS(최장 공통부분 문자열) 알고리즘을 이용해 두 문자열을 순회하며 공통된 문자열을 제외한 부분을 업데이트하는 방식으로 구현했습니다.
공통 문자열이 전체 문자열에서 맨 처음에 위치할 경우 문제가 해결되었으나, 다른 위치에서는 동일한 문제가 발생했습니다.
Two Pointer 알고리즘을 이용해 텍스트 노드의 양쪽 끝에서부터 순회하여 LCS보다 더 빠른 시간 내에 변경된 부분을 찾았습니다.
결과적으로 텍스트 변경이 잦더라도 즉각적으로 반영되도록 구현했습니다.
Language
Framework
Server
DB
Library
Collaboration Tool
npm run dev
cd /live-voard/bin
# for Linux
PORT=1235 node ./server.js
# for windows
SET PORT=1235
node ./server.js
디렉터리 구조 확인하기
live-board
├─ .eslintrc.cjs
├─ .gitignore
├─ bin
│ ├─ callback.js
│ ├─ server.js
│ └─ utils.js
├─ index.html
├─ LICENSE
├─ package-lock.json
├─ package.json
├─ public
│ ├─ LCSWorker.js
│ └─ vite.svg
├─ README.md
├─ src
│ ├─ App.tsx
│ ├─ assets
│ │ ├─ cursor.svg
│ │ ├─ eraser.svg
│ │ ├─ highlighter.svg
│ │ ├─ liveBoardLogo.png
│ │ ├─ mindmap.svg
│ │ ├─ pen.svg
│ │ ├─ postit.svg
│ │ ├─ PotatoFieldLogoLong.png
│ │ ├─ PotatoFieldLogoSquare.png
│ │ ├─ react.svg
│ │ ├─ readme
│ │ │ ├─ lineDrawingIssue.png
│ │ │ ├─ liveBoardArchitecture.png
│ │ │ ├─ liveBoardLogoReadme.png
│ │ │ ├─ liveBoardPoster.png
│ │ │ └─ textSyncIssue.png
│ │ ├─ shapes.svg
│ │ ├─ signupLogo.png
│ │ ├─ stamp.svg
│ │ ├─ text.svg
│ │ ├─ thumbdown.png
│ │ └─ thumbup.png
│ ├─ component
│ │ ├─ ButtonCustomGroup.module.css
│ │ ├─ ButtonCustomGroup.tsx
│ │ ├─ ColorContext.tsx
│ │ ├─ Connector.ts
│ │ ├─ contextMenu.css
│ │ ├─ Copyright.tsx
│ │ ├─ Cursor.tsx
│ │ ├─ EditableText.tsx
│ │ ├─ Eraser.tsx
│ │ ├─ Hand.tsx
│ │ ├─ MindMap.tsx
│ │ ├─ MindMapIndex.tsx
│ │ ├─ NavBarLobby.tsx
│ │ ├─ NavBarRoom.tsx
│ │ ├─ Pen.tsx
│ │ ├─ PostIt.tsx
│ │ ├─ Shape.tsx
│ │ ├─ ShapeOrder.ts
│ │ ├─ Stamp.tsx
│ │ ├─ Target.ts
│ │ ├─ Text.tsx
│ │ ├─ TextEditor.tsx
│ │ ├─ ToolContext.tsx
│ │ ├─ Tools.ts
│ │ ├─ UserShape.ts
│ │ ├─ voicechat
│ │ │ ├─ appId.tsx
│ │ │ ├─ voiceAgora.tsx
│ │ │ ├─ voicechat.tsx
│ │ │ └─ voiceserver.js
│ │ ├─ VoteDrawer.module.css
│ │ └─ VoteDrawer.tsx
│ ├─ image
│ │ ├─ addbutton.png
│ │ ├─ imageSample10.png
│ │ ├─ imageSample3.png
│ │ ├─ imageSample4.png
│ │ ├─ imageSample5.png
│ │ ├─ imageSample6.png
│ │ ├─ imageSample7.png
│ │ ├─ imageSample8.png
│ │ ├─ imageSample9.png
│ │ └─ imageSampleMain.png
│ ├─ index.css
│ ├─ lobby.tsx
│ ├─ login.tsx
│ ├─ main.tsx
│ ├─ signup.tsx
│ └─ vite-env.d.ts
├─ tsconfig.json
├─ tsconfig.node.json
└─ vite.config.ts