개념
이 가이드에서는 OpenSpec의 핵심 개념과 그것들이 어떻게 조화를 이루는지 설명합니다. 실용적인 사용 방법은 시작하기 및 워크플로우를 참조하세요.
철학
OpenSpec은 네 가지 원칙을 기반으로 구축되었습니다:
fluid not rigid — 단계적 게이트 없음, 의미 있는 작업 수행
iterative not waterfall — 구축하면서 배우고, 진행하면서 개선
easy not complex — 가벼운 설정, 최소한의 절차
brownfield-first — 신규 개발뿐만 아니라 기존 코드베이스와 작동이러한 원칙들이 중요한 이유
유연하지만 경직되지 않습니다. 기존의 명세 시스템은 여러분을 특정 단계에 고정합니다: 먼저 계획하고, 그 다음 구현하고, 그러면 끝입니다. OpenSpec은 더 유연합니다 — 작업에 의미 있는 순서대로 아티팩트를 생성할 수 있습니다.
폭포수 모델이 아닌 반복적 접근. 요구사항은 변합니다. 이해의 깊이는 커집니다. 처음에는 좋은 접근 방식처럼 보였던 것이 코드베이스를 본 후에는 유지되지 않을 수 있습니다. OpenSpec은 이 현실을 수용합니다.
복잡하지 않고 쉽습니다. 일부 명세 프레임워크는 광범위한 설정, 경직된 형식 또는 무거운 프로세스를 필요로 합니다. OpenSpec은 여러분의 방해가 되지 않습니다. 몇 초 안에 초기화하고, 즉시 작업을 시작하며, 필요할 때만 사용자 정의할 수 있습니다.
기존 시스템 우선 접근. 대부분의 소프트웨어 작업은 처음부터 만드는 것이 아닙니다 — 기존 시스템을 수정하는 것입니다. OpenSpec의 델타 기반 접근 방식은 새로운 시스템을 설명하는 것뿐만 아니라 기존 동작의 변경사항을 쉽게 명세할 수 있게 합니다.
전체 구조
OpenSpec는 작업을 두 가지 주요 영역으로 구성합니다:
┌────────────────────────────────────────────────────────────────────┐
│ openspec/ │
│ │
│ ┌─────────────────────┐ ┌───────────────────────────────┐ │
│ │ specs/ │ │ changes/ │ │
│ │ │ │ │ │
│ │ 원본 소스 │◄─────│ 제안된 수정 사항 │ │
│ │ 시스템의 현재 │ merge│ 각 변경 = 하나의 폴더 │ │
│ │ 동작 방식 │ │ 아티팩트 + 델타 포함 │ │
│ │ │ │ │ │
│ └─────────────────────┘ └───────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────┘Specs는 원본 소스입니다 — 시스템의 현재 동작 방식을 설명합니다.
Changes는 제안된 수정 사항입니다 — 병합할 준비가 될 때까지 별도의 폴더에 보관됩니다.
이 분리가 핵심입니다. 충돌 없이 여러 변경 사항을 병렬로 작업할 수 있습니다. 메인 specs에 영향을 미치기 전에 변경 사항을 검토할 수 있습니다. 그리고 변경 사항을 아카이브하면 델타가 원본 소스에 깔끔하게 병합됩니다.
조정 워크스페이스
워크스페이스 지원은 베타 단계입니다. 아래의 로컬 뷰 모델이 현재 방향이지만, 외부 자동화, 통합, 장기 워크플로우는 명령 동작, 상태 파일, JSON 출력을 여전히 진화 중인 것으로 간주해야 합니다.
아래 명령어는 연결된 리포 또는 폴더에 대한 로컬 뷰를 열기 위한 첫 번째 설정 흐름을 제공합니다.
리포 로컬 OpenSpec 프로젝트는 하나의 리포가 계획, 구현, 아카이브 흐름을 소유할 때 적절한 기본값입니다. 일부 작업은 여러 리포 또는 폴더에 걸쳐 있습니다. 이러한 경우를 위해 OpenSpec 조정 워크스페이스는 연결된 경로, 오프너 상태, 에이전트 설정을 함께 유지하는 머신 로컬 뷰입니다.
워크스페이스의 개념 모델은 다음과 같습니다:
text
workspace = 컨텍스트 스토어, 이니셔티브, 리포, 폴더에 대한 프라이빗 로컬 뷰
context store = 영구 공유 컨텍스트 컨테이너
initiative = 컨텍스트 스토어 내의 영구 조정 컨텍스트
link = 워크스페이스가 로컬에서 해석할 수 있는 리포 또는 폴더의 안정적인 이름
change = 계획된 하나의 작업 단위; 구현은 소유 리포에 속함워크스페이스는 리포 로컬 프로젝트와 다른 구조를 가집니다:
text
getGlobalDataDir()/workspaces/<workspace-name>/
├── workspace.yaml # 프라이빗 로컬 뷰 레코드
├── AGENTS.md # 생성된 런타임 가이드
└── <workspace-name>.code-workspace # 생성된 에디터 워크스페이스 파일리포 로컬 OpenSpec 상태는 기존 구조를 유지합니다:
text
repo-root/
└── openspec/
├── specs/
└── changes/이 구분이 중요합니다. 워크스페이스 폴더는 연결된 리포 또는 폴더를 열고 검사하기 위한 로컬 조정 표면입니다. 각 리포의 openspec/ 디렉터리는 리포 소유 specs, 리포 로컬 변경 사항, 구현 계획의 본거지로 남습니다. 사용자는 워크스페이스 폴더 내에서 리포 로컬 openspec init을 실행할 필요가 없습니다.
안정적인 링크 이름은 워크스페이스가 리포 및 폴더를 참조하는 방식입니다. 프라이빗 워크스페이스 레코드는 api, web, checkout과 같은 이름을 유지하고 이를 이 런타임의 로컬 경로에 매핑합니다.
yaml
# workspace.yaml
version: 1
name: platform
context: null
links:
api: /repos/api
web: /repos/web워크스페이스가 이니셔티브를 열면 context는 선택된 컨텍스트 스토어 바인딩과 이니셔티브 ID를 기록합니다. 레지스트리로 선택된 스토어는 ID로 이식성을 유지합니다; 경로로 선택된 스토어는 workspace.yaml이 프라이빗 로컬 상태이므로 의도적으로 런타임 로컬 경로를 보존합니다.
yaml
context:
kind: initiative
store:
id: platform
selector:
kind: registry
id: platform
initiative:
id: billing-launch연결된 경로는 전체 리포, 대형 모노레포 내부의 폴더, 또는 기타 기존 폴더일 수 있습니다. 워크스페이스 계획에 참여하기 전에 리포 로컬 openspec/ 상태가 필요하지 않습니다. 이후 구현, 검증, 아카이브 워크플로우에는 더 많은 리포 준비가 필요할 수 있지만, 계획 가시성은 링크부터 시작됩니다.
text
multi-repo:
api -> /repos/api
web -> /repos/web
large monorepo:
billing -> /repos/platform/services/billing
checkout -> /repos/platform/apps/checkout관리되는 워크스페이스는 표준 OpenSpec 데이터 디렉터리 아래에 있습니다:
text
getGlobalDataDir()/workspaces이는 XDG_DATA_HOME이 설정된 경우 $XDG_DATA_HOME/openspec/workspaces, Unix 스타일 폴백 시 ~/.local/share/openspec/workspaces, 네이티브 Windows 폴백 시 %LOCALAPPDATA%\openspec\workspaces를 의미합니다. 네이티브 Windows 셸, PowerShell, WSL2 각각은 OpenSpec을 실행하는 런타임의 경로 문자열을 유지합니다. 이 기반은 D:\repo, /mnt/d/repo, UNC WSL 경로 간 변환을 지원하지 않습니다.
OpenSpec은 이전 베타 워크스페이스 루트를 호환성 입력으로 계속 읽을 수 있지만, 관리되는 워크스페이스는 이제 위의 루트 workspace.yaml 레코드를 사용합니다. 워크스페이스 폴더는 자체 프라이빗 로컬 뷰에 대한 권위를 유지합니다.
워크스페이스 가시성은 변경 커밋이 아닙니다. OpenSpec이 관련 리포 또는 폴더를 인식해야 할 때 워크스페이스를 설정하세요; 기능 수정, 수정, 프로젝트 또는 기타 작업을 계획할 준비가 되면 나중에 변경 사항을 생성하세요.
유용한 명령어:
bash
# 안내 설정
openspec workspace setup
# 자동화 친화적 설정
openspec workspace setup --no-interactive --name platform --link /repos/api --link web=/repos/web
openspec workspace setup --no-interactive --name platform --link /repos/api --opener codex-cli
# 로컬 레지스트리에서 알려진 워크스페이스 확인
openspec workspace list
openspec workspace ls
# 선택된 워크스페이스의 링크 추가 또는 수정
openspec workspace link /repos/api
openspec workspace link api-service /repos/api
openspec workspace relink api-service /new/path/to/api
# 이 머신이 해석할 수 있는 것 확인
openspec workspace doctor
openspec workspace doctor --workspace platform
# 워크스페이스 로컬 가이드 및 에이전트 스킬 새로고침
openspec workspace update
openspec workspace update --workspace platform --tools codex,claude
# 연결된 작업 세트 열기
openspec workspace open
openspec workspace open platform --agent github-copilot
openspec workspace open --editor
# 이니셔티브를 로컬 워크스페이스 뷰로 열기
openspec workspace open --initiative billing-launch --store platform
openspec workspace open --initiative billing-launch --store-path /repos/platform-contextworkspace setup은 항상 표준 워크스페이스 위치에 워크스페이스를 생성하고, 로컬 레지스트리에 기록하며, 워크스페이스 위치를 표시하고, 최소 하나의 연결된 리포 또는 폴더를 요구합니다. 대화형 설정은 선호하는 오프너를 묻고 선택된 에이전트에 대해 OpenSpec 스킬을 설치할 수 있습니다. 비대화형 설정은 --opener codex-cli, --opener claude, --opener github-copilot 또는 --opener editor가 제공될 때만 하나를 저장합니다.
워크스페이스 스킬은 워크스페이스 루트에만 설치됩니다. 활성 글로벌 프로필이 생성되는 워크플로우 스킬을 선택합니다; --tools는 스킬을 받을 에이전트를 선택합니다. 워크스페이스 설정 및 업데이트는 글로벌 전달에 명령어가 포함되어 있더라도 슬래시 명령 파일을 생성하지 않습니다. openspec workspace update를 실행하여 워크스페이스 로컬 가이드를 새로고침하고, 연결된 리포 또는 폴더를 편집하지 않고 관리되는 워크스페이스 로컬 스킬 디렉터리를 추가, 새로고침 또는 제거하세요.
OpenSpec은 또한 루트 워크스페이스 열기 파일도 유지합니다: AGENTS.md의 OpenSpec 관리 가이드 블록과 VS Code 및 GitHub Copilot-in-VS-Code 열기를 위한 머신 로컬 <workspace-name>.code-workspace 파일입니다. 관리되는 워크스페이스는 리포가 아니므로, OpenSpec은 기본 워크스페이스 .gitignore 또는 기본 워크스페이스 수준 changes/ 디렉터리를 생성하지 않습니다.
유지되는 VS Code 워크스페이스는 유효한 연결된 리포 또는 폴더를 먼저 나열하고, 그 다음 연결 시 이니셔티브 컨텍스트를, 그 다음 OpenSpec 워크스페이스 파일을 나열합니다. VS Code는 이러한 항목들을 멀티 루트 워크스페이스로 표시합니다.
workspace open은 해당 세션에 --agent <tool> 또는 --editor가 전달되지 않는 한 저장된 선호 오프너로 연결된 작업 세트를 엽니다. 두 오프너 오버라이드를 모두 전달하면 오류입니다. 루트 워크스페이스 열기는 연결된 리포와 폴더를 탐색 및 컨텍스트에 가시적으로 만듭니다; 구현은 사용자가 명시적으로 구현 작업을 요청한 후에 시작됩니다.
workspace link와 workspace relink는 기존 폴더만 기록합니다; 연결된 리포 또는 폴더를 생성, 복사, 이동, 초기화 또는 편집하지 않습니다. 성공적인 링크 또는 리링크 후, OpenSpec은 관리되는 가이드 및 VS Code 워크스페이스 파일을 새로고침합니다.
하나의 워크스페이스가 필요한 워크스페이스 명령어는 --workspace <name>을 사용하여 어디에서든 실행할 수 있습니다. 워크스페이스 폴더 또는 하위 디렉터리 내에서 실행하면 OpenSpec은 해당 현재 워크스페이스를 사용합니다. 여러 알려진 워크스페이스를 사용할 수 있고 --workspace <name>을 전달하지 않으면, 대화형 명령어는 선택기를 표시합니다; --json 및 --no-interactive는 프롬프트 대신 구조화된 상태 오류로 실패합니다.
직접 워크스페이스 명령어는 스크립트용 JSON 출력을 지원합니다. JSON 응답은 기본 데이터를 workspace, workspaces 또는 link 객체에 유지하고 경고 또는 오류를 status 배열에 보고합니다. 정상 객체는 status: []를 사용합니다.
스펙
스페ック은 구조화된 요구사항과 시나리오를 사용하여 시스템의 동작을 설명합니다.
구조
openspec/specs/
├── auth/
│ └── spec.md # 인증 동작
├── payments/
│ └── spec.md # 결제 처리
├── notifications/
│ └── spec.md # 알림 시스템
└── ui/
└── spec.md # UI 동작 및 테마스페ック을 도메인별로 정리하세요 — 시스템에 의미 있는 논리적 그룹화입니다. 일반적인 패턴:
- 기능 영역별:
auth/,payments/,search/ - 구성요소별:
api/,frontend/,workers/ - 제한된 컨텍스트별:
ordering/,fulfillment/,inventory/
스펙 형식
스페ック은 요구사항을 포함하며, 각 요구사항에는 시나리오가 있습니다:
markdown
# 인증 명세서
## 목적
애플리케이션을 위한 인증 및 세션 관리.요구 사항
요구 사항: 사용자 인증
시스템은 로그인 성공 시 JWT 토큰을 발행해야 합니다.
시나리오: 유효한 자격 증명
- GIVEN 유효한 자격 증명을 가진 사용자가 있을 때
- WHEN 사용자가 로그인 양식을 제출하면
- THEN JWT 토큰이 반환됩니다
- AND 사용자가 대시보드로 리디렉션됩니다
시나리오: 유효하지 않은 자격 증명
- GIVEN 유효하지 않은 자격 증명이 있을 때
- WHEN 사용자가 로그인 양식을 제출하면
- THEN 오류 메시지가 표시됩니다
- AND 토큰은 발행되지 않습니다
요구 사항: 세션 만료
시스템은 30분 동안 활동이 없으면 세션을 만료시켜야 합니다.
시나리오: 유휴 타임아웃
- GIVEN 인증된 세션이 있을 때
- WHEN 활동 없이 30분이 경과하면
- THEN 세션이 무효화됩니다
- AND 사용자는 재인증해야 합니다
**핵심 요소:**
| 요소 | 목적 |
|---------|---------|
| `## Purpose` | 이 명세서의 도메인에 대한 상위 수준 설명 |
| `### Requirement:` | 시스템이 가져야 하는 특정 동작 |
| `#### Scenario:` | 요구 사항이 실제로 적용되는 구체적인 예시 |
| SHALL/MUST/SHOULD | 요구 사항 강도를 나타내는 RFC 2119 키워드 |
### 명세서를 이런 구조로 작성하는 이유
**요구 사항은 "무엇을"** — 구현을 지정하지 않고 시스템이 무엇을 해야 하는지를 명시합니다.
**시나리오는 "언제"** — 검증할 수 있는 구체적인 예시를 제공합니다. 좋은 시나리오는:
- 테스트 가능합니다 (자동화된 테스트를 작성할 수 있음)
- 해피 패스와 엣지 케이스를 모두 다룹니다
- Given/When/Then 또는 유사한 구조화된 형식을 사용합니다
**RFC 2119 키워드** (SHALL, MUST, SHOULD, MAY)는 의도를 전달합니다:
- **MUST/SHALL** — 절대적 요구 사항
- **SHOULD** — 권장되지만 예외가 있음
- **MAY** — 선택 사항
### 명세서가 무엇이고 무엇이 아닌가
명세서는 **행위 계약**이지, 구현 계획이 아닙니다.
좋은 명세서 내용:
- 사용자 또는 다운스트림 시스템이 의존하는 관찰 가능한 동작
- 입력, 출력 및 오류 조건
- 외부 제약 조건 (보안, 개인정보 보호, 신뢰성, 호환성)
- 테스트하거나 명시적으로 검증할 수 있는 시나리오
명세서에서 피해야 할 것:
- 내부 클래스/함수 이름
- 라이브러리 또는 프레임워크 선택
- 단계별 구현 세부 정보
- 상세 실행 계획 (해당 내용은 `design.md` 또는 `tasks.md`에 속함)
빠른 테스트:
- 구현이 변경되어도 외부적으로 보이는 동작이 바뀌지 않는다면, 그것은 아마 명세서에 속하지 않을 것입니다.
### 가볍게 유지: 점진적 엄격성
OpenSpec은 관료주의를 피하려고 합니다. 변경 사항을 검증 가능하게 만들 수 있는 가장 가벼운 수준을 사용하세요.
**라이트 명세서 (기본):**
- 짧은 동작 중심 요구 사항
- 명확한 범위와 비목표
- 구체적인 수용 검사 항목 몇 가지
**전체 명세서 (더 높은 위험도의 경우):**
- 크로스 팀 또는 크로스 리포 변경
- API/계약 변경, 마이그레이션, 보안/개인정보 보호 우려 사항
- 모호성이 비용이 많이 드는 재작업을 초래할 수 있는 변경
대부분의 변경은 라이트 모드를 유지해야 합니다.
### 인간 + 에이전트 협업
많은 팀에서, 인간이 탐색하고 에이전트가 아티팩트를 초안 작성합니다. 의도된 루프는:
1. 인간이 의도, 맥락 및 제약 조건을 제공합니다.
2. 에이전트가 이를 동작 중심 요구 사항과 시나리오로 변환합니다.
3. 에이전트는 구현 세부 정보를 `design.md`와 `tasks.md`에 유지하고, `spec.md`에는 넣지 않습니다.
4. 검증이 구현 전에 구조와 명확성을 확인합니다.
이를 통해 명세서는 인간에게는 읽기 쉽고 에이전트에게는 일관성을 유지합니다.
## 변경 사항
변경 사항은 이해하고 구현하는 데 필요한 모든 것이 포함된 폴더로 제안된 시스템 수정 사항입니다.
### 변경 구조openspec/changes/add-dark-mode/ ├── proposal.md # 이유와 내용 ├── design.md # 방법 (기술적 접근) ├── tasks.md # 구현 체크리스트 ├── .openspec.yaml # 변경 메타데이터 (선택 사항) └── specs/ # 델타 명세서 └── ui/ └── spec.md # ui/spec.md에서 변경되는 내용
각 변경은 자체 포함됩니다. 다음을 포함합니다:
- **아티팩트** — 의도, 설계 및 작업을 캡처하는 문서
- **델타 명세서** — 추가, 수정 또는 제거되는 내용에 대한 명세서
- **메타데이터** — 이 특정 변경에 대한 선택적 구성
### 변경 사항이 폴더인 이유
변경 사항을 폴더로 패키징하면 여러 가지 이점이 있습니다:
1. **모든 것이 함께 있습니다.** 제안서, 설계, 작업 및 명세서가 한 곳에 있습니다. 다른 위치를 찾아다닐 필요가 없습니다.
2. **병렬 작업.** 여러 변경 사항이 충돌 없이 동시에 존재할 수 있습니다. `add-dark-mode` 작업을 진행하는 동안 `fix-auth-bug`도 진행할 수 있습니다.
3. **깔끔한 기록.** 아카이브될 때, 변경 사항은 전체 맥락과 함께 `changes-archive/`로 이동합니다. 무엇이 바뀌었는지뿐만 아니라 왜 바뀌었는지 이해할 수 있습니다.
4. **리뷰 친화적.** 변경 폴더는 리뷰하기 쉽습니다 — 열고, 제안서를 읽고, 설계를 확인하고, 명세서 델타를 확인하세요.
## 아티팩트
아티팩트는 작업을 안내하는 변경 내의 문서입니다.
### 아티팩트 흐름proposal ──────► specs ──────► design ──────► tasks ──────► implement │ │ │ │ 이유 무엇을 어떻게 수행할
- 범위 변경하는가 접근 단계
아티팩트는 서로 위에 구축됩니다. 각 아티팩트는 다음에 대한 맥락을 제공합니다.
### 아티팩트 유형
#### 제안서 (`proposal.md`)
제안서는 높은 수준에서 **의도**, **범위** 및 **접근 방식**을 캡처합니다.
```markdown
# 제안서: 다크 모드 추가
## 의도
사용자들은 야간 사용 시 눈의 피로를 줄이고 시스템 환경설정과 일치시키기 위해 다크 모드 옵션을 요청했습니다.
## 범위
범위 내:
- 설정의 테마 토글
- 시스템 환경설정 감지
- localStorage에 환경설정 유지
범위 외:
- 맞춤 색상 테마 (향후 작업)
- 페이지별 테마 오버라이드
## 접근 방식
상태 관리를 위해 React 컨텍스트와 함께 테마 지정을 위해 CSS 커스텀 속성을 사용합니다. 첫 로드 시 시스템 환경설정을 감지하고 수동 오버라이드를 허용합니다.제안서를 업데이트해야 하는 경우:
- 범위 변경 (축소 또는 확장)
- 의도가 명확해짐 (문제에 대한 더 나은 이해)
- 접근 방식이 근본적으로 전환될 때
명세서 (specs/의 델타 명세서)
델타 명세서는 현재 명세서에 대해 변경되는 내용을 설명합니다. 아래 델타 명세서를 참조하세요.
설계 (design.md)
설계는 기술적 접근 방식과 아키텍처 결정을 캡처합니다.
markdown
# 설계: 다크 모드 추가
## 기술적 접근 방식
프롭 드릴링을 피하기 위해 React 컨텍스트를 통해 테마 상태를 관리합니다. CSS 커스텀 속성을 사용하면 클래스 토글 없이 런타임 전환이 가능합니다.
## 아키텍처 결정
### 결정: Redux보다 컨텍스트 사용
테마 상태에 React 컨텍스트를 사용하는 이유:
- 단순한 이진 상태 (라이트/다크)
- 복잡한 상태 전환 없음
- Redux 의존성 추가 방지
### 결정: CSS 커스텀 속성
CSS-in-JS 대신 CSS 변수를 사용하는 이유:
- 기존 스타일시트와 호환
- 런타임 오버헤드 없음
- 브라우저 네이티브 솔루션
## 데이터 흐름
```
ThemeProvider (컨텍스트)
│
▼
ThemeToggle ◄──► localStorage
│
▼
CSS 변수 (:root에 적용)
```
## 파일 변경 사항
- `src/contexts/ThemeContext.tsx` (새 파일)
- `src/components/ThemeToggle.tsx` (새 파일)
- `src/styles/globals.css` (수정됨)설계를 업데이트해야 하는 경우:
- 구현에서 접근 방식이 작동하지 않는 것으로 밝혀질 때
- 더 나은 솔루션이 발견될 때
- 의존성 또는 제약 조건이 변경될 때
작업 (tasks.md)
작업은 구현 체크리스트 — 체크박스가 있는 구체적인 단계입니다.
markdown
# 작업
## 1. 테마 인프라
- [ ] 1.1 라이트/다크 상태가 있는 ThemeContext 생성
- [ ] 1.2 색상을 위한 CSS 커스텀 속성 추가
- [ ] 1.3 localStorage 영속성 구현
- [ ] 1.4 시스템 환경설정 감지 추가
## 2. UI 컴포넌트
- [ ] 2.1 ThemeToggle 컴포넌트 생성
- [ ] 2.2 설정 페이지에 토글 추가
- [ ] 2.3 빠른 토글을 포함하도록 Header 업데이트
## 3. 스타일링
- [ ] 3.1 다크 테마 색상 팔레트 정의
- [ ] 3.2 CSS 변수를 사용하도록 컴포넌트 업데이트
- [ ] 3.3 접근성을 위한 대비 비율 테스트작업 모범 사례:
- 관련 작업을 제목 아래에 그룹화
- 계층적 번호 매기기 사용 (1.1, 1.2 등)
- 작업을 하나의 세션에서 완료할 수 있을 만큼 작게 유지
- 작업을 완료할 때 체크 표시
델타 명세서
델타 명세서는 OpenSpec이 레거시 시스템(그린필드가 아닌) 개발에 작동하게 만드는 핵심 개념입니다. 전체 명세서를 다시 진술하는 대신 변경되는 내용을 설명합니다.
형식
markdown
# 인증에 대한 델타
## 추가된 요구 사항
### 요구 사항: 2단계 인증
시스템은 TOTP 기반 2단계 인증을 지원해야 합니다.
#### 시나리오: 2FA 등록
- GIVEN 2FA가 활성화되지 않은 사용자가 있을 때
- WHEN 사용자가 설정에서 2FA를 활성화하면
- THEN 인증 앱 설정을 위한 QR 코드가 표시됩니다
- AND 사용자는 활성화 전에 코드로 확인해야 합니다
#### 시나리오: 2FA 로그인
- GIVEN 2FA가 활성화된 사용자가 있을 때
- WHEN 사용자가 유효한 자격 증명을 제출하면
- THEN OTP 챌린지가 제시됩니다
- AND 로그인은 유효한 OTP 후에만 완료됩니다
## 수정된 요구 사항
### 요구 사항: 세션 만료
시스템은 15분 동안 활동이 없으면 세션을 만료시켜야 합니다.
(이전: 30분)
#### 시나리오: 유휴 타임아웃
- GIVEN 인증된 세션이 있을 때
- WHEN 활동 없이 15분이 경과하면
- THEN 세션이 무효화됩니다
## 제거된 요구 사항
### 요구 사항: 로그인 상태 유지
(2FA로 대체되었습니다. 사용자는 각 세션마다 재인증해야 합니다.)델타 섹션
| 섹션 | 의미 | 아카이브 시 발생하는 일 |
|---|---|---|
## ADDED Requirements | 새로운 동작 | 메인 명세서에 추가됨 |
## MODIFIED Requirements | 변경된 동작 | 기존 요구 사항을 대체함 |
## REMOVED Requirements | 더 이상 사용되지 않는 동작 | 메인 명세서에서 삭제됨 |
전체 명세서 대신 델타를 사용하는 이유
명확성. 델타는 정확히 무엇이 변경되는지 보여줍니다. 전체 명세서를 읽으면 현재 버전과 비교하여 정신적으로 차이를 파악해야 합니다.
충돌 방지. 두 변경 사항이 서로 다른 요구 사항을 수정하는 한, 같은 명세서 파일을 터치하더라도 충돌하지 않습니다.
리뷰 효율성. 리뷰어는 변경 사항을 보지, 변경되지 않은 맥락을 보지 않습니다. 중요한 것에 집중합니다.
레거시 시스템 적합성. 대부분의 작업은 기존 동작을 수정합니다. 델타는 수정을 사후 대처가 아닌 우선 처리 대상으로 만듭니다.
스키마
스키마는 워크플로우를 위한 아티팩트 유형과 그 종속성을 정의합니다.
스키마 작동 방식
yaml
# openspec/schemas/spec-driven/schema.yaml
name: spec-driven
artifacts:
- id: proposal
generates: proposal.md
requires: [] # 의존성 없음, 먼저 생성 가능
- id: specs
generates: specs/**/*.md
requires: [proposal] # 생성 전에 proposal 필요
- id: design
generates: design.md
requires: [proposal] # specs와 병렬로 생성 가능
- id: tasks
generates: tasks.md
requires: [specs, design] # specs와 design 둘 다 필요아티팩트는 의존성 그래프를 형성합니다:
proposal
(루트 노드)
│
┌─────────────┴─────────────┐
│ │
▼ ▼
specs design
(requires: (requires:
proposal) proposal)
│ │
└─────────────┬─────────────┘
│
▼
tasks
(requires:
specs, design)의존성은 가능성을 보여주는 것이지, 반드시 거쳐야 하는 관문이 아닙니다. 다음에 무엇을 생성해야 하는지가 아니라, 무엇을 생성할 수 있는지를 나타냅니다. 필요하지 않다면 design을 건너뛸 수 있습니다. design 전이나 후에 specs를 생성할 수 있습니다 — 둘 다 proposal에만 의존합니다.
내장 스키마
spec-driven (기본값)
스펙 주도 개발을 위한 표준 워크플로우:
proposal → specs → design → tasks → implement적합한 경우: 구현 전에 스펙에 동의하고 싶은 대부분의 기능 작업.
커스텀 스키마
팀의 워크플로우에 맞는 커스텀 스키마를 생성하세요:
bash
# 처음부터 생성
openspec schema init research-first
# 또는 기존 스키마를 포크
openspec schema fork spec-driven research-first커스텀 스키마 예시:
yaml
# openspec/schemas/research-first/schema.yaml
name: research-first
artifacts:
- id: research
generates: research.md
requires: [] # 먼저 조사 수행
- id: proposal
generates: proposal.md
requires: [research] # 조사를 바탕으로 제안서 작성
- id: tasks
generates: tasks.md
requires: [proposal] # 스펙/디자인 건너뛰고 바로 작업으로커스텀 스키마 생성 및 사용에 대한 자세한 내용은 커스터마이제이션을 참조하세요.
아카이브
아카이빙은 변경의 델타 스펙을 메인 스펙에 병합하고, 변경 이력을 보존하여 변경을 완료합니다.
아카이브 시 발생하는 작업
아카이브 전:
openspec/
├── specs/
│ └── auth/
│ └── spec.md ◄────────────────┐
└── changes/ │
└── add-2fa/ │
├── proposal.md │
├── design.md │ 병합
├── tasks.md │
└── specs/ │
└── auth/ │
└── spec.md ─────────┘
아카이브 후:
openspec/
├── specs/
│ └── auth/
│ └── spec.md # 이제 2FA 요구 사항 포함
└── changes/
└── archive/
└── 2025-01-24-add-2fa/ # 이력을 위해 보존됨
├── proposal.md
├── design.md
├── tasks.md
└── specs/
└── auth/
└── spec.md아카이브 프로세스
- 델타 병합. 각 델타 스펙 섹션(추가/수정/삭제)이 해당 메인 스펙에 적용됩니다.
- 아카이브로 이동. 변경 폴더는 시간순 정렬을 위해 날짜 접두어와 함께
changes/archive/로 이동합니다. - 맥락 보존. 모든 아티팩트는 아카이브 내에 그대로 보존됩니다. 변경이 이루어진 이유를 항상 되돌아볼 수 있습니다.
아카이브가 중요한 이유
깔끔한 상태. 활성 변경(changes/)에는 진행 중인 작업만 표시됩니다. 완료된 작업은 비켜갑니다.
감사 추적. 아카이브는 모든 변경의 전체 맥락을 보존합니다 — 무엇이 변했는지만이 아니라, 왜 했는지 설명하는 제안서, 어떻게 했는지 설명하는 디자인, 그리고 수행된 작업을 보여주는 작업 문서까지 포함합니다.
스펙의 발전. 스펙은 아카이브됨에 따라 유기적으로 성장합니다. 각 아카이브는 델타를 병합하여, 시간이 지남에 따라 포괄적인 스펙을 구축합니다.
전체 통합 방식
┌──────────────────────────────────────────────────────────────────────────────┐
│ OPENSPEC FLOW │
│ │
│ ┌────────────────┐ │
│ │ 1. 변경 시작 │ /opsx:propose (코어) 또는 /opsx:new (확장) │
│ │ │ │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 2. 아티팩트 │ /opsx:ff 또는 /opsx:continue (확장 워크플로우) │
│ │ 생성 │ proposal → specs → design → tasks 생성 │
│ │ │ (스키마 의존성에 기반) │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 3. 작업 │ /opsx:apply │
│ │ 구현 │ 작업을 수행하고 완료 처리 │
│ │ │◄──── 학습하면서 아티팩트 업데이트 │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ 4. 작업 검증 │ /opsx:verify (선택사항) │
│ │ │ 구현이 스펙과 일치하는지 확인 │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ ┌──────────────────────────────────────────────┐ │
│ │ 5. 변경 │────►│ 델타 스펙이 메인 스펙으로 병합 │ │
│ │ 아카이브 │ │ 변경 폴더가 archive/로 이동 │ │
│ └────────────────┘ │ 스펙이 이제 업데이트된 유일한 진실의 원천 │ │
│ └──────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────┘선순환:
- 스펙은 현재 동작을 설명합니다
- 변경은 수정 사항을 제안합니다 (델타 형태로)
- 구현은 변경을 실현합니다
- 아카이브는 델타를 스펙으로 병합합니다
- 스펙은 이제 새로운 동작을 설명합니다
- 다음 변경은 업데이트된 스펙을 기반으로 합니다
용어집
| 용어 | 정의 |
|---|---|
| Artifact | 변경 내의 문서 (제안서, 디자인, 작업 또는 델타 스펙) |
| Archive | 변경을 완료하고 그 델타를 메인 스펙으로 병합하는 프로세스 |
| Change | 시스템에 대한 제안된 수정 사항, 아티팩트가 포함된 폴더로 패키징됨 |
| Delta spec | 현재 스펙에 대한 변경 사항(추가/수정/삭제)을 설명하는 스펙 |
| Domain | 스펙의 논리적 그룹 (예: auth/, payments/) |
| Requirement | 시스템이 가져야 하는 구체적인 동작 |
| Scenario | 요구 사항의 구체적인 예시, 일반적으로 Given/When/Then 형식 |
| Schema | 아티팩트 유형과 그 의존성의 정의 |
| Spec | 시스템 동작을 설명하는 명세, 요구 사항과 시나리오 포함 |
| Source of truth | 현재 합의된 동작을 포함하는 openspec/specs/ 디렉토리 |