Skip to content

좋은 스펙 작성하기 ​

빈 페이지에서 스펙을 작성하는 경우는 거의 없습니다. 변경사항을 평이한 언어로 설명하면, /opsx:propose가 요구사항과 시나리오 초안을 작성하고, 이후에 이를 다듬습니다. 이 페이지는 마지막 단계에 대한 것입니다 — '좋은' 스펙이란 어떤 모습인지, 그리고 AI를 어떻게 그 방향으로 유도하는지입니다.

변경사항 검토의 동반 문서입니다: 검토는 초안의 약점을 찾아내는 것이고, 작성은 강한 스펙이 무엇으로 이루어져 있는지 아는 것입니다.

스펙은 동작이지 코드가 아닙니다 ​

스펙은 시스템이 무엇을 하는지를 누구나 확인할 수 있는 용어로 설명합니다 — 어떻게 구현되었는지가 아닙니다. 요구사항(동작에 대한 진술)과 시나리오(이를 증명하는 구체적인 예시)로 구성됩니다.

markdown
### Requirement: Session Timeout
The system SHALL expire a session after 30 minutes of inactivity.

#### Scenario: Idle timeout
- GIVEN an authenticated session
- WHEN 30 minutes pass with no activity
- THEN the session is invalidated and the user must re-authenticate

어떻게 하는지 — 큐, 라이브러리, 테이블 스키마 — 는 design.md나 코드에 남겨두세요. 동작과 구현이 하나의 요구사항에 섞이면, 그 요구사항은 테스트 불가능해지고 코드가 변경되는 순간 바로 구식이 됩니다.

좋은 요구사항의 조건 ​

좋은 요구사항은 하나의 동작을, 다른 사람에게 테스트를 맡길 수 있을 정도로 평이하게 서술한 것입니다.

  • 한 진술, 하나의 SHALL/MUST. 요구사항에 세 개의 '그리고 또한' 절이 있다면, 실제로는 세 개의 요구사항입니다. 분리하세요.

  • 관찰 가능한. 코드 외부의 사람이 충족 여부를 판단할 수 있어야 합니다. "업로드가 10MB를 초과하면 시스템이 오류 배너를 표시해야 한다"는 관찰 가능합니다. "시스템이 대용량 업로드를 우아하게 처리해야 한다"는 관찰 불가능합니다.

  • 적절한 강도. OpenSpec는 RFC 2119 키워드를 사용하며, 각 키워드는 다른 의미를 가집니다:

    KeywordMeaning
    MUST / SHALLA hard requirement. Non-negotiable.
    SHOULDA strong recommendation, with room for a justified exception.
    MAYGenuinely optional.

    기본적으로 MUST/SHALL을 사용하세요. SHOULD는 '좋은 이유가 없다면'이라는 의미를 진정으로 의도할 때만 사용하세요.

요구사항의 검증 기준: 코드를 본 적 없는 테스터가 통과 여부를 판단할 수 있는가? 그렇지 않다면 더 날카롭게 다듬어야 합니다.

좋은 시나리오의 조건 ​

시나리오는 요구사항이 그 가치를 증명하는 곳입니다. 각 시나리오는 자동화 테스트로 전환될 수 있는 구체적인 GIVEN / WHEN / THEN입니다.

  • 요구사항을 실제로 검증한다. 요구사항을 다른 말로 반복하는 시나리오는 아무것도 검증하지 못합니다. 특정 상황과 특정 결과를 가진 시나리오로 만드세요.
  • 중요한 케이스를 다루세요, 해피 패스만으로는 부족합니다. 유효한 로그인은 쉽습니다. 빈 입력, 만료된 토큰, 두 번째 클릭, 잘못되는 것 — 버그는 바로 그 곳에 살고, 시나리오가 가장 가치를 발휘하는 곳이기도 합니다.
  • 제목에 케이스 이름을 명시하세요. "Scenario: Rejects an expired token"은 검토자가 한눈에 무엇을 다루는지 알 수 있게 하지만, "Scenario: Test 2"는 그렇지 않습니다.

유용한 습관: 승인하기 전에 내가 깨진 것을 보고 화가 날 한 가지 케이스는 무엇인가?라고 자문하고, 시나리오에 이를 명시했는지 확인하세요.

적절한 델타 유형 선택 ​

변경사항은 세 가지 섹션 유형으로 스펙에 대한 편집을 설명합니다. 올바른 유형을 사용하면 아카이브된 스펙의 정합성을 유지할 수 있습니다:

  • ## ADDED Requirements — 이전에 존재하지 않던 완전히 새로운 동작.
  • ## MODIFIED Requirements — 이미 존재하던 동작이 변경되는 경우. 새로운 버전 전체를 포함하세요. 변경된 내용에 대한 짧은 주석은 검토자에게 도움이 됩니다.
  • ## REMOVED Requirements — 제거되는 동작과 그 이유에 대한 한 줄 설명.

