소프트웨어를 두 번 쓰지 마라: 명세 주도 개발과 재작성의 종말

Albert Santalo avatar
Albert Santalo 8분 분량
소프트웨어를 두 번 쓰지 마라: 명세 주도 개발과 재작성의 종말

소프트웨어가 왜 늘 두 번 쓰였는지 — 한 번은 명세로, 다시 한 번은 코드로 — 그리고 그 두 번째 쓰기가 왜 마침내 사라지고 있는지.

소프트웨어 개발에서, 제대로 한다면 우리는 소프트웨어를 두 번 써야 한다. 먼저 소프트웨어가 정확히 무엇을 해야 하는지 설명하는 상세한 명세로, 그다음 그 명세에 생명을 불어넣는 코드로. 그런데 냉정한 사실이 있다. 처음부터 제대로 되는 일이 드물다.

이 과정이 자주 무너지는 이유는 빠짐없는 명세를 만드는 데 시간이 많이 들고, 팀이 필요한 모든 세부를 앞단에서 포착하는 일이 드물기 때문이다. 그것은 공백과 가정과 값비싼 재작업으로 이어진다. 그 결과 소프트웨어 프로젝트는 자주 예산을 초과하고, 기한을 놓치고, 모두를 좌절시킨다.

소프트웨어를 두 번 쓰는 데 드는 숨은 비용

소프트웨어를 두 번 쓰는 일이 왜 필요하면서도 잘 되는 일이 드문지 이해하기 위해, 두 단계를 나눠 보자.

1. 첫 번째 쓰기: 자연어 명세

소프트웨어가 처음 쓰이는 그때, 우리는 코드를 쓰고 있지 않다. 그것은 요구사항, 사용자 스토리, 설계 문서를 만드는 일이다 — 자연어로 쓰인다. 여기서 팀은 소프트웨어가 어떻게 기능해야 하는지, 사용자가 무엇을 할 수 있는지, 경험이 어떠해야 하는지를 서술한다.

그런데 문제가 있다. 모든 세부를 다 쓸 여유를 가진 팀은 없다. 프로덕트 매니저는 종종 공격적인 일정을 맞추려고 서둘러야 한다 — 어떤 프로젝트에는 전문 프로덕트 매니저 자체가 없다. 그들은 큰 줄기를 그리지만 핵심 기능과 상호작용은 빠진다. 스티브 잡스의 유명한 말처럼 「훌륭한 제품은 5,000개의 작은 결정으로 만들어진다」. 그런데 대부분의 프로젝트에서 우리는 그 결정들을 앞단에서 내리지 않는다. 그것은 나중에 개발자가 해석하도록 남겨지고, 그것이 두 번째 단계로 이어진다.

2. 두 번째 쓰기: 명세를 코드로 번역하기

명세가 넘겨지면 엔지니어는 그 서술을 작동하는 코드로 바꾸는 책임을 진다. 그런데 첫 번째 「쓰기」가 불완전할 때, 개발자는 상상력으로 공백을 채우도록 강요된다. 가정이 만들어지고, 엔지니어가 기술을 잘 파악하고 있더라도 제품 비전의 전체 그림은 갖고 있지 않을 수 있다.

여기서 문제가 수면으로 올라온다.

  • 빠진 세부가 마찰을 낳는다: 프로덕트 팀이 중요한 기능이나 사용 사례를 명시하지 않으면 개발자는 추측하거나 즉흥적으로 해야 한다. 그것은 자주 기대에 맞지 않는 기능으로 이어진다.
  • 가정이 재작업을 낳는다: 개발자가 공백을 채우면, 제품 비전과 맞지 않는 방식으로 기능을 만들 수 있고, 프로젝트 후반에 대규모 재작업을 초래한다.
  • 책임 전가가 불가피해진다: 기한이 밀리고 예산이 넘치면 팀은 비난을 옮긴다. 프로덕트 팀은 엔지니어링이 「이해하지 못했다」고 지적하고, 엔지니어는 명세가 불분명했다며 프로덕트를 가리킨다.

