본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 22. 15:29

README에는 80개라고 적혀 있었지만, 실제 코드는 96개였습니다. 몇 주 동안 아무도 눈치채지 못했습니다.

요약

오픈 소스 MCP 서버 운영 중 README의 문서 내용과 실제 코드 간의 수치 불일치(Drift)를 발견한 사례를 다룹니다. 문서화되지 않은 기능이 오히려 가장 강력하고 중요한 도구일 수 있다는 교훈을 전달합니다.

핵심 포인트

  • 문서와 코드 간의 수치 불일치(Drift)는 점진적으로 발생함
  • 문서화되지 않은 기능은 프로젝트에서 가장 강력한 도구일 가능성이 높음
  • 단순한 문서 업데이트를 넘어, 기능의 중요도와 문서화의 상관관계를 경계해야 함

저는 오픈 소스 MCP (Model Context Protocol) 서버를 운영하고 있습니다. 이 서버는 AI 코딩 에이전트에게 브라우저 자동화 도구들을 제공합니다. 예를 들어, 특정 요소를 클릭하거나, 페이지를 읽거나, 양식을 채우는 등의 작업입니다. README에는 "80개의 도구"라는 자랑스러운 표가 크게 들어있습니다. 태그라인(tagline)에도, 네비게이션 앵커(nav anchor)에도, 소셜 미리보기 이미지의 대체 텍스트(alt text)에도, 두 개의 비교 테이블(comparison tables)에도 그 숫자가 적혀 있습니다. 심지어 공유 버튼을 위한 미리 작성된 트윗 텍스트에도 포함되어 있습니다.

80개. 모든 곳에 80이라고 적혀 있었습니다.

지난주에 저는 지루한 감사(audit)를 진행했습니다. 단순히 README가 주장하는 내용과 코드가 시작 시점에 실제로 register(등록)하는 내용을 비교(diffing)해 본 것이었습니다. 코드는 96개를 등록하고 있었습니다.

80개가 아니었습니다. 96개였습니다. 아홉 군데의 서로 다른 위치에서 숫자가 틀려 있었고, 매번 그 숫자를 직접 타이핑한 사람은 바로 저였습니다.

숫자가 부패하는 방식

README에서 거짓말을 하기로 결심하는 사람은 아무도 없습니다. 드리프트(Drift, 괴리)는 한 번의 머지(merge)마다 조금씩 발생합니다.

기능을 배포합니다. 도구가 3개 추가됩니다. 리뷰어들이 확인하는 부분인 도구 _목록(list)_은 업데이트하지만, 태그라인에 있는 숫자는 잊어버립니다. 다음 릴리스에서 4개가 더 추가됩니다. 이제 목록이 말하는 것과 태그라인이 말하는 것이 서로 달라지고, 둘 다 실제 상황보다 뒤처지게 됩니다. "작고 빠른" 릴리스가 한 달 동안 이어진 후, 그 격차는 16개가 됩니다.

가장 최악인 부분은 태그라인조차 아니었습니다. 도구 목록(list) 자체의 항목을 실제로 세어 보았을 때, 거기에는 83개의 도구가 문서화되어 있었습니다. 즉, 하나의 파일 안에 세 가지 서로 다른 진실이 공존하고 있었던 것입니다:

  • 마케팅용 숫자: 80
  • 문서화된 목록: 83
  • 코드: 96

13개의 도구는 존재하고, 작동하며, npm으로 배포되었고, 실제 사용자들의 기기에서 실행되고 있었지만 — 완전히 문서화되지 않은 상태였습니다. 그 도구들은 README에 전혀 언급되지 않았습니다. 만약 제 문서를 읽기만 했다면, 그 도구들이 존재하는지조차 몰랐을 것입니다.

당신이 잊어버린 도구가 바로 중요한 도구입니다

문서 정리 작업이 진심으로 불편한 오후로 변하게 된 지점은 바로 여기입니다.

문서화되지 않은 13개는 safari_wait_for_new_tab 같은 지루한 헬퍼(helper) 함수들일 것이라고 예상했습니다. 실제로 일부는 그랬습니다. 하지만 그중 4개는 네이티브 입력 (native input) 도구였습니다. 이는 페이지에 주입된 JavaScript를 통하는 것이 아니라, OS 레벨의 이벤트 API (CGEvent)를 통해 구동되는 합성 키보드 및 마우스 이벤트였습니다.

이것들은 프로젝트 전체에서 가장 강력한 도구들입니다. JavaScript 레벨의 자동화는 페이지에 의해 샌드박스(sandboxed) 처리되지만, OS 레벨의 입력은 그렇지 않습니다. 이는 포커스가 있는 무엇이든 타이핑할 수 있습니다. 이는 "이 <input>을 채워라"와 "시스템 레벨에서 물리적인 키를 눌러라"의 차이입니다. 이는 보안을 중시하는 사용자가 접근성(Accessibility) 권한을 부여하기 전에 반드시 읽어보고 싶어 할 바로 그 범주입니다.

그리고 그것은 제가 단 한 번도 기록해 두지 않았던 범주였습니다.

이것이 진짜 교훈이며, 단순히 "문서를 최신 상태로 유지하라"는 뜻이 아닙니다. 핵심은 이것입니다: 문서 드리프트 (documentation drift)는 당신이 문서화되지 않기를 가장 바라는 것들을 향해 선택 편향 (selection-biased)되어 있다는 점입니다. 당신이 문서화하는 것을 잊어버리는 도구들은 기능 브랜치(feature branch)에서 마감 기한에 쫓겨 급하게 추가된 것들입니다. 이는 강력하거나, 날카롭거나, 보안과 관련된 도구들과 거의 완벽하게 상관관계가 있습니다. 평범한 것들은 쉬우니까 문서화됩니다. 위험한 것들은 TODO로 남겨집니다.

