Blog
spec-kitspec-driven-developmentconstitutionai-agentclaude-codeai

[Spec Kit ③] Constitution — AI에게 우리 팀의 원칙을 각인시키기

Spec Kit의 모든 단계로 흘러 들어가는 단 하나의 파일, constitution.md. 데이터 엔지니어링 팀이 dq-monitor 프로젝트의 헌법을 어떻게 세우는지, 좋은 원칙과 나쁜 원칙의 차이는 무엇인지 실전 예제와 함께 짚습니다.

Data Dynamics2026年6月13日28 min read
This post is not yet translated. The original Korean version is shown below.

2부에서 우리는 specify CLI로 dq-monitor 프로젝트에 SDD 스캐폴딩을 깔고 Claude Code와 연동했습니다. 이제 빈 캔버스 위에 첫 줄을 그을 차례인데, 그 첫 줄이 명세도 코드도 아닌 헌법(constitution) 이라는 점이 SDD의 특이한 출발점입니다. 헌법은 "이 프로젝트에서 좋은 코드란 무엇인가"를 한 번 적어두는 파일이고, 이후 등장하는 모든 /speckit.* 단계가 이 파일을 읽고 시작합니다. 이 글은 그 헌법을 데이터 엔지니어링 팀의 현실에 맞게 어떻게 잘 쓰는지에 대한 이야기입니다.

이 글에서 배우는 것

  • 헌법(.specify/memory/constitution.md)이 왜 시리즈에서 가장 레버리지가 큰 파일인지
  • /speckit.constitution 명령으로 헌법 초안을 생성하는 법
  • "검증 가능한 원칙" vs "듣기 좋은 구호" — 좋은 원칙과 나쁜 원칙의 차이
  • 바로 가져다 쓸 수 있는 데이터 엔지니어링 팀용 헌법 전체 예제
  • 헌법이 clarify·checklist·analyze 게이트와 어떻게 맞물리는지

이 글은 Spec Kit 시리즈의 3부입니다. 1부에서 SDD의 철학을, 2부에서 설치와 프로젝트 구조를 다뤘다면, 3부는 본격적인 워크플로의 첫 단추인 헌법을 채웁니다.


1. 헌법이란 무엇이고, 왜 모든 단계를 지배하는가

Spec Kit의 워크플로는 다음 순서로 흐릅니다.

Constitution → Specification → Clarification → Planning
→ Task Breakdown → Implementation → Convergence

이 흐름에서 헌법은 맨 앞에 옵니다. 그런데 단지 "첫 단계"인 것이 아니라, 나머지 모든 단계의 배경으로 깔리는 단계입니다. 명세를 쓸 때도, 계획을 세울 때도, 작업을 분해할 때도, 코드를 구현할 때도 AI 에이전트는 헌법을 먼저 읽고 그 기준 위에서 판단합니다.

헌법 파일은 다음 경로에 살아 있습니다.

.specify/memory/constitution.md

경로의 memory라는 이름이 의미심장합니다. 헌법은 프로젝트의 장기 기억입니다. 1부에서 우리는 바이브 코딩의 첫 번째 실패 모드로 "맥락 유실(context loss)"을 꼽았습니다. 대화가 길어지면 초반에 합의한 결정이 컨텍스트 창 밖으로 밀려난다는 문제였죠. 헌법은 바로 그 문제에 대한 구조적 해법입니다. "우리는 타입을 100% 명시한다", "스키마는 절대 조용히 깨지 않는다" 같은 결정을 파일에 박아두면, 그 결정은 50번째 요청에서도 사라지지 않습니다.

헌법은 매 /speckit.* 단계에 로드됩니다. 명세 파일은 기능마다 하나씩 생기고, 계획도 기능마다 갈리지만, 헌법은 전 단계·전 기능에 공통으로 적용되는 단 하나의 파일입니다. 한 줄을 고치면 그 효과가 이후 모든 산출물에 곱해집니다. 이것이 헌법이 시리즈 전체에서 레버리지가 가장 큰 파일인 이유입니다.

구체적으로 헌법이 담는 것은 "이 프로젝트를 관통하는 원칙"입니다. 대표적으로 네 축이 있습니다.