그 결과는 놓친 일정과 초과된 예산과 만족스럽지 않은 결과로 이어지는 문제의 연쇄다. Standish Group의 CHAOS 연구는 대부분의 소프트웨어 프로젝트가 예산을 초과하고 납기를 놓친다는 것을 수년간 추적해 왔다. McKinsey가 옥스퍼드 대학과 함께 한 연구는, 대규모 IT 프로젝트가 평균 45% 예산 초과와 7% 일정 초과를 겪으면서 예측보다 56% 적은 가치를 전달한다는 것을 — 그리고 대규모 IT 프로젝트의 17%는 회사의 존립 자체를 위협할 만큼 나쁘게 진행된다는 것을 — 발견했다.

분명히, 이 과정의 무언가가 고장 나 있다.

이 실천에는 이제 이름이 있다

대부분의 사람이 프롬프트를 두고 논쟁하는 동안 업계는 이것에 대한 용어에 정착했다. 명세 주도 개발. 요구사항과 제약과 성공 기준을 먼저 쓴다. 그 명세를 사실의 원천으로 대한다. 에이전트가 그것에 맞춰 만들게 한다.

GitHub은 Spec Kit을 냈다. AWS는 Kiro를 냈다. BMAD-METHOD, OpenSpec, Tessl 모두 각자 시도했다. Martin Fowler도 이에 관해 썼다. 이 수렴은 우연이 아니다 — 하나의 카테고리 전체가 같은 실패 양상을 같은 시점에 발견할 때 벌어지는 일이다.

그리고 그 실패 양상은 위에서 설명한 그것이다. 프롬프트부터 시작하는 도구는 첫 번째 쓰기를 완전히 건너뛴다. 그들은 곧장 두 번째로 가서, 명세가 결코 내리지 않은 모든 결정을 추측한다. 데모에는 괜찮고 제품에는 파멸적이다.

명세 주도 개발은 첫 번째 쓰기를 없애지 않는다. 첫 번째 쓰기를 인간의 판단이 필요한 유일한 쓰기로 만든다.

새로운 첫 번째 쓰기: 실제로 끝낼 수 있는 명세

여기서 바뀌는 것이 있다. 아무도 완전한 명세를 쓰지 않았던 이유는 쓰고 싶지 않았기 때문이 아니었다 — 그 작업이 정당화하기엔 너무 느렸기 때문이었다. 첫 스프린트와 접촉하는 순간 낡아 버리는 문서를 만들기 위해 몇 주의 탐색. 그래서 팀은 큰 줄기만 쓰고, 5,000개의 작은 결정은 나중에 해석 하나씩 발견되도록 남겼다.

명세를 초안 잡는 데 몇 달이 아니라 몇 시간이 걸릴 때, 산수는 뒤집힌다. 빠짐없이 하는 것을 감당할 수 있게 된다. 기능 요구사항, 시각 설계, 데이터 모델, 경계 사례 — 누군가 편집기를 열기 전에 포착되고, 무언가를 배웠을 때 수정할 만큼 저렴하다.

마지막 부분이 중요하다. 저렴하게 수정할 수 없는 명세는 현실이 도착하는 순간 거짓이 된다. 이것은 API-first로 만드는 것 뒤에 있는 것과 같은 직관이다. 누군가 화면을 쓰기 전에 하중을 받는 결정을 올바르게 내리고, 나머지는 따라오게 하라.

새로운 두 번째 쓰기: 번역이 아니라 코드 생성

명세가 완전해지면 두 번째 쓰기는 번역 문제이기를 그만둔다. 그것은 생성 문제가 된다. 표준 언어 — JavaScript, TypeScript, Python. 표준 프레임워크 — React, Next.js. 엔지니어가 이미 아는 형태의 진짜 코드가, 이미 모든 결정을 내려 둔 문서에서 도출된다.

차이는 개발자가 더 빨리 일한다는 것이 아니다. 애초에 엔지니어링이 아니었던 부분 — 다른 누군가가 이미 내린 결정을 기계적으로 다시 서술하는 일 — 을 그만둔다는 것이다.

아래로 흐르며 바뀌는 것

