-
Notifications
You must be signed in to change notification settings - Fork 2
⚡ 기술적 이슈
*Git의 개념과 용어를 모르는 일반인 유저를 위해, Docsa에서는 일반적인 Git의 개념과 대응되는 용어를 다음과 같이 정의합니다.
(기록: commit, 버전: branch, 병합하기: merge)
관련 코드 위치:
src/main/java/io/ejangs/docsa/domain/commit/app/CommitService.java의createCommit
블록 저장 방식에 초점을 맞춰 '기록하기' 로직에 대해 간단히 설명한다.
기록마다 매번 본문 전체를 저장하는 wiki 형식이 아닌, 이전 기록에서 변경된 사항을 저장하는 스냅샷 비교 방식으로 구현하였다. 이는 '버전 관리'라는 목표에 집중하며 효율적으로 데이터를 저장하기 위한 선택이다.
최소 저장 단위는 문단, 즉 '블록'이다. 여기에 가장 적합한 라이브러리로 블록 스타일 에디터인 Editor.js를 선택하였다. Editor.js는 전통적인 WYSIWYG 에디터와 달리, JSON 형태로 구조화된 블록 단위로 데이터를 관리한다. 하나의 블록은 Editor.js가 부여한 고유 id를 가지며 이를 통해 각 블록을 식별한다. (블록의 내용이 변경되더라도 블록 자체의 고유 id는 변하지 않는다.)
사용자가 '기록하기'를 누를 때 서버에 전달되는 커밋 관련 주요 정보는 1. 변경된 블록의 내용, 2. 문서 전체의 블록 순서 정보 이다.
변경감지 되지 않은 블록은 새로 저장하지 않고 이미 저장되어있는 블록을 재사용 할 것이다.
이해를 돕기 위해 사진과 함께 예시 상황을 설명한다.
1번 기록이 직전의 커밋이고 사용자가 2번 커밋에 해당하는 내용을 새로 커밋하려 한다면, 프론트는 이전 커밋과 비교하여 변경/새로 추가된 블록인 BLOCK-ID01, BLOCK-ID03의 내용 그리고 문서 전체의 블록 순서인 ['BLOCK-ID01', 'BLOCK-ID02', 'BLOCK-ID03']을 보낸다.
1) 프론트에서 전달받은 수정된 블록들이 먼저 MongoDB의 Block에 저장된다. (BLOCK-ID01 , BLOCK-ID03을 저장한 도큐먼트의 id를 mongo_id003 , mongo_id004이라 하자)
2) MongoDB의 commitBlockSequence에서 이전 커밋(기록1)의 블록 순서인 cbs-id001을 가져온다.
3) 이전 커밋의 블록 순서는 Block의 리스트인 [mongo_id001, mongo_id002]이다.
4,5) 이제 프론트에서 전달받은 문서의 Editor.js 블록 순서인 "blockOrders": [BLOCK-ID01, BLOCK-ID02, BLOCK-ID03] 을 순서대로 탐색해, 적절한 mongo_id를 찾아 매핑하는 과정이 필요하다. 변경사항이 있어 새로 저장된 블럭인 BLOCK-ID01과 BLOCK-ID03은 1) 의 리스트에,
기존에 존재하던 블럭인 BLOCK-ID02는 3) 의 리스트에 있을 것이다.
6) 기록2의 Block의 리스트는 [mongo_id003, mongo_id002, mongo_id004]가 된다.
7) 완성된 리스트를 commitBlockSequence에 저장하고, 반환된 MongoDB의 id cbs-Id002를 기록2(메타데이터만 저장되어 있는 Commit 엔터티)의 commitMongoId 필드에 추가한다.
관련 코드 위치:
src/main/java/io/ejangs/docsa/domain/commit/app/CommitService.java의deleteCommit
블록은 여러 기록에서 참조할 수 있기 때문에, 기록 삭제시 다른 데이터와 달리 블록을 삭제하기 위한 추가적인 검증이 필요하다.
1) 직전 커밋인 기록 1의 모든 블록 id를 담은 set_A
2) 삭제하려는 커밋인 기록 2의 모든 블록 id를 담은 set_B
3) set_B.removeAll(set_A)
관련 코드 위치:
src/main/java/io/ejangs/docsa/domain/branch/app/BranchService.java의deleteBranch
버전 삭제도 비슷한 방식으로 진행한다. 차집한 연산을 통해 오직 삭제하려는 버전에만 존재하는 블록을 찾아 삭제 가능한 블록을 식별한다.
1) 버전 a의 모든 블록 id를 담은 set_A
2) 삭제하려는 버전 b의 모든 블록 id를 담은 set_B
3) set_B.removeAll(set_A)
블록 처리 방식 이외에 이종 DB를 고려한 저장과 삭제 로직에 대해서는 다음 링크 참고.