헌법이 고정하는 것고정하지 않으면 생기는 일
코드 품질 (Code Quality)스타일·타이핑·린트 게이트AI가 요청마다 다른 컨벤션으로 코드를 짬
테스트 기준 (Testing Standards)커버리지 기준, 어떤 테스트를 의무화할지테스트가 있는 코드와 없는 코드가 뒤섞임
UX 일관성 (UX Consistency)에러 포맷, 로그·알림의 톤과 구조같은 상황을 매번 다른 모양으로 출력
성능 (Performance)지연·처리량 예산(SLA)"빠르게"라는 말만 있고 기준이 없어 회귀를 못 잡음

핵심은 헌법이 무엇을 만들지(what) 가 아니라 어떻게 잘 만들지(how well) 를 정한다는 것입니다. 기능 요구사항은 명세(2부 예고대로 4부)에서 다룹니다. 헌법은 그 위 계층, 즉 어떤 기능을 만들든 항상 지켜야 할 품질의 바닥을 까는 일입니다.


2. /speckit.constitution 실행하기

헌법을 직접 손으로 적을 수도 있지만, Spec Kit은 AI 에이전트가 초안을 잡아주는 전용 명령을 제공합니다. Claude Code 안에서 다음과 같이 호출합니다.

/speckit.constitution

명령만 던지면 에이전트가 "어떤 원칙에 초점을 둘까요?"라고 되묻거나, 함께 넘긴 지시를 바탕으로 바로 초안을 작성합니다. 가장 좋은 사용법은 초점 영역을 명시한 프롬프트를 함께 주는 것입니다.

/speckit.constitution
 
코드 품질, 테스트 기준, 사용자 경험 일관성, 성능 요구사항에
초점을 둔 원칙을 만들어 줘. 우리는 실시간 데이터 품질 모니터링
서비스(dq-monitor)를 만드는 데이터 엔지니어링 팀이야.

(영문 원문 권장 표현: "Create principles focused on code quality, testing standards, user experience consistency, and performance requirements.")

이 프롬프트를 받으면 에이전트는 대략 다음 순서로 움직입니다.

Loading diagram…

여기서 강조할 점은 4번 단계(사람의 검토) 입니다. 에이전트가 만든 초안은 출발선이지 결승선이 아닙니다. 1부에서 봤듯 SDD의 품질은 "한 방 생성"이 아니라 "단계별 사람 검증"에서 나옵니다. 헌법은 그 첫 검증 지점이고, 여기서 흐릿하게 넘어간 원칙은 이후 모든 단계에 흐릿함을 전파합니다.

그래서 초안을 받으면 가장 먼저 던질 질문은 단 하나입니다. "이 원칙을 위반했는지 기계나 리뷰어가 판정할 수 있는가?" 이 질문에 "아니오"라면, 그 원칙은 다시 써야 합니다. 다음 절이 바로 그 이야기입니다.


3. 좋은 원칙 vs 나쁜 원칙 — 검증 가능성이 전부다

헌법이 실패하는 가장 흔한 방식은 "틀린 원칙"이 아니라 "검증할 수 없는 원칙" 입니다. "우리는 깨끗한 코드를 추구한다" 같은 문장은 누구도 반대하지 않지만, 동시에 누구도 위반할 수 없습니다. 위반을 판정할 수 없는 원칙은 AI를 전혀 제약하지 못합니다. AI는 어떤 코드를 내놓아도 "이것이 깨끗하지 않다"는 반증에 부딪히지 않기 때문입니다.

좋은 원칙은 구체적이고(specific) 검증 가능(checkable) 합니다. 사람이 읽고 "이건 통과/실패"를 가를 수 있어야 하고, 가능하면 기계가 판정할 수 있으면 더 좋습니다. 아래 표가 그 차이를 보여줍니다.

영역나쁜 원칙 (모호·검증 불가)좋은 원칙 (구체·검증 가능)
코드 품질"코드는 읽기 쉬워야 한다""모든 공개 함수는 타입 어노테이션을 가지며, ruffmypy --strict가 무경고로 통과해야 한다"
테스트"충분한 테스트를 작성한다""신규/변경 코드의 라인 커버리지 80% 이상, 모든 데이터 스키마는 계약 테스트(contract test)를 가진다"
성능"알림은 빨라야 한다""이상 탐지 → 알림 발송까지 p95 지연 5초 이내, 단일 인스턴스가 초당 10k 이벤트를 처리한다"
데이터 계약"스키마를 잘 관리한다""스키마 변경은 버전 번호를 올리고, 하위 호환을 깨는 변경은 마이그레이션 노트 없이는 머지 불가"
관측성"로그를 잘 남긴다""모든 로그는 JSON 구조화 로그이며 trace_id를 포함한다. 모든 알림은 원인 메트릭으로 역추적 가능해야 한다"
보안"보안에 신경 쓴다""시크릿은 코드/로그에 절대 등장하지 않고 환경변수 또는 시크릿 매니저로만 주입한다. 서비스 계정은 최소 권한을 가진다"

