You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
v0: 가능성만 확인해 봄. 회사 메신저로 복사/붙여넣기 없이 한땀한땀 타이핑해서 집에서 짠 코드를 회사로 옮기는 것이 가능한가...(이때 1000줄 정도를 타이핑해서 옮겼고 회사에서 깃허브 열어놓고 오타 잡았음)
v1: 순수 텍스트만 비교. 편집 중인 텍스트에 즉시 하이라이팅되는 걸 원했기 때문에 편집기(textarea)의 내용과 100% 똑같이 렌더링되는 레이어를 만들어서 겹쳐놓고 이 레이어의 DOM을 직접 수정해서 하이라이팅 했음. 내 잔머리에 너무 감탄했지만 알고보니 여기저기서 쓰는 방법이더라. 이 때 사내 메신저에서 "복사/붙여넣기"하는 편법을 찾아 냈음.
v2: 누가 "표는 안나와?"라는 말을 할 때마다 속이 타들어가서... *"표를 원해? 준다. 내가 표 준다"*라는 심정으로... 순수 텍스트 대신 HTML 자체를 비교하게 개선(개선이라기보단 처음부터 다시 만들었다고 보면 됨). 도중에 react까지 얹어버려서 코드가 너무 커졌지만(react는 이후에도 뗐다 붙였다 몇 번 했는데 자잘한 UI 요소도 react 없이 만들려면 너무 답답하더라) 복사/붙여넣기로 코드를 옮기는 것에 한계가 있어 zip 압축 후 base64로 인코딩해서 붙여넣기 함.
v2.2?: "그림은 비교 안돼?" 아이씨... 이것 때문에 픽셀 비교를 해주는 pixelmatch를 붙여봤었는데 사실 영 마음에 안든다. pixelmatch를 쓰려면 그림의 실제 내용(바이트 배열?)이 필요하지만 앱의 권한 상 이게 항상 가능한 게 아님. 결국 브라우저 확장을 만들어서 확장이 내용을 뽑아서 다시 diffseek앱으로 보내주는 것까지 만들었는데 픽셀vs픽셀 비교는 그렇게 만족할 만한 결과를 주지 않기 때문에(같은 내용의 그림이더라도 그림이 포함하는 여백의 상이한 경우 등등) 이 고생을 해야할까 싶은거다. 지금은 날려버림.
구현 의도? 왜 이렇게?
양쪽에 텍스트 붙여넣고 실행버튼 딱~ 누르면 diff들이 표시되게....
그딴 짓을 왜???? 버튼을 뭐하러 눌러? 그냥 척하면 딱.diff는 텍스트 변경시 실시간으로, 입력한 텍스트 바로 그 자리에 보여줘야 함!! 매번 귀찮게 버튼 누르는 짓은 하고 싶지 않다. 결과 view를 완전히 새로 만드는 것이 훨씬 쉽지만 너무 쉬워서 안함.
정말 순간적으로, 입력 즉시 하이라이트가 업데이트 되는 걸 원했기 때문에 내용 변경 시에 debounce나 throttle 같은 건 자제하거나 딜레이를 최소로 두고 거의 즉시 diff pipeline이 실행되도록 함.
실시간으로 업데이트가 일어나는 도중에도 편집을 방해하면 안됨. 입력 딜레이, 의도하지 않은 커서 위치 변경, 한글 입력상태 유지/복원 등등을 다 신경써야 함.
당연히 메인쓰레드에서 무거운 작업을 할 순 없으니 worker로 보내서 처리하지만 DOM 접근이 필요한 경우 어쩔 수 없이 메인쓰레드에서 처리해야 함.
공백은 옵션에 따라서 완전히 무시하거나 정규화(두개 이상의 공백은 하나로 취급)해서 비교함. 우리말보다 공백규칙이 애매하거나 혹은 잘 안지켜지는 언어가 또 있을까 싶다.
순수 텍스트와 그 위에 diff 하이라이트를 입히는 것만 다루다가 결국 렌더링된 HTML 문서에 하이라이팅을 입히는 지경까지 왔음.
특히 커서 위치 문제(이건 커서 위치를 순간적으로 복구해버리면 쉽게 해결됨)나 한글 입력상태 문제를 완전히 회피하려면 입력 중에 DOM에 변경을 가하면 안되고 이 때문에 실시간으로 하이라이트를 표시하는 게 쉽지 않음. 순수 텍스트만을 보여줄 때에는 편집창과 똑같은 내용을 똑같은 위치에 그려주는 레이어를 하나 만들어서 그 레이어에다가 하이라이트를 넣는 방법을 썼지만 HTML 문서를 그대로 표시하기로 하면서 태그의 경계를 자유롭게 넘나들 수 있는 그런 방법을 찾아야 했기에 canvas에다가 하이라이트를 직접 그려넣는 방법으로 바꿈.
canvas에 하이라이트용 rect를 그리는 것은 정말 빠르지만 문서 크기만큼의 canvas를 가질 순 없으니 스크롤이 될 때마다 즉시 canvas를 지우고 새로운 위치에 맞게 새로 그려야 함. 창의 크기가 변경되는 경우는 위치 뿐만 아니라 하이라이트 영역의 모양과 크기까지 완전히 바뀌기 때문에 rect를 새로 추출해야 함.
편집기(그냥 단순 <div contenteditable>임)의 기본적인 기능(복붙,undo/redo,...)들은 되도록 브라우저에게 넘길 것. 이런 기능들은 숨쉬기와 같아서 예상대로 작동 안하는 순간 짜증 솟구침. 또한 나처럼 깐깐한 사람에게 어색함이 안느껴질만큼 제대로 구현하기는 쉽지 않음(커서위치, 텍스트선택범위, 스크롤 위치, 얼마나 많은 편집을 얼마의 딜레이 간격으로 하나의 히스토리 엔트리로 묶을 것인가, 그리고 양쪽 편집기를 왔다갔다 했을 때 등 생각보다 신경쓸 게 많음. 단순히 text만 보관하는 것으로는 어림 없음).
처음엔 그랬지만... HTML으로 렌더링하기 시작하면서부터 내용을 sanitize를 해야했기 때문에 개입이 필요해짐. document.execCommand("insertHTML",...)를 쓰면 undo/redo가 문제 없이 작동하지만 이 함수는 정말 끔찍하리만큼 느림. deprecated 상태라서 오랫동안 개선 없이 그냥 버려진 듯? 어쩔 수 없이 큰 문서를 붙여넣을 땐 다른 방법을 써야했고 그런 경우 undo로 붙여넣기 이전 상태로 돌아가는 건 불가능함.
diff 하이라이트 색들은 정말 세심하게 고른 것들임. 절대 불만을 가져서는 안됨. 빨간색 계통은 배경과 확실히 대비되지 않을 수 있기 때문에 의도적으로 제외함..
큰 워드문서에서 복붙을 할 때에 복사가 바로 되지 않는 문제가 있는데 사내 DRM 프로세스의 문제인 것 같음. 될때까지 붙여넣기 하면 언젠가는 된다(기다리는 동안 워드는 먹통됨).
처음엔 복사 이전 클립보드에 들어있던 내용이 붙여넣기 됨
재시도(ctrl-v) 하다보면 빈 텍스트가 붙여넣기 됨
계속... 재시도(ctrl-v)하다보면 결국 성공함.
엣지(혹은 크롬) 전용.
정렬 모드
양쪽 에디터에서 서로 대비되는 줄들을 서로 같은 위치로 맞춰주고 스크롤을 동기화해주는 기능. F2로 토글.
이를 위해서 diff 단계부터 양쪽의 대응 쌍들을 추적하고 그 쌍이 각 줄의 시작부분에 위치하는 경우 실제 DOM의 Y좌표를 뽑아서 필요한 경우 그 차이만큼 한쪽에 패딩을 강제로 넣어서 위치를 정확하게 맞춤.
순수 텍스트로인 경우 Y좌표를 항상 커지는 방향으로 진행되지만 HTML, 특히 테이블을 표시하는 경우 앞부분의 내용이 그 뒷부분의 내용보다 반드시 Y좌표 상 위에 있다는 보장이 없음. 그렇기 때문에 위에서부터 순서대로 정렬을 해줘야함.
이렇게 강제로 양쪽에서 대응되는 부분의 Y좌표를 강제로 맞추고 전체 문서의 높이까지 맞춰주면 스크롤 동기화는 그냥 양쪽의 scrollTop만 똑같이 맞추면 됨.
동적으로 화면에 보이는 내용만 우선 정렬하는 방법도 써봤지만 코드의 복잡성에 비해서 큰 실효가 없었음. 위에 썼듯 문서 상의 순서가 반드시 Y좌표의 순서와 일치하지 않으므로 까다로움.
readonly 모드임. 입력->내용바뀜->diff->재정렬 과정에서 방금 입력한 텍스트의 위치나 스크롤 위치가 바뀌면 짜증나니까.
믿을 건 브라우저 뿐...
인터넷도 안되고 다른 프로그램 설치도 불가능한 사내 PC에서 코드를 짜서 돌릴 수 있는 건 웹브라우저 뿐이었음.
결과적으로 최선의 선택인 듯 함. 요즘 웹브라우저만큼 최적화 잘 되어있는 프로그램은 없을거고 너무나 당연해서 있는지도 모르다가 갑자기 안되면 멘탈 나가는 필수 기본적인 기능들이 브라우저에 이미 다 들어있다. 간단한 UI도 쉽다.