원문 캡처 · kirahowe.com
원문 캡처 · kirahowe.com

editmd 0.1.0은 macOS용 위지윅 마크다운 편집기로, 파일을 열어 둔 상태에서 에이전트가 내용을 수정해도 사람의 미저장 편집을 보존하고 변경 사항을 실시간으로 병합한다. macOS 14 이상에서 애플 실리콘과 인텔 맥을 모두 지원한다.

설치와 사용

Homebrew로 설치한 뒤 마크다운 파일을 열 수 있다.

brew install --cask kirahowe/tap/editmd
open -a editmd notes.md

앱은 아직 애플 개발자 ID로 서명되지 않았다. Homebrew cask를 이용하면 격리(quarantine) 플래그를 제거한다. 릴리스 페이지에서 ZIP 파일을 직접 받았다면 앱을 열기 전에 다음 명령을 실행해야 한다.

xattr -dr com.apple.quarantine editmd.app

기능을 더 설명하는 웹사이트도 제공한다.

에이전트와 동시에 편집하기

제작자는 Claude가 코드 대부분을 작성하는 환경에서 문서를 편집하는 시간이 늘어, 마크다운 파일로 저장하면서도 워드 프로세서처럼 쓸 수 있는 간단한 위지윅 편집기를 만들었다고 설명했다. 에이전트가 참고 자료를 찾고 링크를 추가하거나, 기억이 희미한 인용문을 채우고, 사양 문서에 코드 예제를 보태는 동안에도 파일을 계속 편집할 수 있도록 하는 것이 목적이다.

대부분의 편집기는 파일이 바뀌면 한쪽 변경 사항을 덮어쓰거나 디스크의 파일이 바뀌었다는 대화상자를 띄운다. editmd는 Y.js를 이용해 에이전트의 수정을 실시간으로 병합한다. 파일을 연 상태에서 에이전트가 내용을 바꾸면 변경 사항이 화면에 나타나고, 사용자의 미저장 편집은 유지된다. Cmd-Z는 에이전트가 한 변경이 아니라 사용자가 직접 한 변경만 되돌린다.

편집기와 파일 처리

앱은 네이티브 AppKit 문서 앱에 WebKit 뷰를 넣고, 그 안에서 Milkdown 편집기를 실행한다. 편집기는 ProseMirror와 remark를 사용하며 앱에 모두 포함돼 있어 네트워크에서 불러오는 구성 요소는 없다. 각 창의 문서는 Y.js의 충돌 없는 복제 데이터형(CRDT)으로 관리한다.

디스크의 파일이 바뀌면 editmd는 새 텍스트와 마지막으로 확인한 버전을 비교한 뒤, 차이를 블록별 편집으로 재생해 Y.js가 사용자가 입력한 내용과 병합하도록 한다. 서로 다른 문단, 목록 항목, 표 행을 수정한 경우에는 변경 사항이 함께 반영된다.

입력을 멈춘 뒤 1초 후 자동 저장하며, 계속 입력 중이면 5초마다 저장한다. 열었다가 수정하지 않고 저장한 파일은 바이트 단위로 원본을 유지한다. 수정한 파일도 UTF-8, UTF-16, Windows-1252 인코딩과 줄바꿈 형식, YAML·TOML 프런트 매터, 참조형 링크, 표를 유지한다.

GitHub Flavored Markdown을 지원해 표, 작업 목록, 취소선, 각주, GitHub의 제목 앵커를 올바르게 표시한다. 따라서 GitHub용으로 작성한 목차도 예상대로 작동한다. mermaid 코드 펜스는 편집 중 실시간 미리보기가 있는 다이어그램으로 렌더링된다. 다이어그램을 클릭하면 원시 마크다운을 볼 수 있고, Cmd-/를 누르면 문서 전체를 원시 마크다운으로 전환한다.