오른쪽 열의 공통점은 숫자, 도구 이름, 명시적 금지가 들어 있다는 것입니다. p95 5초, 커버리지 80%, mypy --strict, 머지 불가 같은 표현은 회색지대를 없앱니다. AI가 헌법을 읽고 코드를 짤 때도, 사람이 PR을 리뷰할 때도, 나중에 /speckit.checklist가 항목을 만들 때도 모두 같은 기준으로 판정할 수 있습니다.

원칙을 쓸 때 자가진단: 문장에서 테스트 케이스나 린트 규칙, 또는 PR 리뷰 코멘트가 곧바로 연상되지 않는다면, 그 원칙은 아직 구호 단계입니다. 한 번 더 구체화하세요.


4. 데이터 엔지니어링 팀용 헌법 전체 예제

이제 dq-monitor를 만드는 데이터 엔지니어링 팀이 실제로 쓸 만한 헌법을 통째로 보겠습니다. 아래는 그대로 .specify/memory/constitution.md에 넣고 팀 사정에 맞춰 숫자만 조정하면 되는, 재사용 가능한 자산입니다. (앞서 본 "검증 가능성" 원칙을 모든 조항에 적용했습니다.)

# dq-monitor Constitution
 
본 헌법은 실시간 데이터 품질 모니터링 서비스(dq-monitor)의 모든
명세·계획·작업·구현에 적용되는 최상위 원칙이다. 모든 `/speckit.*`
단계는 본 문서를 기준으로 산출물을 생성·검증한다. 조항 간 충돌 시
상위 번호(낮은 번호)가 우선한다.
 
Version: 1.0.0
Ratified: 2026-06-23
Last Amended: 2026-06-23
 
## 1. 코드 품질 (Code Quality)
 
- 1.1 언어 표준: 서비스 코드는 Python 3.12+를 사용하며, 모든 공개
      함수·메서드·모듈 경계는 타입 어노테이션을 가진다.
- 1.2 정적 게이트: `ruff check`(lint) 및 `ruff format --check`(format),
      `mypy --strict`가 모두 무경고로 통과해야 CI가 그린이 된다.
      게이트 미통과 코드는 머지할 수 없다.
- 1.3 함수 복잡도: 단일 함수는 순환 복잡도(cyclomatic complexity)
      10을 넘지 않는다. 초과 시 분해하거나 명시적 예외 주석을 남긴다.
- 1.4 의존성: 신규 런타임 의존성 추가는 PR 설명에 도입 이유와
      대안 검토를 1줄 이상 기록한다. lock 파일 갱신을 동반한다.
 
## 2. 테스트 기준 (Testing Standards)
 
- 2.1 커버리지: 신규/변경된 라인의 테스트 커버리지는 80% 이상이다.
      전체 커버리지를 하락시키는 PR은 사유를 명시해야 한다.
- 2.2 계약 테스트: 모든 입력 데이터 스키마와 외부 알림 페이로드는
      계약 테스트(contract test)를 가진다. 스키마는 픽스처로
      고정되며, 픽스처와 실제 코드가 어긋나면 테스트가 실패한다.
- 2.3 결정성: 테스트는 외부 네트워크·실시간 시계에 의존하지 않는다.
      시간은 주입 가능한 클럭으로, 외부 시스템은 페이크/목으로 대체한다.
- 2.4 회귀 테스트: 버그 수정 PR은 수정 전이라면 실패했을 회귀
      테스트를 반드시 포함한다.
 
## 3. 데이터 계약 규율 (Data Contract Discipline)
 
- 3.1 스키마 버전: 모든 데이터 스키마는 명시적 버전(semver)을 가진다.
- 3.2 무무음 파괴(no silent breaking change): 하위 호환을 깨는 스키마
      변경은 (a) major 버전 증가, (b) 마이그레이션 노트, (c) 명시적
      승인 라벨 없이는 머지 불가하다.
- 3.3 호환 우선: 가능하면 필드 추가(가산적 변경)를 선호하고, 필드
      삭제·타입 변경·의미 변경은 deprecation 기간을 둔다.
