-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/#019 crdt 동시 편집 구현 #100
The head ref may contain hidden characters: "Feature/#019_CRDT_\uB3D9\uC2DC_\uD3B8\uC9D1_\uAD6C\uD604"
Conversation
- package.json 등록 - tsconfig.json 빌드 설정 #98
- tsconfig 설정 - vite 설정 추가
- nest-cli webpack으로 빌드되도록 설정 추가 - tsconfig 경로를 읽을 수 있도록 설정
- server build - webpack으로 빌드되도록 추가 - CRDT라이브러리가 먼저 빌드 되어야 client와 server가 안정적으로 빌드되어 root package의 build 멘트에 cd명령어 추가
- 추후 RemoteInsertOperation과 InsertOperation 합칠 가능성 있음 - 현재는 동작별로 분류하여 명시성을 중점으로 둠
- NodeId는 논리적 시계 clock과 숫자형의 client정보로 판단 - Node는 양방향 링크드 리스트 형태로 선언하여 순서비교 메소드 추가
- head와 node정보를 담는 nodeMap 선언 - setNode : 노드맵에 노드 추가 - getNode : 노드 조회 - deleteNode : 특정 노드 제거 후 nodeMap에서 제거 - findByIndex : 특정 인덱스에 해당하는 노드 찾기 - insertAtIndex : 인덱스가 주어지면 추가 - insertById : 추가할 Id가 주어지면 추가 - stringify : 링크드리스트를 문자열로 변환 - spread : 링크드리스트를 배열로 변환 - 추후 react에 사용가능성 있음
- 로컬,원격 삽입 알고리즘 구현 - 로컬,원격 삭제 알고리즘 구현 - localInsert : 로컬 삽입 연산 후 원격 전파 - localDelete : 로컬 삭제 연산 후 원격 전파 - remoteInsert : 원격 삽입 연산 수신 반영 - remoteDelete : 원격 삭제 연산 수신 반영 - read: CRDT 내부의 링크드리스트에서 문자열 반환 - spread: CRDT 내부의 링크드리스트에서 텍스트 배열 반환 - getTextLinkedList : 링크드리스트 인스턴스 반환 - 추후 CRDT 확장 가능성 - serialize : CRDT 직렬화 함수 - 추후 역직렬화 함수 추가 가능성 있음 #25 #31
- 추후 직렬화를 위한 interface 선언
…이브러리_client,_server가_접근_가능하도록_환경_구축 Feature/#98 nocta crdt 라이브러리 client, server가 접근 가능하도록 환경 구축
- 추후 RemoteInsertOperation과 InsertOperation 합칠 가능성 있음 - 현재는 동작별로 분류하여 명시성을 중점으로 둠
- NodeId는 논리적 시계 clock과 숫자형의 client정보로 판단 - Node는 양방향 링크드 리스트 형태로 선언하여 순서비교 메소드 추가
- head와 node정보를 담는 nodeMap 선언 - setNode : 노드맵에 노드 추가 - getNode : 노드 조회 - deleteNode : 특정 노드 제거 후 nodeMap에서 제거 - findByIndex : 특정 인덱스에 해당하는 노드 찾기 - insertAtIndex : 인덱스가 주어지면 추가 - insertById : 추가할 Id가 주어지면 추가 - stringify : 링크드리스트를 문자열로 변환 - spread : 링크드리스트를 배열로 변환 - 추후 react에 사용가능성 있음
- 로컬,원격 삽입 알고리즘 구현 - 로컬,원격 삭제 알고리즘 구현 - localInsert : 로컬 삽입 연산 후 원격 전파 - localDelete : 로컬 삭제 연산 후 원격 전파 - remoteInsert : 원격 삽입 연산 수신 반영 - remoteDelete : 원격 삭제 연산 수신 반영 - read: CRDT 내부의 링크드리스트에서 문자열 반환 - spread: CRDT 내부의 링크드리스트에서 텍스트 배열 반환 - getTextLinkedList : 링크드리스트 인스턴스 반환 - 추후 CRDT 확장 가능성 - serialize : CRDT 직렬화 함수 - 추후 역직렬화 함수 추가 가능성 있음 #25 #31
- 추후 직렬화를 위한 interface 선언
…campwm-2024/web33-Nocta into Feature/#019_CRDT_동시_편집_구현
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저는 연결리스트로 마이그레이션 하면서 노드간 연결관계 설정할때 엄청 오래걸리고 코드도 복잡했는데 굉장히 깔끔하게 잘 작성된 것 같습니다!
문자간 노드 관계는 문제가 없을 것 같은데 블록간 노드관계는 제가 구현한 연결리스트 구조와 차이가 있는 것 같아서 이부분은 같이 코드보면서 얘기해보면 좋을것 같아요!
고생하셨습니다 approve하겠습니다!
export class Node { | ||
id: NodeId; | ||
value: string; | ||
next: NodeId | null; | ||
prev: NodeId | null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
현재 이 노드로 글자간 인덱스와 블록간 관계를 모두 처리하는건가요?
블록의 경우에 prevNode, NextNode가 존재하고, 리스트나 체크박스의 경우 children을 가지는 경우가 있어서 해당하는 블록은 firstChild라는 포인터로 첫번째 자식 노드를 가리키게 구현했습니다. 자식들의 경우 기존 prevNode, nextNode를 사용하게 되면 연결관계가 꼬이는 문제가 있어 prevSibling, nextSibling 포인터를 사용해서 자식관 관계를 저장하고 있습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네, 맞습니다. 연규님이 작성하신 방법은 자식들을 관리해야해서 자식들을 신경쓰지말고 오직 next, prev로만 관리한 다음에 각 블록마다 indent props 를 넣어서 관리하면 좀더 편하지 않을까 합니다. 이 CRDT구조하고도 어느정도 일맥상통하구요ㅎㅎ 자세한 부분은 오늘 회의로 말씀드렸으니 DB스키마에서 확인하면 될 것 같습니다!
head: NodeId | null; | ||
nodeMap: { [key: string]: Node }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
head와 nodeMap의 차이가 무엇인가요? 둘다 노드에 관한 정보를 저장하고 있는것 같은데 head는 순회할때 사용하고, 실제 값을 사용할때는 nodeMap을 사용하나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
head는 처음 시작하는 nodeId를 뜻하고, nodeMap은 그 노드들을 가지고 있는 Map 자료구조 입니다. 말씀하신 것 같이 실제 값을 사용할때는 nodeMap[nodeId] = node 식으로 사용될 것 같습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
정말 고생 많으셨습니다!
📝 변경 사항
🔍 변경 사항 설명
기본 4개로 구성 되어있습니다.
위 동작을 위한 내부 메소드들이 선언되어 있습니다.
연결, 재연결을 할때 client <-> server가 CRDT 정보를 주고받기 위해서 CRDT의 직렬화된 정보를 주고받기 위해
serialized 정보역시 메소드로 선언 되어 있습니다.
client에서는 server로부터 CRDT를 받아 역직렬화를 하고 각 동작을 server와 송/수신 해야 합니다.
server는 수신받은 연산을 반영한 CRDT 정보를 mongoDB에 주기적으로 업데이트 해줘야합니다.
🙏 질문 사항
📷 스크린샷 (선택)
✅ 작성자 체크리스트