Martin(arp242)이 최근 레거시 프로젝트를 하나 인수했다. 그가 진짜로 코드를 읽기 전에 가장 먼저 한 일은 — 명령어 한 줄을 실행하는 것이었다:
git log --no-merges --format=format:'%b' | sed '/^$/d' | wc -l
결과는 295. 13년 동안 이 프로젝트의 모든 커밋 설명을 다 합쳐도 295줄에 불과했다. dependabot 자동 커밋, ‘revert commit’, ‘fix typo’를 제외하면 167줄이 남았다. 평균 월 1줄이다.
문서는 없었다. 주석은 거의 없었다. 그리고 전임 개발자의 3주 인계 기간 동안의 소통 수준은 커밋 로그와 동급이었다. Martin은 이렇게 썼다: “Jack Bauer가 극단적 수단으로 정보를 얻어내는 심정을 그렇게 이해한 적이 없었다. 직접 해볼걸 그랬다.”
울타리의 양면
체스터턴의 울타리 원칙은 소프트웨어 엔지니어링에서 오랫동안 회자되어 왔다: 이상한 코드를 발견하고 지우고 싶어질 때, 먼저 왜 거기에 있는지 알아내야 한다 — 당신이 의식하지 못한 어떤 위험을 막고 있을지도 모른다. 이것이 정면이다. G.K. Chesterton의 원래 말은, 개혁가가 울타리를 허물기 전에 반드시 “왜 여기 세워졌는가”에 답할 수 있어야 한다는 것이다.
Martin은 그 뒷면을 제시했다 — 체스터턴의 중지.
“그래, 우리는 이 모든 이상한 일들을 했지만, 아무에게도 이유를 말할 생각이 없어. 엿이나 먹어.”
울타리의 존재 의미는 맥락에 의존한다. 그 맥락이 커밋 메시지, 주석, 문서와 함께 사라지면, 울타리는 더 이상 보호가 아니라 저주다. 후임 개발자가 마주하는 것은 명판 없는 유적이다: 설명할 수도 없고 분류할 수도 없는 잡동사니 더미. 몇 달에 걸쳐 고고학을 하든지, 아니면 위험을 무릅쓰고 허물어버리든지.
세 가지 독성 커밋
Martin이 체계적으로 분류한 것은 아니지만, 그의 묘사는 가장 파괴적인 세 가지 커밋 패턴을 드러낸다:
“fix page A” — 공허한 제목. 대규모 수정에도 커밋 제목은 “fix page A”뿐이다. 제목은 아무 정보도 전달하지 않고, 본문은 비어 있다. 후임 개발자는 줄 단위 diff를 거꾸로 추적하며 의도를 추론해야 한다 — 정확도는 뼈점술 수준이다.
WIP 커밋 — 반쯤 완성된 채 방치됨. 미완성 리팩토링이 코드베이스에 흩어져 있다. 옛 기능의 잔해는 정리되지 않았다. 이미 추가되었지만 어디에도 링크되지 않았고, 어떤 사용자도 사용한 적 없는 기능이 코드 깊숙이 잠들어 있다. 이것들은 버그가 아니지만, 버그보다 더 까다롭다 — 버그는 적어도 누군가 제보라도 한다.
“필요 없음”형 — 체스터턴의 공백. Martin은 대칭 개념을 도입한다: 체스터턴의 울타리가 “벽을 쌓고 이유를 말하지 않는 것”이라면, 체스터턴의 공백은 “벽이 필요 없는 곳에도 벽을 세우는 것”이다 — 아무도 필요로 하지 않은 곳에 추상화 계층을 추가하고, 과도하게 엔지니어링하며, 존재하지 않는 미래 수요를 위한 설계를 미리 심어둔다.
이 세 패턴은 함께 코드베이스의 고고학적 재앙을 구성한다: 후임자는 코드가 무엇을 하는지 이해해야 할 뿐 아니라, 전임자가 왜 그렇게 했는지, 그리고 그들이 당시 무엇을 의도했는지까지 추론해야 한다.
세 가지 질문
Martin은 현실적인 커밋 메시지 프레임워크를 제시한다 — 세 가지 질문:
- 무엇을 바꿨는가?
- 왜 바꿨는가?
- 왜 이것이 좋은 해결책인가?
“Implement new feature X”로 충분할 때도 있지만, 대부분의 경우 말할 게 있다 — 파라미터 선택의 이유, 경계 조건의 출처, 거부된 대안 같은 것들도 포함해서.
아름다운 영어일 필요는 없다. 철학 논문처럼 쓸 필요도 없다. 어떤 포인트는 깜빡해도 괜찮다(하지만 쓰는 게 더 낫다). 마지노선은: 뭐라도 있으면 된다. 어떤 반쯤 진지한 시도도 빈칸보다 무한히 낫다.
Martin의 판단은 단호하다: “커밋 메시지를 쓰는 것은 선택 가능한 부가 작업이 아니다. 그것은 일의 일부다. 쓰지 않는 것은 본職을 완수하지 않는 것이다.”
Lobsters 커뮤니티의 합의
Lobsters에서 이 글은 106점을 받았고, 댓글란에는 논쟁이 거의 없었다. 한 사용자는 이렇게 썼다: “나는 전 세계를 돌며 이런 코드베이스를 수리하는 데 5년을 보냈다. 《Working Effectively with Legacy Code》를 베개 삼아 잔다.”
또 다른 사용자 david_chisnall의 관점은 코드 리뷰의 핵심 가치를 정확히 찔렀다: “코드 리뷰의 가장 큰 이점은 입 밖에 내지 않은 모든 맥락을 강제로 적게 만든다는 것이다. 당신이 설명 못 하는 것, 리뷰어가 이해 못 하는 것, 전부 주석에 써야 한다.”
반복적으로 언급된 시나리오: 동료가 퇴사한 후의 코드베이스를 이어받는 상황. 누구에게도 물어볼 수 없을 때, 커밋 로그가 마지막 정보원이다. 만약 그것이 비어 있다면, 당신이 마주한 것은 코드가 아니다 — 고고학 현장이며, 모든 비문은 의도적으로 지워진 것이다.
왜 오늘날 이 문제가 특히 중요한가
AI 코딩 도구(Codex, Claude Code, Copilot)가 코드 생산 속도를 한 자릿수 이상 끌어올리고 있다. 하지만 커밋 메시지는 자동으로 생성되지 않는다 — 더 정확히 말하면, 자동 생성된 “Add files via upload”, “Update code”는 빈칸보다 더 나쁘다. ‘문서가 있다’는 환각을 만들어내기 때문이다.
13년 동안 커밋 메시지가 295줄뿐인 프로젝트는, AI 보조 프로그래밍 시대에 더 적어지지는 않을 것이다. 더 많아질 것이다. 코드 생산이 주석 작성보다 더 빠르고, AI는 아직 “왜 이 자료구조를 선택했는지 여기에 설명했어야 하는데”라고 당신 대신 느껴주지 않기 때문이다.
Martin은 마지막에 이렇게 썼다: “아무것도 쓰지 않는다면, 당신은 모든 후임자에게 중지를 날리고 있는 것이다.” 이 비유는 거칠지만, 정확하다. 커밋 메시지는 당신 자신을 위한 메모가 아니다 — 3년 후의 당신에게, 당신의 일을 이어받은 동료에게, 한밤중에 on-call로 호출되어 regression을 추적하는 그 사람에게 쓰는 것이다.
이 글의 소재는 공개 정보와 커뮤니티 논의에서 가져왔습니다. 이 주제에 대해 더 깊이 있는 일차 경험이 있다면 글의 부족한 점을 지적해 주시기 바랍니다.