- 3.4 검증 위치: 데이터는 시스템 경계(수집 지점)에서 즉시 스키마
      검증한다. 검증을 통과하지 못한 레코드는 조용히 버리지 않고
      격리(dead-letter)하고 메트릭으로 집계한다.
 
## 4. 관측성 (Observability)
 
- 4.1 구조화 로그: 모든 로그는 JSON 구조화 로그이며, 최소 필드로
      `timestamp`, `level`, `service`, `trace_id`, `message`를 포함한다.
- 4.2 추적성: 하나의 이벤트 처리 흐름은 단일 `trace_id`로 수집부터
      알림까지 연결 가능해야 한다.
- 4.3 메트릭: 처리 지연, 큐 적체, 이상 탐지 건수, 알림 발송 결과는
      메트릭으로 노출한다(예: Prometheus 형식).
- 4.4 추적 가능한 알림: 모든 알림은 그 알림을 유발한 원인 메트릭·
      레코드로 역추적 가능해야 한다. 근거 없는 알림은 금지한다.
 
## 5. 성능 / SLA (Performance / SLA)
 
- 5.1 알림 지연 예산: 이상 탐지 시점부터 알림 발송까지의 지연은
      p95 기준 5초, p99 기준 10초를 넘지 않는다.
- 5.2 처리량: 단일 워커 인스턴스는 초당 최소 10,000 이벤트를
      안정적으로 처리한다(백프레셔 없이).
- 5.3 성능 회귀 게이트: 성능에 영향을 줄 수 있는 변경은 벤치마크
      결과를 PR에 첨부한다. 5.1·5.2 예산을 깨는 변경은 머지 불가.
- 5.4 자원 한계: 정상 부하에서 워커 메모리 사용은 설정된 상한을
      넘지 않으며, 초과 시 OOM 대신 백프레셔로 흡수한다.
 
## 6. 보안 (Security)
 
- 6.1 시크릿: API 키·토큰·비밀번호는 코드·설정 파일·로그에 절대
      평문으로 등장하지 않는다. 환경변수 또는 시크릿 매니저로만 주입한다.
- 6.2 최소 권한: 모든 서비스 계정·토큰은 필요한 최소 범위의 권한만
      가진다. 광범위(admin/wildcard) 권한 부여는 PR에서 사유를 요구한다.
- 6.3 입력 신뢰 금지: 외부에서 들어온 데이터는 신뢰하지 않고,
      검증·정규화 후에만 처리·저장한다(3.4와 연계).
- 6.4 의존성 보안: 알려진 취약점(예: `pip-audit` 고위험)이 있는
      의존성은 머지 전에 해소하거나 명시적 위험 수용 기록을 남긴다.
 
## 거버넌스 (Governance)
 
- 본 헌법은 살아 있는 문서다. 분기마다 또는 중대한 아키텍처 변경 시
  검토하며, 개정 시 버전(semver)과 개정일을 갱신한다.
- 어떤 명세·계획·작업도 본 헌법과 충돌할 수 없다. 충돌이 불가피하면
  헌법을 먼저 개정한 뒤 진행한다.
- 원칙은 검증 가능해야 한다. 새 조항을 추가할 때는 "어떻게 위반을
  판정하는가"를 함께 적는다.

이 예제의 의도는 "그대로 베껴 쓰라"가 아니라 각 조항이 어떻게 검증 가능하게 쓰였는지를 보여주는 데 있습니다. 모든 항목이 숫자·도구·명시적 금지를 품고 있고, 거버넌스 절은 헌법을 write-once 문서가 아니라 살아 있는 문서로 못 박습니다. 여러분 팀은 숫자(80%, p95 5초, 초당 10k)와 도구 이름(ruff, mypy, pip-audit)을 자기 스택에 맞게 바꾸면 됩니다.


5. 헌법이 이후 게이트와 맞물리는 방식

헌법은 적어두고 끝나는 문서가 아니라, 이후 품질 게이트들이 참조하는 기준점입니다. Spec Kit은 프로덕션 작업이나 의미 있는 모호성이 있는 작업에서 /speckit.constitution·/speckit.clarify·/speckit.checklist를 품질 게이트로 켤 것을 권장합니다. 이 게이트들은 모두 헌법을 위에서 비춥니다.

Loading diagram…

각 게이트가 헌법을 쓰는 방식을 구체화하면 다음과 같습니다.

