왜 요구사항 명세서가 필요한가
이번 챕터는 3부로 별도 할당했습니다. 그만큼 중요한 챕터라고 생각했기 때문입니다. 다만 이 챕터는 초급자가 바로 이해하기 어려울 수 있고, 이해할 필요가 없는 내용도 있습니다. 따라서 천천히 읽어보시고, 필요할 것 같은 부분만 골라서 읽어보시기 바랍니다.
GitHub에 올리는 파일 중 .gitignore라는 파일이 있습니다. 이 파일은 내 컴퓨터에 있는 파일 중 업로드 하지 말아야 할 파일을 명시합니다. 그런데 '우리가 gitignore하는 것이 Code가 될 수도 있다.'라는 얘기가 종종 들려옵니다. 이제는 Code가 자산이 아니라 무엇을 개발할지 명확하게 정의하고 지시하는 프롬프트가 자산이라는 것이죠.
모델은 앞으로도 계속 발전할 것입니다. 지금 성능의 2 ~ 3배가 된다고 가정해봅시다. 그 결과로 원하는 결과물을 5분, 10분만에 만들 수 있다고 생각해봅시다. 무엇을 만들지, 어떻게 확장해갈지, 목표 달성 수치는 무엇인지 정의하는 것이 더 중요한 시대가 될 것입니다.
기술도 마찬가지입니다. 리팩토링도 시간이 얼마 걸리지 않게 되는 시대가 열릴 수 있습니다. 구조적 한계를 극복하기 위해 난이도 높은 유지보수를 채택하는 것이 아니라 처음부터 개발하는 시대가 열릴 수 있습니다. 이런 시대가 온다면 코드의 자산가치는 이전만큼 크지 않을 것입니다.
혹시 그런 시대가 온다면 이번 챕터는 모든 챕터를 통틀어 가장 중요한 챕터라 할 수 있습니다. 따라서 좀 더 상세히 챕터를 면밀히 검토해보시기 바랍니다. 과할 정도로 많은 문서를 살펴볼 예정입니다. 전통적인 명세서부터 바이브 코딩을 위한 명세서 템플릿까지 살펴볼 예정입니다.
하나의 명세서를 정답처럼 사용할 수는 없습니다. 규모, 상황, 인력, 자본 등이 다르기 때문이죠. 천천히 읽어보시고, 자신에게 필요할 것 같은 명세서 템플릿을 조합해 사용하세요.
1. 전통적인 개발에서의 요구사항 명세서
과거 소프트웨어 개발에서 요구사항 명세서는 개발자와 기획자, 클라이언트 간의 소통을 위한 필수 문서였습니다. 복잡한 시스템을 구축하기 전에 무엇을 만들어야 하는지 명확히 정의하고, 개발 과정에서 발생할 수 있는 오해를 방지하는 것이 주목적이었습니다. 폭포수 모델이 주류였던 시대에는 요구사항 명세서가 프로젝트의 성패를 좌우하는 핵심 문서였습니다. 한번 작성된 명세서는 개발이 완료될 때까지 변경되지 않는 것이 이상적이라고 여겨졌고, 이를 위해 초기 단계에서 가능한 모든 세부사항을 다루려고 했습니다.
하지만 이러한 전통적인 접근법은 여러 한계를 드러냈습니다. 가장 큰 문제는 과도한 문서화였습니다. 실제 개발보다 문서 작성에 더 많은 시간을 소요하는 경우가 빈번했고, 개발자들은 코딩 대신 문서 작성과 검토에 매몰되었습니다. 또한 한번 작성된 명세서는 변경하기 어려운 경직성을 보였습니다. 시장의 변화나 사용자의 새로운 요구사항이 발생해도 이미 확정된 명세서를 수정하려면 복잡한 승인 절차와 비용이 따랐습니다. 이런 환경에서는 실질적인 가치 창출보다는 절차적 완성도에 집중하게 되었고, 정작 사용자가 원하는 것과는 거리가 먼 시스템이 만들어지는 경우도 많았습니다.
그럼에도 불구하고 요구사항 명세서가 완전히 사라진 것은 아닙니다. 복잡한 시스템일수록, 많은 이해관계자가 관여할수록 명확한 요구사항 정의의 필요성은 여전히 존재했기 때문입니다. 다만 그 형태와 활용 방식이 변화해야 한다는 공감대가 형성되었습니다.
폭포수 모델은 소프트웨어를 개발하기 위한 프로세스 중 하나로 개발의 흐름이 마치 폭포가 떨어지는 것처럼 순차적으로 일어난다고 하여 붙여진 이름입니다. 요구사항 분석, 설계, 구현, 시험, 통합, 유지보수 단계로 이뤄져 있습니다.
2. 바이브 코딩을 위한 요구사항 명세서
바이브 코딩에 사용할 요구사항 명세서는 전통적인 명세서와 다릅니다. Context를 제공해야합니다. 왜 개발해야 하는지 전통적인 요구사항 명세서에는 명시하지 않을 수 있지만 이러한 맥락이 AI와 협업에서 주어지지 않으면 원치 않는 결과물이 나올 수 있습니다. 이처럼 바이브 코딩을 위한 요구사항 명세서는 아래와 같은 사항들을 포함해야 합니다. 아래 사항들은 포함되어야 하는 모든 사항이 아니라 전통적인 요구사항 명세에서 달라진 지점이라는 점을 유념해주세요.
- AI 이해를 위한 맥락 제공과 구조화: 바이브 코딩을 위한 요구사항 명세는 단지 요구사항을 나열하는 문서가 아니라 파트너에게 업무를 지시하기 위한 업무지시서와도 같습니다. 따라서 AI가 이해하고 실행할 수 있는 형태로 요구사항의 맥락과 프로젝트를 구조화하는 것이 중요해졌습니다.
- 반복적 개선: 바이브 코딩에서는 요구사항 명세서가 고정된 문서가 아닙니다. Claude와의 대화 과정에서 새로운 아이디어가 나오거나 기존 요구사항의 한계가 발견되면 대화와 함께 명세서를 업데이트할 수 있습니다. 이는 전통적인 명세서의 정적인 특성과는 완전히 다른 접근법입니다.
- 실행 가능한 명세: 가장 큰 변화는 추상적인 설명이 아닌, 바로 코드로 변환 가능한 구체적인 지시사항을 작성할수록 원하는 결과물에 근접한다는 것입니다. 추상화된 설명일수록 구체적인 것을 AI가 채워넣게 됩니다. 그러면 원하는 결과물이 나오지 않을 수 있습니다. "사용자 친화적인 인터페이스"라는 모호한 표현 대신 "버튼 크기는 최소 44px × 44px, 색상 대비는 WCAG AA 기준 준수, 로딩 상태는 스켈레톤 UI로 표시"와 같은 구체적인 요구사항을 명시합니다. 이렇게 작성된 요구사항은 AI가 이해하고 구현할 수 있는 실행 가능한 명세가 됩니다. 우리가 앞서 디자인 요구사항들을 정리했던 것을 떠올리시면 됩니다.
3. 바이브 코딩에서 요구사항 명세서의 새로운 가치
3.1 AI 컨텍스트 제공
Claude Code는 프로젝트의 전체 맥락을 이해해야 효과적으로 작동합니다. 단순히 "로그인 기능을 만들어줘"라고 요청하는 것보다 "B2C 이커머스 플랫폼의 사용자 인증 시스템으로, JWT 토큰 기반이며 소셜 로그인도 지원해야 하고, 보안은 OWASP 기준을 준수해야 합니다"라고 구체적인 컨텍스트를 제공할 때 Claude는 더 정확하고 적절한 코드를 생성할 수 있습니다. 요구사항 명세서는 이러한 컨텍스트를 체계적으로 정리하고 제공하는 역할을 합니다.
예를 들어, SW개발을 전혀 모르시는 분의 랜딩페이지나 스타트업의 MVP를 개발하는 상황과 대기업의 레거시 시스템을 개선하는 상황은 완전히 다른 접근이 필요합니다. SW 개발을 모르시는 분에게는 기술적 설명이 상당히 자세히 나와야 하며 유지보수가 매우 쉬워야 하고, MVP는 빠른 시장 검증을 위한 유연성이 중요하고, 대기업의 시스템 개선은 안정성과 호환성이 우선입니다. 이러한 맥락 정보가 명확히 전달되어야 Claude가 적절한 기술 스택과 아키텍처를 제안할 수 있습니다.
3.2 복잡성 관리
대규모 프로젝트에서도 AI가 일관성 있게 작업할 수 있도록 복잡한 요구사항을 관리 가능한 단위로 분해합니다. 예를 들어, "온라인 쇼핑몰을 만들어줘"라는 거대한 요청을 하게 되면 의도치 않은 기술을 사용한다던가, 중간에 요청하지 않은 기능이 들어가거나 필요한 기능이 구현이 되어 있지 않은 경우가 생기게 됩니다. 이를 "요구사항 명세 간섭"이라는 이름으로 불러보겠습니다. 이 요구사항 명세 간섭이 일어나는 구간은 어디일까요? 우리가 정확하게 정의하지 않은 모든 구간에 AI는 간섭을 일으킵니다.
예를 들어, 요구사항에 기술 스택이 정의되어 있지 않으면 자신이 학습한 데이터 중 가장 합당한 기술을 선택하게 되죠. 대부분은 이 합당한 기술 선택이 적절합니다. 다만, 충분한 Context가 주어진 것이 아니기 때문에 개발자 입장에서 합당치 않은 기술 선택을 할 수도 있습니다. 예를 들어, 개발을 이제 막 시작한 분에게 React라는 기술은 상당히 어려운 기술이에요. TypeScript도 마찬가지죠. 간단한 랜딩 페이지 또는 2 ~ 3 페이지의 페이지도 순수한 HTML, CSS, JavaScript를 사용하는 편이 좋습니다.
다른 예를 들어보겠습니다. "온라인 쇼핑몰을 만들어줘"라는 프롬프트로 온라인 쇼핑몰을 개발할 때 카테고리가 4개로 나뉘고 각 카테고리별로 페이지도 나뉘었으면 좋겠다고 생각을 했습니다. 문서화 하지 않은거죠. 그러면 AI는 가장 합당하다 생각하는 쇼핑몰의 형태로 개발할 수 밖에 없죠. 가령 카테고리는 12개, 페이지도 15개 페이지를 만들었다 생각해봅시다. 제가 생각한 결과물과 다른 결과물이 나온거죠. 우리가 요구사항 명세에 어떤 페이지를 어떻게 나누고, 어떤 구성으로 되어 있는지를 상세하게 작성하지 않았기 때문에 요구사항 명세에 간섭이 일어나게 된 것이죠.
이렇게 AI의 요구사항 명세 간섭이 일어나지 않기 위해서는, 또는 간섭이 일어나도 우리가 원하는 방향으로 이끌기 위해서는 사용자 관리, 상품 관리, 주문 처리, 결제 시스템, 페이지 구성 등으로 기능과 구성을 세분화하고, 각각의 우선순위와 의존성을 명확히 정의해야 합니다. 이렇게 구조화된 요구사항은 Claude가 전체 시스템의 일관성을 유지하면서도 단계적으로 개발을 진행할 수 있게 도와줍니다.
특히 중요한 것은 전체 페이지 구성과 맥락, 각 모듈 간의 인터페이스와 데이터 플로우를 명확히 정의하는 것입니다. 만약 구성과 맥락, 인터페이스와 데이터 흐름이 정확하지 않다면, 같은 DB를 여러개 만든다던지 하는 등의 추후 유지보수의 문제가 발생할 수도 있습니다. 이렇게 향후 통합 과정에서 발생할 수 있는 문제들을 사전에 방지할 수 있는 요구사항 명세를 작성하는 것도 중요하죠.
3.3 품질 보증
명확한 요구사항을 통해 AI가 생성한 코드의 품질을 검증하고 개선할 수 있는 기준점을 제공합니다. "성능이 좋아야 한다"는 추상적인 요구사항 대신 "API 응답 시간은 200ms 이내, 동시 사용자 1000명 지원, 페이지 로딩 시간 3초 이내"와 같은 구체적인 기준을 명시하면, Claude가 생성한 코드가 이 기준을 만족하는지 객관적으로 평가할 수 있습니다. 또한 이러한 기준은 지속적인 개선과 최적화의 방향을 제시하기도 합니다.
이는 단순히 기능적 요구사항뿐만 아니라 비기능적 요구사항까지 포함합니다. 보안, 성능, 접근성, 확장성 등의 품질 속성들을 구체적인 지표와 함께 명시함으로써 Claude가 이를 고려한 설계와 구현을 할 수 있도록 가이드하는 것입니다.