어떤 프로젝트에서 가장 위험하고 검토가 덜 된 영역을 찾고 싶다면, 문서를 읽지 마세요. 문서와 코드 사이의 간극을 읽으세요.

"그냥 README를 업데이트하세요"는 잘못된 해결책입니다

유혹적인 해결책은 숫자를 수정하는 것입니다. 80을 96으로 바꾸고, 누락된 13개의 항목을 추가한 뒤 커밋(commit)하면 끝입니다. 저도 그 작업을 했습니다. 하지만 그것은 증상만을 치료하는 것입니다.

숫자가 틀렸던 이유는 그것이 수동으로 관리되었기 (hand-maintained) 때문입니다. 사람이 직접 입력하는 모든 사실은 결국 현실과 일치하지 않게 됩니다. 유일하고 지속 가능한 해결책은 사실을 틀리는 것이 불가능하게 만드는 것입니다. 즉, 사실을 다시 진술하는 대신 신뢰할 수 있는 원천 (source of truth)으로부터 이를 도출(derive)하는 것입니다.

아이러니하게도, 제 프로젝트의 한 곳에는 이미 이 문제가 해결되어 있었습니다. 제가 아닌 다른 누군가가 기여한 스모크 테스트 (smoke test)가 있었는데, 이 테스트는 실제 stdio 전송 (stdio transport)을 통해 서버를 부팅하고, 서버에 등록된 도구 (tool)가 몇 개인지 물어본 뒤, 소스 (source)로부터 도출된 (derived) 수치와 비교하여 검증합니다. 하드코딩된 숫자를 사용하지 않는 것입니다. 도구를 추가하면 테스트의 기대값도 자동으로 함께 움직입니다. 그 테스트는 결코 80개로 어긋날(drift) 수 없었습니다. 왜냐하면 어긋날 대상인 '80'이라는 숫자를 애초에 *저장(stored)*하고 있지 않았기 때문입니다.

따라서 해결책은 "README를 더 엄격하게 관리하자"가 아닙니다. 엄격함(discipline)이야말로 한 달 내내 실패했던 요소입니다. 진짜 해결책은 다음과 같습니다:

  • 수치 (Counts) → 생성(generate)하세요. 빌드 타임 (build time)에 등록 사항을 읽어 README에 숫자를 써넣는 아주 작은 스크립트를 만드세요. 사람은 절대 직접 입력하지 않습니다.
  • 도구 목록 (Tool lists) → 이것 역시 생성하세요. 이상적으로는 서버가 시작될 때 읽는 것과 동일한 레지스트리 (registry)로부터 생성하는 것이 좋습니다. 스키마 (schema)는 이미 구조화된 데이터입니다. 이를 마크다운 (Markdown) 표로 렌더링하는 것은 포맷팅 (formatting)의 문제이지, 작성 (writing)의 문제가 아닙니다.
  • 주변 설명 (The prose around them) → 이 부분이 바로 사람이 실제로 주의를 기울여야 할 부분입니다. 생성기 (generator)가 작성할 수 없는 부분이기 때문입니다.

문서에 포함된 모든 사실은 도출 가능하거나, 그렇지 않거나 둘 중 하나입니다. 도출 가능한 사실은 절대로 수동으로 입력해서는 안 됩니다. 그것들은 곧 발생할 '어긋남 (drift)'을 기다리는 상태일 뿐입니다.

30초면 끝나는 점검

만약 여러분이 "우리는 N개의 기능 / N개의 도구 / N개의 통합을 보유하고 있다"라는 주장을 유지하고 있다면, 다음의 감사를 수행해 보십시오. 저는 단 한 번의 명령어로 이를 확인했습니다:

  1. 코드 내의 실제 대상(등록 사항, 내보내진 함수, 라우트 핸들러 등 — 여러분의 N이 실제로 세고 있는 것이 무엇이든)을 세어보세요.
  2. README가 주장하는 수치를 세어보세요.
  3. 두 수치가 일치하지 않는다면, 단순히 오래된 숫자를 가지고 있는 것이 아닙니다. 여러분은 실제로 존재하지만 아무도 기록하지 않기로 선택한 항목들의 목록을 가지고 있는 것입니다. 목록을 읽어보세요. 그것이 여러분의 저장소 (repo)에서 가장 흥미로운 목록일 것입니다.

제 경우에는 그 차이가 16개의 도구까지 벌어져 있었고, 프로젝트에서 가장 날카로운 도구들이 그 차이 속에 포함되어 있었습니다. 여러분의 차이는 더 작을 수도 있습니다. 하지만 "우리는 절대 확인하지 않는다"와 "숫자가 정확하다"는 같은 상태가 아니며, 이 둘을 구분하는 유일한 방법은 직접 확인하는 것뿐입니다.

이 글은 macOS용 AI 에이전트를 위한 오픈 소스 Safari 자동화 서버인 Safari MCP(이제는 96개라고 정확히 기재되어 있습니다)를 유지 관리하며 작성되었습니다. 저는 achiya-automation.com에서 소규모 오픈 소스 소프트웨어 (OSS) 프로젝트를 운영하며 겪는 화려하지 않은 부분들에 대해 글을 씁.

여러분의 프로젝트에서 문서와 코드 사이의 간극이 가장 컸던 사례는 무엇이었나요? 그리고 그 간극 사이에 있었던 내용은 지루한 것이었나요, 아니면 무서운 것이었나요?

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0