현재 진행중인 프로젝트인 무비위키의 버전 관리 기능은 크게 두 부분으로 나뉜다.
두 문서의 변경 사항을 추적하여 데이터화 하는 diff 알고리즘과
원본 문서와 변경 사항 데이터를 더해서 최신 버전 문서를 만들어내는 patch 알고리즘이다.
그런데 기능 테스트 중 오류를 발견했다.
한산 : 리덕스 (moviId : 3721)의 버전 기록
버전 6의 content에 버전 7의 diff를 더하면 버전 7의 content가 나와야하는데
변경 사항 데이터인 diff가 제대로 반영이 되지 않는다.....
{
"postId": 148,
"userId": 13,
"content": "<p>이순신 3부작의 2탄!</p><p>노량의 기록을 깰 수 있을 것인가</p><p>최종 스코어 720만</p><p>박해일 버전 이순신은 뭔가 냉철한 느낌이네요</p><p>가슴이 웅장해지네요...</p><p>거북선 폼 미쳤어요!!</p>",
"comment": "원본의 다섯번째 수정",
"createdAt": "2023-06-13T02:42:48.556Z",
"version": 6
}
{
"postId": 149,
"userId": 13,
"content": "<p>이순신 3부작의 2탄!</p><p>제작비 312억억</p><p>최종 스코어 720만</p><p>박해일 버전 이순신은 뭔가 냉철한 느낌이네요</p><p>가슴이 웅장해지네요...</p><p>거북선 폼 미쳤어요!!</p>",
"comment": "원본의 여섯번째 수정",
"createdAt": "2023-06-13T02:44:18.153Z",
"version": 7,
"diff": [
{
"type": "remove",
"value": "<p>노량의 기록을 깰 수 있을 것인가",
"idx": 1
},
{
"type": "add",
"value": "<p>제작비 312억억",
"idx": 1
},
{
"type": "remove",
"value": "<p>박해일 버전 이순신은 뭔가 냉철한 느낌이네요",
"idx": 3
},
{
"type": "remove",
"value": "<p>거북선 폼 미쳤어요!!",
"idx": 4
},
{
"type": "remove",
"value": "<p>가슴이 웅장해지네요...",
"idx": 5
}
]
}
현재 무비위키 프로젝트의 patch 알고리즘 코드
generateModifiedArticle = (originalArticle, diff) => {
let modifiedArticle = originalArticle;
for (const change of diff) {
if (change.type === 'remove') {
const sentenceToRemove = change.value;
modifiedArticle = modifiedArticle.replace(sentenceToRemove, '');
} else if (change.type === 'add') {
const sentenceToAdd = change.value;
const insertIndex = change.idx;
modifiedArticle = this.insertSentence(modifiedArticle, sentenceToAdd, insertIndex);
}
}
// 연속된 '</p>' 정리
modifiedArticle = this.cleanUpConsecutiveTags(modifiedArticle, '</p>');
// 마지막에 '</p>' 추가
modifiedArticle += '</p>';
return modifiedArticle;
}
// </p> 태그 단위로 나누고 다시 더함
insertSentence = (article, sentence, index) => {
const sentences = article.split('</p>');
const modifiedSentences = [
...sentences.slice(0, index),
sentence,
...sentences.slice(index)
].filter(Boolean);
return modifiedSentences.join('</p>');
}
// 가공 마지막에 </p> 태그 중복값 제거
cleanUpConsecutiveTags = (article, tag) => {
const consecutiveTagsRegex = new RegExp(`${tag}+`, 'g');
return article.replace(consecutiveTagsRegex, tag);
}
현재 patch 알고리즘 코드를 살펴보니 두가지 문제가 있었다!
첫번째 remove 데이터의 경우
diff 객체에서 type이 remove일 경우 value값을 원본 데이터인 modifiedArticle에서 찾아서 replace 메서드를 이용해
지워주는데 diff에는 value: '<p>문장' 형태로 되어있고 modifiedArticle(원본문서)에는 '<p>문장1</p><p>문장2</p><p>문장3</p>' 형태로 되어있어서 remove 문장을 검색하지 못한 것이다.
그래서 </p> 태그를 붙여서 지울 문장을 찾도록 수정했다.
if (change.type === 'remove') {
const sentenceToRemove = change.value + '</p>';
modifiedArticle = modifiedArticle.replace(sentenceToRemove, '');
}
두번째 add 데이터의 경우
diff 객체에서 type이 add일 경우 '<p>문장1</p><p>문장2</p><p>문장3</p>'의 형태로 되어 있는 원본 문서를
</p> 단위로 split하여 배열로 만든 다음, diff 데이터의 idx를 참고하여 추가된 문장을 삽입한다.
그리고 마지막으로 </p>로 join을 해주는데 마지막 문장에 </p>가 붙지 않아 온전한 문장이 되지 않는 것이었다.
그래서 join을 해주고 나서 문자열 제일 끝에 </p>를 붙여주도록 하였다.
// </p> 태그 단위로 나누고 다시 더함
insertSentence = (article, sentence, index) => {
const sentences = article.split('</p>');
const modifiedSentences = [
...sentences.slice(0, index),
sentence,
...sentences.slice(index)
].filter(Boolean);
return modifiedSentences.join('</p>')+'</p>';
}
수정 후 정상 작동하는 것을 확인하였다.
같은 문장으로 테스트하였는데 diff 데이터도 달라진 것을 보니
반복된 수정으로 인해 잘못된 diff데이터가 쌓인 것으로 추측된다.
{
"postId": 244,
"userId": 13,
"content": "<p>이순신 3부작의 2탄!</p><p>제작비 312억억</p><p>최종 스코어 720만</p><p>박해일 버전 이순신은 뭔가 냉철한 느낌이네요</p><p>가슴이 웅장해지네요...</p><p>거북선 폼 미쳤어요!!</p>",
"comment": "버전7",
"createdAt": "2023-06-15T05:12:06.007Z",
"version": 7,
"diff": [
{
"type": "remove",
"value": "<p>노량의 기록을 깰 수 있을 것인가",
"idx": 1
},
{
"type": "add",
"value": "<p>제작비 312억억",
"idx": 1
}
]
},
{
"postId": 243,
"userId": 13,
"content": "<p>이순신 3부작의 2탄!</p><p>노량의 기록을 깰 수 있을 것인가</p><p>최종 스코어 720만</p><p>박해일 버전 이순신은 뭔가 냉철한 느낌이네요</p><p>가슴이 웅장해지네요...</p><p>거북선 폼 미쳤어요!!</p>",
"comment": "버전6",
"createdAt": "2023-06-15T05:11:23.017Z",
"version": 6
}
'Development > TIL' 카테고리의 다른 글
Nest.js 클러스터링 (0) | 2023.06.21 |
---|---|
비교 단위별 Diff 및 Patch 코드 동작 속도 측정 (0) | 2023.06.16 |
DP, LCS, MED, SES 개념정리 (1) | 2023.06.15 |
문서의 문장 단위 변경 추적 (0) | 2023.06.13 |
git의 diff 알고리즘 (0) | 2023.06.10 |