In part one에서 나는 마크다운이 아무도 투표하지 않았음에도 불구하고 명세(specification) 계층에서 승리했다고 주장했으며, 우리가 버전 관리와 코드 검토 방식을 그대로 가져가면서 우리 분야의 나머지 부분은 뒤에 남겨두었다. 이것이 바로 부재(absence)가 허용하는 구체적인 지점이다.
명세 기반 개발은 대체로 옳으며, 나는 이 방식에 맞춰 팀 운영 방식을 재정비한 사람으로서 그렇게 말한다.
그 주장은 타당하다. 구현을 생성하는 것이 저렴해지면, 명세의 품질이 제약 조건(constraint)이 된다. Sean Grove가 The New Code에서 제시한 틀은 이를 가장 명확하게 설명한다: 프롬프트는 일시적이지만, 버전 관리되는 명세는 시간이 지남에 따라 인간과 모델을 정렬시킨다. GitHub's Spec Kit, AWS Kiro 및 Claude Code는 모두 이 전제에 기반하여 실제 도구들을 구축했다. 움직임의 급진적인 끝단에서는 인간이 명세만 편집하고 코드를 컴파일된 아티팩트(compiled artifact)로 취급한다.
나는 그 방향이 옳다고 생각한다. 또한 내가 사용하는 것을 포함하여 이 움직임이 표준화한 형식들 모두가 같은 섹션을 빠뜨리고 있다고 생각한다.
계속해서 잘못되는 것: 다운스트림 문제점
전달 수치(delivery numbers)가 특정한 방식으로 이상하다.
Sonar의 LinearB 2026 엔지니어링 벤치마크 보고서에 따르면, AI 지원 풀 리퀘스트는 사람이 작성한 것보다 약 절반의 속도로 병합된다고 한다. 또한 이들은 약 2.5배 더 크며 검토를 기다리는 시간은 대략 다섯 배나 길다.
Happy Bhati가 에이전트 기반 소프트웨어 개발 수명 주기(agentic software development lifecycle)에 대해 발표한 논문도 구조적으로 같은 점을 지적합니다. 에이전트는 소프트웨어 제공의 병목 현상을 변화시키지만, '검토(review), 통합(integration), 테스트(testing), 보안(security), 배포(deployment), 그리고 운영(production operations)은 여전히 제약적인 단계로 남아 있습니다.' 논문에 따르면, 필드 연구를 통해 얻는 이득은 코드를 작성하는 것과 신뢰할 수 있는 소프트웨어를 출시하는 것 사이에서 급격히 감소합니다.
결국 코드는 더 빨리 생산되지만, 채택되는 비율은 절반 수준에 머뭅니다. 실패는 '생산된' 단계와 '채택된' 단계 사이에 발생하며, 이는 명세(spec) 움직임이 가장 적은 시간을 할애한 파이프라인 부분입니다.
명세는 한 방향을 가리킨다
명세는 목적지(destination)를 설명합니다. 그것이 온전한 역할이며, 이 역할에 있어서는 뛰어납니다.
하지만 결과를 수용하려면 다른 것이 필요합니다. 지금 가진 것과 이전에 가지고 있던 것을 비교하여 그 차이가 우리가 요청했던 것인지 결정해야 합니다. 이러한 비교에는 '기원(origin)'이 필요합니다.
거의 모든 명세 형식은 기원을 담고 있지 않습니다. 명세를 작성한 사람은 자신이 작업을 수행할 가치가 있다고 결정했을 때, 머릿속에 그것을 가지고 있었습니다. 그들은 무엇이 잘못되었는지 알고 있었고, 아마도 그것이 발생하는 것을 본 적이 있을 것이며, 그리고는 원하는 것만 글로 적어 나머지 부분은 버렸습니다.
이는 저자가 건물 내에서 작업이 완료되었는지 여부를 말할 수 있는 유일한 사람이라는 의미입니다.
과거에는 인간 엔지니어가 구현을 담당했기 때문에 이것이 생존 가능했습니다. 왜냐하면 인간은 명세를 읽고, 간극(gap)을 알아차리며, 맥락(context)으로부터 조용히 채우기 때문입니다. 그들은 제품을 본 적이 있고, 사용자가 무엇에 대해 불평했는지 알고 있습니다. 아무도 요청하지 않아도 부족한 절반을 공급합니다.
하지만 에이전트는 그것을 문자 그대로 읽고 단어가 설명하는 것을 정확하게 구축합니다. 부족한 절반은 여전히 빠져있게 되고, 이는 검토 단계에서 표면화되며, 바로 여기서 병합률(merge-rate) 수치가 나오는 것입니다.
명세는 주장이다
최근 저는 한 번도 실패한 테스트를 지켜보지 않은 테스트에 대해 글을 썼습니다. 이미 통과하는 코드를 기반으로 작성된 테스트는, 작성되는 순간부터 구조적으로 참이었으며, 작동하는 시스템과 고장 난 시스템을 구별해낸 적이 단 한 번도 없습니다. 그것은 커버리지를 높이고 아무것도 검증하지 못합니다.
명세(spec) 역시 한 단계 위에서 같은 형태를 가집니다. 그것은 제품이 특정 방식으로 동작해야 한다고 주장할 뿐입니다. 만약 아무도 그 제품이 그렇게 동작하지 않는 실패 사례를 관찰한 적이 없고, 그 실패가 어떤 모습이었는지 문서로 남긴 사람이 없다면, 그 주장은 작성자 외에는 누구도 확인할 수 없습니다.
같은 질병, 다른 산물입니다.
누락된 섹션
이것은 사람들이 게으른 명세를 작성한다는 주장이 아닙니다. 이것은 구조적인 문제이며, 약 10초 만에 스스로 확인할 수 있습니다.
여기에 GitHub의 Spec Kit가 생성하는 명세 템플릿을 제목 그대로 보여드립니다:
# Feature Specification: [FEATURE NAME]
Feature Branch | Created | Status | Input
...
141,000개의 스타를 받은 도구 키트에 12개의 제목이 있으며, 그중 세 개가 필수 항목으로 표시되어 있습니다.
그 목록을 읽어보면서 오늘 실제로 무슨 일이 일어나고 있는지 작성하는 부분을 찾아보세요. 성공 기준(Success Criteria)은 목적지를 설명합니다. 엣지 케이스(Edge Cases)는 새로운 동작이 생존해야 할 상황들을 설명합니다. 각 사용자 스토리 안에 있는
따라서 이렇게 명세된 작업이 구현되어 돌아왔을 때, 그것이 작동했는지 여부를 말할 수 있는 사람은 오직 그 작업을 작성한 날에 머릿속으로 '이전 상태(before-state)'를 가지고 있던 사람뿐입니다. 다른 모든 사람들은 목적지에 대한 설명을 읽고 작가의 말을 믿는 것과 같습니다.
제가 추가하고 싶은 부분
사용자 스토리 앞에 배치할 섹션 하나가 필요합니다.
## 현재 동작(Current behaviour) (필수)
문제점(Problem)
...
이렇게 채워지면 다음과 같습니다.
## 현재 동작(Current behaviour)
문제점(Problem)
...
세 문장과 번호가 매겨진 목록으로 구성됩니다. 주목할 점은 이 내용 중 어느 것도 에이전트에게 무언가를 어떻게 구축해야 하는지 알려주지 않는다는 것인데, 이것이 의도적입니다. 이는 '격차(gap)'를 명시함으로써 목적지를 지정합니다.
이렇게 함으로써 이전에는 그렇지 않았던 세 가지 사실이 진실이 됩니다.
작성자와 대화해 본 적 없는 검토자라도 작업을 검증할 수 있습니다. 왜냐하면 재현 단계가 바로 거기에 놓여 있고, 그들이 여전히 20개의 항목을 생성하는지 아니면 그렇지 않은지 알 수 있기 때문입니다.
에이전트는 자신이 요청받은 내용을 스스로 해석한 것에 의존하기보다는, 명시된 관찰 가능한(observable) 기준과 비교하여 자신의 출력을 점검할 수 있습니다.
그리고 승인 기준(acceptance criterion)은 제품 내에 이미 존재하는 두 숫자의 비교가 되며, 이는 '전체 결과 세트를 통틀어 페이지를 넘기는 것'보다 우연히 만족시키기가 훨씬 더 어렵습니다.
전체 구성
완벽한 명세서에는 하나의 추가 섹션이 Spec Kit 자체의 구조 안에서 들어갑니다.
# 기능 명세: 주간 요약본 완성(Feature Specification: Complete Weekly Digest)
기능 브랜치(Feature Branch): 014-complete-weekly-digest
...
이는 관찰 가능하고 재현 가능하며 문서화할 수 있는(writable) 동일한 섹션에서 확인할 수 있습니다:
Problem
어떤 고객이 이탈했는지 알 방법이 없습니다. 계정 관리자들은 현재 전체 고객 목록을 내보내 스프레드시트에서 정렬합니다...
만약 어떤 기능에 대해 해당 섹션을 작성할 수 없다면, 그것 자체가 유용한 정보입니다. 이는 보통 당신이 아직 아무도 더 나은 방법을 수행하는 사람이 아니라는 것을 의미합니다.
구현 세부 사항을 추가하는 것이 왜 상황을 악화시키는가
과잉 명세(Over-specification)는 이미 명명된 실패 모드이며, 스펙 부패(spec-rot) 및 느린 시작(slow starts)과 함께 명세 기반 개발에서 논의됩니다. 저는 이 메커니즘에 대해 더 구체적으로 이야기하고 싶습니다. 왜냐하면 '과잉 명세를 하지 말라'는 조언은 아무도 실행할 수 없기 때문입니다.
사람들이 압박감 속에서 추가하는 세부 사항은 미래 지향적인(forward) 세부 사항입니다. 무엇을 구축해야 하는지에 대한 더 많은 글머리 기호, 건드려야 할 클래스, 취해야 할 접근 방식 등 말이죠. 이 모든 줄들은 두 가지 일을 합니다. 당신이 고려하지 못했던 경로를 찾으려는 에이전트의 자유도를 제거하고, 작업 결과가 돌아왔을 때 검증할 수 있는 것은 아무것도 추가하지 않습니다.
당신은 명세 예산을 문제였던 문서의 절반에 쓰고 있습니다. 현재 무슨 일이 일어나고 있는지, 어떻게 볼 수 있는지, 그리고 어떤 숫자가 바뀌어야 하는지에 대해 쓴 똑같은 열 줄만으로도 당신을 한 번도 만난 적 없는 사람이 결과를 검증할 수 있게 합니다.
이것이 팀에서 변화시키는 것
제 팀이 사용하는 형식은 일곱 개의 필드를 가지고 있습니다. 문제(Problem), 증거(Evidence), 재현 단계(Steps to reproduce), 예상 결과(Expected result), 범위(Scope), 승인 기준(Acceptance criteria), 그리고 범위를 벗어난 항목(Out of scope)입니다. 이 중 여섯 개는 일반적입니다. 핵심이 되는 것은 관찰 가능한 이전 상태(observable before-state)인데, 재현 가능한 증상이 없는 티켓은 누구에게도 승인받을 수 없기 때문입니다.
이것이 강제된 후 세 가지가 사라졌습니다.
작업이 이식 가능해졌습니다. 재현 단계가 포함된 명세는 대화 없이도, 또는 에이전트가도 맡아 진행할 수 있으며, 쓰여지지 않았던 맥락을 복구할 필요가 없습니다.
검토 비용이 절감되었습니다. 검토자는 diff에서 의도를 재구성하는 것이 아니라, 세 단계를 실행하고 숫자를 읽습니다.
그리고 상당수의 제안된 티켓들이 작성 단계에서 폐기되었는데, 그 이유는 그것을 작성한 사람이 해당 문제가 존재한다는 증거를 제시할 수 없었기 때문입니다. 이것이 제가 예상하지 못했던 부분이며, 이 목록에 있는 다른 어떤 것보다도 더 많은 엔지니어링 시간을 절약해 주었습니다.
주장
우리는 프로세스 자체에 우리가 구축한 것에 대해 모델들에게 책임을 전가하고 있습니다. 검증할 수 없는 명세는 받아들여질 수 없는 결과물을 낳으며, 업계 전체가 이 사실을 깨닫고 있습니다. 왜냐하면 이전에는 조용히 빠져 있던 절반의 부분을 공급하던 인간들이 그 단계에서 제외되었기 때문입니다.
명세(Specs)가 새로운 코드가 되었습니다. 좋습니다. 그렇다면 명세는 코드에게 항상 필요했던 것, 즉 작성자 본인이 아닌 다른 사람이 평가할 수 있는 명시된 기대치(stated expectation)를 필요로 합니다.