아카이브 시 ADDED는 메인 스펙에 추가되고, MODIFIED는 기존 버전을 대체하며, REMOVED는 제거됩니다. 기능의 마지막 요구사항을 제거하면 해당 기능이 은퇴합니다: 빈 스펙을 남겨두기보다는 아카이브가 openspec/specs/<capability>/spec.md를 삭제합니다. 파일 삭제를 수반하는 유일한 아카이브 단계이므로 명시적으로 요청해야 합니다 — 해당 파일에 이미 필요한 schema:와 함께 변경사항의 .openspec.yaml에 retire_capabilities: true를 추가하세요. 이것이 없으면 아카이브가 중단되고 그 사실이 알려집니다. 은퇴는 파일 전체를 삭제하므로, 제목, ## Purpose, 요구사항 블록 외에 다른 내용이 있는 경우에도 거부됩니다 — ## Notes 섹션, 요구사항 하단의 주석 등이 해당합니다. 중단 시 해당 줄이 명시됩니다. ## Purpose나 요구사항으로 이동하거나, 수동으로 스펙을 삭제하세요. 호출자의 체크아웃에 있는 스펙의 경우, 아카이브 출력에 커밋된 파일을 복원하는 git checkout 명령도 명시됩니다. 선택된 스토어에는 체크아웃 범위의 복구 안내가 대신 제공됩니다. 실제 변경사항을 ADDED로 표시하면 두 개의 경쟁하는 요구사항이 생기고, 새로운 동작을 MODIFIED로 서술하면 대체할 대상이 없습니다. 불확실하면 현재 스펙을 열어 해당 요구사항이 이미 있는지 확인하세요.

알아두면 좋은 한 가지 섹션이 더 있습니다. 델타가 아직 존재하지 않는 기능을 생성할 때, ## Purpose로 시작하세요 — 해당 기능의 목적에 대한 한두 문장입니다. 아카이브는 이를 생성하는 메인 스펙의 Purpose로 사용합니다. 건너뛰면 수동으로 채워야 할 TBD 플레이스홀더가 생깁니다. 기존 스펙에는 이미 Purpose가 있으므로 델타의 Purpose는 무시됩니다 — 변경하려면 openspec/specs/<capability-path>/spec.md를 직접 편집하세요. 여기서 <capability-path>는 specs/에 대한 상대 디렉터리로, 플랫 프로젝트에서는 user-auth, 도메인별로 조직된 프로젝트에서는 identity/user-auth와 같습니다.

변경사항의 규모를 적절히 맞추기 ​

가장 흔한 작성 실수는 서술이 나쁜 요구사항이 아닙니다 — 세 개의 변경사항을 한 번에 하려는 것입니다.

좋은 변경사항은 한 문장으로 말할 수 있는 하나의 의도를 가집니다. "다크 모드 토글 추가." "로그인 엔드포인트에 레이트 리밋 적용." "세션을 쿠키에서 마이그레이션." 변경사항을 설명하는 데 '그리고 또한'이 많이 필요하면, 분할해야 한다는 신호입니다.

변경사항이 너무 크다는 징후:

  • 제안서의 범위가 관련 없는 기능 목록처럼 읽힌다.
  • 검토에 오후 내내 걸리므로 아무도 하지 않는다.
  • 두 사람이 충돌 없이 작업할 수 없다.
  • 작업의 절반이 독립적으로 배포될 수 있다.

작은 변경사항은 검토하기 쉽고, 하나의 집중된 세션에서 구축하기 쉽고, 아카이브만 남아 있는 6개월 후에도 추론하기 쉽습니다. 여러 변경사항을 병렬로 실행할 수 있습니다 — 편집 및 반복과 워크플로를 참조하세요.

반대 경우도 있습니다: 한 줄 오타 수정에 세 개의 요구사항과 설계 문서가 필요하지 않습니다. 의식의 규모를 위험도에 맞추세요.

AI를 좋은 초안으로 유도하는 방법 ​

/opsx:propose가 첫 번째 초안을 작성하므로, 받아들이는 결과물의 품질은 입력한 품질에 따라 달라집니다. 요구사항을 수동으로 작성할 필요는 없습니다 — AI를 잘 조준해야 합니다:

  • 의도와 경계를 명시하세요. "첫 로드 시 OS 설정을 따르는 다크 모드 토글 추가 — 기존 테마 API는 건드리지 마세요." 범위 밖인 절반도 범위 안인 절반만큼 중요합니다.
  • 중요한 케이스를 명시하세요. "이미 수동으로 테마를 선택한 사용자를 위한 시나리오가 있는지 확인하세요." AI는 지시한 것을 커버합니다.
  • 그리고 편집하세요. 단순 마크다운입니다. 모호한 SHALL을 구체화하고, 아무것도 검증하지 않는 시나리오를 삭제하고, 놓친 케이스를 추가하세요 — 또는 AI에게 요청하세요: "타임아웃 요구사항이 모호하니 30분으로 고정하세요."

초안 작성, 다듬기, 반복. 몇 라운드면 신뢰할 수 있는 스펙이 만들어집니다 — 그것이 전부입니다.

빠른 체크리스트 ​

다음 단계 ​