게이트헌법을 어떻게 참조하는가
/speckit.clarify명세의 빈틈을 질문할 때, 헌법이 정한 기준(예: SLA, 스키마 버전 정책)에 비춰 빠진 결정을 캐묻는다
/speckit.checklist헌법 조항을 검증 가능한 체크 항목으로 변환한다. "p95 5초" 같은 조항이 곧 체크리스트 한 줄이 된다
/speckit.analyzespec·plan·tasks가 서로 모순되는지뿐 아니라, 헌법을 위반하는 결정이 끼어들지 않았는지 교차검증한다
/speckit.implement코드를 생성할 때 헌법의 코드 품질·테스트·보안 원칙을 적용 기준으로 삼는다

이 구조의 함의는 분명합니다. 헌법 한 줄이 나중에 수많은 체크리스트 항목과 분석 경고로 증폭됩니다. 반대로 헌법에서 빠뜨린 원칙은 어느 게이트에서도 잡히지 않습니다. 게이트는 헌법에 없는 기준을 스스로 발명하지 않기 때문입니다. 그래서 3절에서 강조한 "검증 가능하게 쓰기"가 이 절에서 비로소 보상받습니다 — 구체적인 조항일수록 더 많은 자동 검증으로 환원됩니다.


6. 안티패턴 — 헌법을 망치는 세 가지 방법

좋은 헌법을 쓰는 법만큼, 흔한 실패를 피하는 법도 중요합니다. 현장에서 반복되는 세 가지 안티패턴을 짚습니다.

안티패턴 1 — 범용 헌법 복붙

인터넷에서 찾은 "모범 constitution"을 통째로 붙여넣는 경우입니다. 문제는 헌법의 가치가 그 팀의 구체적 결정에 있다는 점입니다. "초당 10k 이벤트", "p95 5초"는 dq-monitor의 도메인에서 나온 숫자이지, 범용 헌법에 적혀 있을 수 없습니다. 남의 헌법은 좋은 목차일 수 있어도 좋은 내용일 수는 없습니다. 구조는 참고하되, 모든 숫자와 금지 조항은 여러분 팀이 채우세요.

안티패턴 2 — 아무도 강제하지 않는 원칙

"커버리지 80%"라고 써놓고 CI에 커버리지 게이트가 없으면, 그 원칙은 장식입니다. 검증 가능하게 쓰는 것(3절)은 필요조건일 뿐, 실제로 게이트에 연결해야 비로소 힘을 갖습니다. 헌법의 각 조항에 대해 "이것을 강제하는 메커니즘이 어디에 있는가?"(CI 잡, 린트 규칙, /speckit.checklist 항목, PR 리뷰 룰)를 물으세요. 강제 메커니즘이 없는 조항은 다음 회고에서 강제하거나 삭제할 후보입니다.

안티패턴 3 — write-once 문서로 취급

헌법을 한 번 쓰고 잊는 것입니다. 그러나 프로젝트는 자라고, 처음의 SLA가 비현실적이었음이 드러나거나, 새로운 보안 요구가 생깁니다. 헌법은 살아 있는 문서여야 합니다 — 위 예제의 거버넌스 절이 "분기마다 검토, 개정 시 버전 갱신"을 명시한 이유입니다. 헌법을 고치는 일은 패배가 아니라 학습입니다. 다만 고칠 때는 코드가 아니라 헌법을 먼저 고친다는 SDD의 방향을 지키세요.

세 안티패턴을 한 문장으로: 헌법은 남의 것이 아니라 우리 것이어야 하고, 장식이 아니라 강제되어야 하며, 박제가 아니라 살아 있어야 합니다.


마치며

헌법은 분량으로 보면 한 화면짜리 파일이지만, 레버리지로 보면 시리즈 전체에서 가장 무거운 파일입니다. 이후 명세·계획·작업·구현의 모든 단계가 이 파일을 읽고 시작하기 때문입니다. 그래서 헌법을 잘 쓰는 비결은 단 하나, 검증 가능하게 쓰는 것입니다. 숫자·도구·명시적 금지를 담아, 사람과 AI와 자동 게이트가 모두 같은 기준으로 판정할 수 있게 만드세요.

다음 4부에서는 헌법이라는 바닥 위에 드디어 무엇을 만들지를 적습니다. /speckit.specifydq-monitor의 요구사항을 명세하고, /speckit.clarify로 그 명세의 빈틈을 메우는 과정을 따라가 보겠습니다. 헌법이 "어떻게 잘 만들지"를 정했다면, 명세는 "무엇을 만들지"를 정합니다. 둘이 만나는 지점에서 진짜 SDD가 시작됩니다.

참고 자료