세 가지가 동시에 바뀐다.

  1. 첫 번째 쓰기가 끝까지 완성된다: 명세 작업이 몇 달이 아니라 몇 시간의 비용일 때, 팀은 작은 결정들을 리뷰에서 발견하는 대신 앞단에서 내리는 것을 감당할 수 있다.
  2. 아무도 공백을 채우지 않는다: 완전한 명세에서 생성된 코드는 프로덕트 팀이 무엇을 의도했는지 누군가 추측할 것을 요구하지 않는다. 그 추측이 언제나 결함의 출처였다.
  3. 재작업이 누적되기를 그만둔다: 의도와 구현이 정렬된 상태로 출발한다. 예전에 재작성이었던 것이 명세에 대한 한 번의 편집이 된다.

소프트웨어 쓰기의 미래: 자연어

누군가 소프트웨어를 배포해 온 이래로, 그 일은 그것을 두 번 쓰기를 요구했다. 한 번은 자연어로, 다시 한 번은 코드로. 그 두 번째 쓰기는 결코 가치 있는 부분이 아니었다. 다른 길이 없었기에 우리가 낸 통행료였다.

이것이 다음 세대의 AI 앱 빌더가 그 중심으로 조직된 수다. 코드보다 명료함이 먼저. 애플리케이션을 청사진으로 서술하고, 아키텍처를 올바르게 잡고, 코드가 그것에 맞춰 생성되게 하라. 정의 작업을 우회하는 지름길이 아니라 — 마침내 그것을 제대로 할 이유다.

이제 다른 길이 있다. 소프트웨어는 애초에 한 번만 쓰이면 되는 것이었다.

더 읽을 거리

이 실천에 대한 완전한 가이드: 명세 주도 개발. 프롬프트 우선 세대가 왜 이 단계를 건너뛰었는지는 바이브 코딩은 약속을 깼다에서, 무엇이 그것을 대체하는지는 바이브 코딩 다음은 무엇인가에서 다룬다.

자주 묻는 질문

명세 주도 개발이란 무엇인가? 명세 주도 개발은 코드가 생성되기 전에 요구사항과 제약과 성공 기준을 쓰고, 그 명세를 AI 에이전트가 맞춰 만드는 사실의 원천으로 대하는 것이다. 그것은 정의 단계를 완전히 건너뛰는 프롬프트 우선 워크플로에 대한 직접적인 응답으로 2025년에 등장했다.

명세 주도 개발은 전통적인 요구사항 문서를 쓰는 것과 어떻게 다른가? 문서는 같은 발상이다. 경제학이 다르다. 전통적인 명세는 팀이 큰 줄기만 쓰고 나머지를 코드 리뷰에서 발견할 만큼 비쌌다. 명세가 몇 달이 아니라 몇 시간이 걸리고 저렴하게 수정할 수 있게 되면, 그것은 끝낼 가치가 — 그리고 최신으로 유지할 가치가 — 생긴다.

어떤 도구가 명세 주도 개발을 지원하는가? GitHub Spec Kit, AWS Kiro, BMAD-METHOD, OpenSpec, Tessl이 이름이 붙은 구현이며, Cursor는 규칙 파일을 통해 더 경량 버전을 지원한다. 그들의 차이는 대체로 명세가 코드에 얼마나 강하게 결속되어 있는지에 있다 — 그것이 생성을 한 번 구동하는지, 코드와 함께 진화하는지, 아니면 당신이 편집하는 유일한 산출물인지.

명세 주도 개발은 팀을 느리게 하는가? 그것은 작업을 옮기고, 추가하지는 않는다. 명세에 포착된 결정은 어차피 누군가 내리는 결정이다 — 앞단에서 의도적으로, 아니면 나중에 개발자나 모델이 추측하며 암묵적으로. 두 번째 경로가 바로 재작업이 나오는 곳이다.

코드가 명세에서 생성되면 개발자는 어떻게 되는가? 다른 누군가의 결정을 기계적으로 다시 서술하는 일이 사라진다. 아키텍처, 트레이드오프, 정확성, 그리고 무엇을 만들지 않을지에 대한 판단은 사라지지 않는다. 그것들은 언제나 엔지니어가 필요했던 부분이다.

관련 게시물