洪民憙 (홍민희) 블로그

이하의 글은 2012년에 쓴 것입니다. 오래된 글인 만큼, 현재의 생각과 전혀 다른 내용도 많이 포함되어 있고, 당시와는 상황이 많이 달라진 점도 있습니다. 또한, 그 당시에 잘못 알려졌던 정보도 포함되어 있을 수 있습니다. 어찌됐든 저는 제 오래된 글이 회자되는 것을 저어합니다. 읽기에 앞서 양해를 부탁드립니다.

나는 Vim 사용자다. 이게 없으면 코딩도 속 편하게 못하고, 웬만한 문서화도 다 Vim으로 특정 마크업 언어(reStructuredText나 Markdown 등)를 사용한다.

Vim은 처음 보면 매우 멋진 구석이 많다. ‘멋지다’는 표현이 적합하다고 생각한다. 쓸모에 비해 멋있다. 나도 어릴 때 Vim을 쓰게 된 계기가 스크린캐스트 같은 걸 보면서 멋있다고 생각했기 때문이다. Vim은 코딩이나 문서를 작성하는 일 자체에 초점이 맞추어져 있다기 보다는, 문자열 자체를 조작하는 데에 초점이 맞추어져 있는 도구다. 커서는 문자열의 특정 오프셋에 위치한다. 그리고 문자열을 잘라내거나, 임의적인 위치로 이동하는 것이 가능하다. 예를 들어 보통 에디터에서는 단어간 이동을 컨트롤 키와 함께 방향키를 입력하는 것으로 해결하거나 홈이나 엔드 키를 눌러서 줄의 맨 처음과 맨 끝으로 이동하고, 페이지 업/다운 키를 써서 먼 거리의 세로 이동을 하게 되어 있다. 하지만 기본적으로는 이 줄에서 세번째로 나오는 대문자 K의 위치로 이동하기같은 일을 위해 축약된 표현은 존재하지 않는다. 대조적으로 Vim은 그런 식의 임의적인 이동이 가능하다(예를 들면, 3fK). 그래서 일반적인 에디터를 사용하던 사람이 보기에는 커서가 마치 홍길동처럼 동해 번쩍 서해 번쩍하듯, 사무라이 만화의 주인공들마냥 전광석화하는 것처럼 보인다. 몇번의 키를 입력하는 것만으로 기대하는 것에 비해 굉장히 많은 변화가 짧은 시간 내에 일어나는 것이다.

반면 코딩을 위한 현대적인 IDE들은 리팩토링 도구를 구비한다. Vim은 기본적으로 그런게 존재하지 않는다. IDE를 쓰면 짧은 시간 내에 보고 있는 텍스트 버퍼에 큰 변화가 일어나는 일은 드물다. 하지만 충분히 짧은 시간 내에 프로그램의 큰 구조를 개선하는 식의 더 크고 중요한 변화가 일어날 수는 있다. Vim에서 그런 일을 제대로 이루려면 유닉스의 크고 작은 유틸리티들을 활용하는 데에 해박하고, Vim 자체의 깊고 다양한 그러나 어두운 구석들을 잘 알고 있어야 한다.

실제로 쓸모 있는 소프트웨어를 작성하는 데에는 특정 규모 이상의 코드가 필수적이다. 파일도 하나 이상이 생긴다. 모듈을 구성하기 위해 디렉토리도 여러 단계로 들어가기 시작한다. 버퍼 하나에 소프트웨어의 모든 것을 담기 힘들어지게 된다. 그런 상황에서는 Vim의 장점이 퇴색하기 시작한다. IDE가 빛을 발한다.