외부에서 받은 신뢰할 수 없는 문서도 안전하게 열도록 설계했다. 렌더링된 보기에서 링크를 Cmd를 누른 채 클릭해도 어떤 항목도 실행하지 않는다. 텍스트 파일은 editmd에서 열고, 그 밖의 파일·폴더·앱은 Finder에 표시한다. 원격 이미지는 Mail처럼 사용자가 허용하기 전까지 차단한다. 따라서 이미지 요청을 통해 문서가 정보를 유출하는 일을 막는다.

제작자가 설명한 AI 개발 과정

제작자는 Claude의 상당한 도움을 받아 editmd를 만들었으며, 현재 주로 Opus 5.5를 사용한다고 밝혔다. 제품은 자신의 취향과 필요에 맞게 만들었고, Claude가 자신보다 코딩을 더 잘하며 이전에는 놓쳤을 문제도 찾아낸다고 설명했다.

릴리스 준비 단계에서 Claude에 엄격한 품질 보증(QA)을 요청하자 여러 문제가 발견됐다. WebKit 콘텐츠 프로세스가 충돌하면 창이 오래된 텍스트를 다시 불러왔고, 다음 자동 저장 때 이미 저장된 변경 사항을 조용히 덮어쓸 수 있었다. 복제한 저장소의 .app 링크를 Cmd를 누른 채 클릭하면 앱이 실행됐는데, 복제된 파일에는 격리 표시가 없어 Gatekeeper 경고도 나타나지 않았다. 문서를 열 때 원격 이미지를 가져와 추적 픽셀을 불러오는 문제도 있었다.

Windows-1252 파일이 조용히 UTF-8로 바뀌고 UTF-16 파일은 깨진 글자로 열리는 문제도 확인됐다. 생성한 마크다운 사례 485개를 직렬화기에 넣어 검사한 결과 실제 내용 손실도 발견됐다. 빌드 배지([![build](…)](…))의 링크가 사라지고, 행 길이가 고르지 않은 표에서 열이 밀렸으며, 사용되지 않은 링크 정의가 삭제됐다.

제작자는 이런 문제를 실제 사용자에게 피해를 주기 전까지 알아채지 못했을 수 있다고 말했다. 이어 Claude에 여러 병렬 에이전트를 실행해 문제를 고치도록 요청했다. 에이전트들은 각기 다른 Git 워크트리에서 7개 문제를 수정했으며, 구현 뒤 독립 코드 검토와 적대적 QA를 거쳐 수정하는 절차를 반복했다. 검토 에이전트 두 명이 승인할 때까지 작업을 진행했다. 하위 에이전트 30개를 사용해 약 2시간 30분이 걸렸다.

통합을 맡은 메인 에이전트는 별도의 버그도 발견했다. 두 워크플로가 모두 마크다운 직렬화기를 수정했는데, 그중 하나가 참조 링크를 깨뜨린 문제였다. 각 수정에는 회귀 테스트가 추가됐고, 테스트 스위트는 웹 테스트 65개에서 762개로 늘었다.

알려진 한계

동일한 문서에 동시에 편집을 적용하는 데는 여전히 한계가 있다.

  • 사용자와 다른 프로그램이 같은 문단을 같은 순간에 수정하면 두 변경 사항이 모두 남는다. 이 경우 수동으로 정리해야 할 수 있다.
  • 저장 직전에 파일을 한 번 더 확인하지만, 확인과 쓰기 사이의 몇 마이크로초 동안 외부 프로그램이 파일을 쓰면 그 변경 사항이 덮어써질 수 있다. 다른 프로그램의 협조 없이는 이 간격을 현실적으로 없앨 수 없다.
  • obsidian://, file:// 같은 사용자 지정 스킴 링크는 렌더링된 보기에서 Cmd를 누른 채 클릭해도 아직 작동하지 않는다.
  • 수백 KB에 이르는 큰 파일도 편집은 가능하지만, 파일을 연 뒤 첫 자동 저장 때는 문서 전체를 직렬화한다.

editmd는 첫 릴리스라 아직 다듬을 부분이 있으며, 제작자는 이미 매일 사용하고 있다고 밝혔다. 문제를 발견하면 저장소에 이슈를 등록할 수 있다.