“They had no concept of a duty of care to their users.”
“사용자를 돌볼 책임이라는 개념이 없었습니다”
Vim의 영구 실행 취소(Persistent Undo)는 파일을 닫거나 컴퓨터를 재시작한 뒤에도 실행 취소 기록을 보존합니다. 글은 NeoVim과의 호환성 문제를 계기로 소프트웨어가 사용자 작업물을 안전하게 다뤄야 한다는 원칙을 짚으며, 댓글에서는 실제 데이터 손실 여부와 설정 차이를 두고 반론이 나옵니다.
- 주제
에디터 노트
버그 리포트인 줄 알았는데 소프트웨어 윤리 에세이였습니다. Chisnall이 문제 삼는 건 NeoVim이 Vim의 실행 취소 파일 형식을 바꾼 것 자체가 아니라, 기존 파일을 변환·보존하지 않고 "형식이 안정적이지 않으니 보존을 기대하지 말라"고 답한 태도입니다. Jef Raskin의 첫 번째 법칙, 컴퓨터는 사용자의 작업물을 해치거나 방치해서는 안 된다는 원칙을 끌어옵니다. 다만 댓글들의 반론도 만만치 않습니다. 기본 설정에서는 두 편집기의 실행 취소 저장 위치가 달라 충돌이 나지 않고, NeoVim의 영구 실행 취소 자체는 여전히 작동합니다. 사실관계로 보면 데이터 손실 사건이 아니라, 호환성 단절과 그 뒤의 대응 태도를 다룬 글입니다.
AI 요약
컴퓨터 과학자 David Chisnall은 2000년 무렵부터 Vim으로 책과 논문, 기사를 써 왔습니다. Vim 명령을 거의 의식하지 않고 쓸 정도로 익숙해졌으며, 다른 편집기로 작성한 문서에는 Vim의 저장 명령인 :w가 종종 남아 있다고 합니다. 그가 특히 좋아하는 기능은 영구 실행 취소(Persistent Undo)입니다. 파일을 닫거나 재부팅한 뒤에도 실행 취소 기록이 남아, 몇 주 전에 지운 내용을 복구하거나 정리 과정에서 작업을 망친 원인을 찾아볼 수 있습니다.
작업물을 보호하는 소프트웨어
글은 이 기능을 Jef Raskin의 ‘첫 번째 법칙’과 연결합니다. 컴퓨터는 사용자의 작업물을 해치지 않아야 하며, 아무 조치도 하지 않아 작업물이 손상되는 상황도 막아야 한다는 원칙입니다. Raskin은 《The Humane Interface》에서 이와 함께 불필요한 시간과 수고를 요구하지 말 것, 사람의 필요와 약점을 배려하는 인터페이스를 만들 것을 제시했습니다.
Chisnall은 새로 나온 NeoVim을 써 보다가 영구 실행 취소가 작동하지 않는 문제를 발견했다고 설명합니다. 그의 설명에 따르면 NeoVim은 Vim의 실행 취소 파일 형식을 바꾸면서 기존 파일을 변환하거나 별도 이름으로 보존하지 않았고, Vim에서 읽을 수 없는 파일을 만들었습니다. 문제를 제기했을 때 “영구 실행 취소 형식은 안정적이지 않으니 데이터 보존을 기대하면 안 된다”는 답을 들었다며, 오류 자체보다 사용자 데이터를 다루는 태도에 실망했다고 말합니다.
실행 취소 파일을 둘러싼 반론
댓글에서는 데이터 손실이 발생하는 조건을 두고 이견이 나옵니다. 한 댓글은 기본 설정에서 Vim과 NeoVim은 실행 취소 파일을 서로 다른 위치에 저장하므로, 두 편집기가 같은 디렉터리를 쓰거나 파일 옆에 저장하도록 설정한 경우에만 충돌한다고 설명합니다. 다른 댓글은 Vim 사용자라면 설정 파일을 NeoVim에서도 재사용할 가능성이 높아 같은 저장 위치를 쓰게 된다고 반박합니다. 이에 기본 설정을 그대로 썼다는 답글도 달렸습니다.
또 다른 댓글은 NeoVim이 읽지 못하는 파일을 덮어쓰는 대신, Vim 설정을 읽어 Vim과 같은 위치와 이름으로 실행 취소 파일을 기록한다고 코드 동작을 설명합니다. 그 결과 두 편집기가 서로 읽지 못하는 파일을 각각 만들 수 있다는 이야기입니다. 이 댓글은 글쓴이가 기존 파일을 실제로 덮어쓰지는 않았다고 과거에 확인했으며, Vim도 실행 취소 파일 형식을 한 차례 바꾼 적이 있다고 덧붙입니다. 다른 참여자는 NeoVim의 영구 실행 취소 기능은 여전히 작동하지만 Vim과 하위 호환되지는 않는다고 정리합니다.
저장 안정성을 둘러싼 별도 경험
한 사용자는 커널이 패닉을 일으킬 때 NeoVim에서 열어 둔 문서가 여러 차례 사라졌다고 주장합니다. 성능을 위해 fsync() 호출을 제거한 것이 원인이었다고 설명하며, 문제를 제기했을 때 개발자가 대응한 태도에도 실망했다고 합니다. NeoVim 개발자라고 밝힌 답글은 fsync() 옵션의 기본값을 성능 때문에 바꿨지만 스왑 파일이 손실을 막을 것으로 판단했으며, 해당 변경은 이후 되돌렸다고 반박합니다. 댓글은 관련 논의 링크도 제시하며 앞선 사용자의 기억과 설명을 문제 삼습니다.
다른 댓글은 몇 주 전 파일을 어떻게 고쳤는지 잊어버렸을 때 영구 실행 취소 기록을 시간 여행처럼 쓴다고 합니다. 다만 버전 관리로 파일을 갱신하거나 LLM이 내용을 수정하면 편집기 밖에서 일어난 변경 때문에 실행 취소 기록이 깨질 수 있다고 덧붙입니다.
Lobsters 반응
- @sri — 성급히 비난하기 전에 관련 맥락을 덧붙입니다. 기본 설정에서는 충돌이 발생하지 않습니다. NeoVim은
$XDG_STATE_HOME/nvim/undo/에, Vim은 편집 중인 파일 옆이나~/.vim/undo/에.un~파일을 저장합니다. 두 편집기가 같은 실행 취소 디렉터리를 쓰거나 파일 옆에 저장하도록 설정한 경우에만 데이터 손실이 발생합니다.- @gir — 두 편집기가 같은 실행 취소 디렉터리를 쓰도록 설정하는 경우는 Vim에서 NeoVim으로 옮기는 영구 실행 취소 사용자 거의 전부일 겁니다. Vim 설정을 두 편집기에서 재사용할 테니까요. 이 댓글은 전형적인 Hacker News식 ‘함정 잡기’처럼 느껴집니다.
- @goldstein — 실행 취소 파일 위치를 따로 설정하는 이유가 무엇인가요? Vim에서도 설정하지 않았고 NeoVim에서도 설정하지 않았습니다. 기본값이면 충분합니다. 업데이트: Vim에서 실행 취소 파일을 한곳에 모으려면 직접 설정해야 한다는 뜻인가요? 그렇다면 직접 설정했을 수도 있겠네요.
- @chinmay — 코드를 완전히 잘못 읽은 게 아니라면 읽을 수 없는 파일을 덮어쓰지는 않습니다. 실제로 덮어쓰지는 않지만, Vim 전용 설정 파일을 Vim이 지정한 위치에서 읽고 그 위치에 Vim이 예상하는 이름으로 파일을 쓰기 때문에 Vim과 NeoVim이 서로 읽지 못하는 실행 취소 파일을 만들었습니다. Chisnall이 5년 전에 기존 파일을 실제로 덮어쓰지 않았다고 확인했는데도, 이 문제를 반복해서 제기합니다.
- @chinmay — Vim도 이미 형식을 한 번 바꿨습니다. NeoVim은 다시 바꾼 것이고, 버전 1에서 2로 바꾼 쪽은 Vim입니다.
- @hyperpape — 두 번째 댓글을 보면 데이터가 사라지거나 삭제된 것이 아니라, 두 시스템이 같은 위치에 서로 읽지 못하는 파일을 쓰는 난감한 상황으로 읽힙니다. 물론 NeoVim이 나오기 전부터 그 위치에 파일을 써 온 Vim에는 책임이 없습니다.
- @chinmay — NeoVim은 설정하지 않으면 Vim과 같은 위치에 쓰지 않습니다. Chisnall은 그렇게 설정했습니다. NeoVim은
$VIMINIT을 읽고, 제 환경에서는 이 변수가 Vim 설정 파일을 불러옵니다. 그래서 Vim 설정에 따라 실행 취소 파일 위치가 정해졌습니다. 두 위치를 나누려고 설정 파일에if has("nvim")조건을 넣어야 했습니다. 다시 말하지만 이 문제에서 NeoVim에 잘못이 있는 것도 아닙니다. - @natkr —
$VIMINIT도 Vim에서 온 변수입니다. - @chinmay — 맞습니다. 다만
.vimrc나 XDG 설정 경로처럼 자동으로 적용되는 파일과 달리, 직접 설정한 환경 변수입니다.
- @alerque — 궁금해하는 분들을 위해 덧붙이면, NeoVim에서도 영구 실행 취소는 여전히 작동합니다. Vim과의 하위 호환은 되지 않습니다.
- @ploum — NeoVim 때문에 큰 데이터 손실을 세 번쯤 겪었습니다. 커널이 불안정해 일주일에 한 번 정도 패닉을 일으켰고, 그때 NeoVim에서 열어 둔 문서가 전부 사라졌습니다. Vim에서는 그런 일이 없었습니다. 조사해 보니 성능을 위해
fsync()를 제거한 버그였습니다. 버그 자체보다 개발자가 처음엔 데이터 손실을 부인하고, 재현 뒤에도 패치를 거부하며 더 조사하지 않은 태도에 놀랐습니다.- @jmk — 성능을 위해 옵션의 기본값을 바꾼 것이지
fsync()를 제거한 것은 아닙니다. 항상fsync()를 호출하는 스왑 파일이 데이터 손실을 막을 거라고 판단했습니다. 해당 변경은 되돌렸지만 아이디어 자체는 타당하다고 봐서 시간이 나면 다시 검토하겠습니다. 그리고 데이터 손실을 일으켰다는 설명을 처음부터 부인한 것도 아닙니다. 기억이 틀렸는데도 인터넷에서 소문을 확신에 차 퍼뜨리는군요. 전체 논의를 확인해 보세요.
- @jmk — 성능을 위해 옵션의 기본값을 바꾼 것이지
- @trenchant — 중요한 내용을 실수로 지우고 몇 주 동안 알아차리지 못한다면 편집기로서는 좋지 않은 모습입니다. 10년 동안 이 편집기를 썼는데도 여전히 큰 부분을 실수로 지웁니다. 대개 알아차리기는 하지만, 나만 그런 게 아니라니 다행입니다.
- @dilawar — 급히 읽는 분들을 위해 글에 나온 세 가지 원칙을 옮깁니다. 컴퓨터는 사용자의 작업물을 해치거나 방치해 손상되게 해서는 안 됩니다. 불필요하게 시간을 낭비시키거나 꼭 필요한 수준보다 더 일하게 해서는 안 됩니다. 인터페이스는 사람의 필요에 반응하고 사람의 약점을 배려해야 합니다.
- @Cajunvoodoo — 덧붙이면, 글쓴이는 몇 주 뒤에도 변경 사항을 이어서 확인하도록 파일별 실행 취소 기록을 저장하는 영구 실행 취소 기능을 NeoVim이 깨뜨렸다고 비판합니다. 글쓴이는 이를 버그라고 봤지만 NeoVim 팀이 대수롭지 않게 넘겼다고 생각했습니다. 이 맥락을 알면 위 원칙이 왜 나오는지 이해할 수 있습니다.
- @pgn — 다소 기묘한 용도지만, 시스템 곳곳에 버전 관리하지 않는 Org 모드 파일과 셸 스크립트가 있습니다. 임시 파일처럼 쓰다가 다시 편집할 때 “지난번에 왜 이렇게 바꿨지?”라고 생각하곤 합니다.
u를 반복하면 작은 타임머신처럼 쓸 수 있습니다. Emacs에서도 비슷한 동작에 의존하게 됐습니다. 성가신 점은 버전 관리 갱신이나 최근의 LLM 편집처럼 편집기 밖에서 바뀐 내용이 영구 실행 취소 기록을 깨뜨린다는 점입니다.