그래서 Vim을 쓰는 사람들은 그래서 자연스레 Java나 Objective-C 같은 문화의 언어들보다는 Haskell이나 Perl 같은 문화의 언어들을 선호하게 된다. 짧고 함축적인 것을 선호하는 동시에 기계적으로 추론 가능한 것들이 소스 코드의 형태로 눈 앞에 늘여놓여지는 것을 싫어하게 된다. 그것들은 기계적으로 추론 가능한 정보들이며, 기본적으로 여분의(redundant) 정보인 것이다. 복제된 정보들은 그것을 갱신하게 될 때 필연적으로 어려움을 겪게 된다. 그걸 손으로 갱신할 수는 없으므로 한 군데에서만 써놔도 컴파일러가 보이지 않는 곳에서 알아서 펼쳐줘야 한다.

반면 IDE를 쓰는 사람들에게는 다른 방향으로 욕구가 작용하게 된다. 복제된 정보가 여러 파일에 걸쳐 늘여놓여 있어도 문제가 없다. 그것들은 기계적인 방식으로 하나의 정보인 것처럼 동시에 수정될 수 있기 때문이다. 단, 그것들이 하나의 정보라는 것을 기계적으로, 코드를 수정하는 시점에, 즉 정적으로 입증 가능해야 한다. 따라서 동적 타이핑을 하는 언어는 꺼려지게 된다. 리팩토링 도구의 사각지대이기 때문이다.

점을 찍으면 알아서 해당 타입에 대해 사용할 수 있는 연산들이 눈앞에 보이고, 메서드 이름이 거의 문서와 같이 길게 늘여놓여 있어서 그것만 보고 뭘 하는 연산인지 짐작할 수 있고, 그 긴 메서드 이름을 직접 입력하는 것이 아니라 화살표로 위 아래를 눌러서 고른 다음 엔터치는 것만으로 완성이 되길 원하는데, 동적 타이핑을 하는 언어는 해당 값이 런타임에 어떤 타입이 될지 확정 불가능하며, 심지어 Ruby 같은 언어의 경우 클래스가 열려있기 때문에 라이브러리를 몇개만 갖다 써도 해당 타입에서 쓸 수 있는 연산이 알지도 못하는 순간에 추가되게 된다.

사람의 욕구는 기본적으로 비슷한 면을 많이 공유한다. 코딩에 있어서 손을 적게 움직여서 원하는 것을 이루고자 하는 욕구는 비슷하다. 하지만 Vim 사용자의 해법은 코드의 분량을 줄이는 것이고, IDE 사용자들의 해법은 키스트로크의 횟수를 줄이는 것이다. 그러다보니 어느쪽 사람들은 값의 타입이 추론될 수 있어야 한다고 보는 한편 다른쪽 사람들은 값의 타입이 무엇인지 코드 상에서 눈에 보여야 한다고 다르게 생각하게 되는 것이다. 어떤 편집기를 사용하느냐가 이렇듯 언어에 관한 취향에 반영된다.

현실에서는, 각 도구를 쓰는 사용자들은 서로를 안 좋은 도구를 쓴다고 생각한다. Vim 사용자들은 IDE 사용자들을 보고 키 몇번이면 수정할 수 있는 것들을 매우 긴 시간을 들여서 고치며 코드만 길어지는 안 좋은 언어를 쓴다고 생각하고 반대로 IDE 사용자들은 Vim 사용자들을 보고 리팩토링 도구를 쓰면 되는데 손으로 모든 것을 다 고치고 자동 완성도 안되는 안 좋은 언어를 쓴다고 생각한다. 하지만 실상은, Vim 사용자들은 굳이 자동 완성을 써야할 정도로 메서드 이름이 긴 문화에서 살지도 않으며, 리팩토링 도구가 필요할 정도로 같은 정보를 여러 군데에 늘어놓는 언어를 쓰지도 않는다(사실은 어떤 언어를 쓰더라도 같은 정보를 여러 군데에 늘어놓아야만 하는 경우는 생기기 마련이다). 마찬가지로 IDE 사용자들은 애초에 리팩토링 도구를 쓰므로 코드의 분량이 늘어나도 그렇게까지 고생을 하지 않는다(사실 IDE를 써도 코드 분량이 길어지면 결국 한 눈에 보기 힘들어지긴 한다).