DEV Community

Cover image for 코딩 에이전트 DESIGN.md란?
Rihpig
Rihpig

Posted on • Originally published at apidog.com

코딩 에이전트 DESIGN.md란?

코딩 에이전트는 빠르게 코드를 작성하지만, 지시하지 않으면 코드베이스의 아키텍처 의도를 모릅니다. Claude Code나 Codex에 모호한 티켓을 주면 컴파일되고 테스트도 통과하지만, 도메인 계층과 HTTP 계층의 경계를 조용히 깨는 코드를 만들 수 있습니다. DESIGN.md는 저장소 안에 아키텍처 의도, 제약 조건, 설계 결정을 기록해 에이전트가 추측하지 않고 규칙에 맞춰 작업하게 만드는 파일입니다.

지금 Apidog 사용해 보기

요약

DESIGN.md는 코드베이스의 아키텍처 의도, 제약 조건, 설계 결정을 Markdown으로 기록하는 저장소 파일입니다.

  • README.md: 프로젝트가 무엇이고 어떻게 시작하는지 설명
  • AGENTS.md: 에이전트가 어떻게 빌드, 테스트, 린트해야 하는지 설명
  • CLAUDE.md: Claude Code 전용 지침
  • DESIGN.md: 코드가 왜 이런 구조인지, 무엇을 절대 깨면 안 되는지 설명

즉, AGENTS.md가 “어떻게 작업하는가”를 다룬다면, DESIGN.md는 “왜 이렇게 설계되었는가”를 다룹니다.

소개

코딩 에이전트를 도입하면 흔히 이런 문제가 발생합니다.

“결제 서비스에 환불 엔드포인트를 추가해줘.”

에이전트는 작동하는 핸들러를 만들 수 있습니다. 하지만 다음과 같은 문제가 숨어 있을 수 있습니다.

  • 컨트롤러에서 데이터베이스를 직접 호출
  • 결제 게이트웨이 오류를 삼켜버림
  • 이미 존재하는 Money 타입을 무시하고 새 금액 타입을 만듦
  • 도메인 불변 조건을 우회
  • 생성된 OpenAPI 타입을 직접 수정

코드는 통과합니다. 테스트도 녹색입니다. 하지만 아키텍처를 아는 리뷰어만 발견할 수 있는 문제가 생깁니다.

에이전트가 코딩을 못해서가 아닙니다. 에이전트는 팀의 머릿속, Notion 페이지, 8개월 전 Slack 스레드에 있는 결정을 보지 못합니다.

DESIGN.md는 이런 결정을 저장소 루트에 명시합니다.

예를 들어:

- HTTP 핸들러는 데이터베이스에 직접 접근하지 않는다.
- 모든 결제 게이트웨이 호출은 아웃박스를 통해 처리한다.
- 금액은 항상 최소 단위 정수와 ISO-4217 통화 코드로 표현한다.
- OpenAPI 사양이 API 계약의 단일 진실 원천이다.
Enter fullscreen mode Exit fullscreen mode

이 파일은 벤더 표준이 아닙니다. ARCHITECTURE.md, ADR, CONTRIBUTING.md처럼 팀이 채택하는 관례입니다. 하지만 코딩 에이전트가 저장소 파일을 직접 읽는 환경에서는 매우 효과적인 안전장치가 됩니다.

DESIGN.md는 무엇인가

DESIGN.md는 코드가 현재 구조를 가지게 된 이유를 설명하는 파일입니다.

다음은 README.md, AGENTS.md와 다릅니다.

  • 코드가 무엇을 하는가 → README.md
  • 어떻게 빌드하고 테스트하는가 → AGENTS.md
  • Claude Code가 어떤 지침을 따라야 하는가 → CLAUDE.md
  • 왜 이 아키텍처를 선택했는가 → DESIGN.md

DESIGN.md에 들어가야 하는 내용은 코드만 읽어서는 알 수 없는 결정입니다.

예를 들어 다음 규칙은 코드에서 어느 정도 추론할 수 있지만, 의도까지는 알기 어렵습니다.

- 요청 스레드에서 결제 게이트웨이를 호출하지 않는다.
  이유: 게이트웨이가 부하 상황에서 자주 타임아웃되므로 모든 호출은 아웃박스 워커가 처리한다.

- `Account.post_entry()`만 원장에 기록할 수 있다.
  이유: 두 번째 쓰기 경로가 과거 잔액 불일치 사고를 만들었다.

- 금액은 부동 소수점이 아니라 최소 단위 정수로 저장한다.
  이유: 반올림 오류를 방지하기 위해서다.
Enter fullscreen mode Exit fullscreen mode

에이전트는 Account.post_entry()가 존재한다는 사실은 볼 수 있습니다. 하지만 그것이 “유일한 쓰기 경로”로 설계되었다는 의도는 알 수 없습니다. 그래서 두 번째 쓰기 경로를 만들 수 있습니다.

DESIGN.md는 이런 설계 의도를 명시적으로 제공합니다.

DESIGN.md vs AGENTS.md vs CLAUDE.md vs README

이 파일들은 역할이 겹쳐 보이지만, 합치면 오히려 유지보수가 어려워집니다.

파일 대상 답하는 질문 변경 빈도 권장 길이
README.md 인간 사용자, 신규 기여자 이것은 무엇이고 어떻게 시작하는가 기능과 함께 변경 중간
AGENTS.md 코딩 에이전트 어떻게 빌드, 테스트, 린트, 커밋하는가 도구와 함께 변경 짧음
CLAUDE.md Claude Code Claude가 따라야 할 지침 도구와 함께 변경 짧음
DESIGN.md 에이전트, 엔지니어, 리뷰어 왜 이런 구조이고 무엇을 깨면 안 되는가 아키텍처와 함께 변경 중간

AGENTS.mdagents.md 프로젝트에서 “코딩 에이전트를 안내하기 위한 간단하고 개방적인 형식”으로 설명됩니다. 빌드 명령, 테스트 명령, 코드 스타일, 커밋 규칙처럼 운영 지침을 담는 데 적합합니다.

Anthropic의 Claude Code 메모리 문서에 따르면 CLAUDE.md는 Claude 전용 지침 파일입니다. 이미 AGENTS.md가 있다면 @AGENTS.md를 임포트해 단일 진실 원천으로 사용하는 방식도 권장됩니다.

하지만 깊은 아키텍처 근거를 AGENTS.mdCLAUDE.md에 모두 넣으면 파일이 길어집니다. Claude Code 문서는 CLAUDE.md를 약 200줄 미만으로 유지하도록 권장합니다. 따라서 다음 구조가 실용적입니다.

README.md      # 인간 온보딩
AGENTS.md      # 빌드, 테스트, 린트, 커밋 규칙
CLAUDE.md      # @AGENTS.md + Claude 전용 규칙
DESIGN.md      # 아키텍처 의도, 불변 조건, 설계 결정
Enter fullscreen mode Exit fullscreen mode

예시:

# AGENTS.md

## 작업 전 확인

- 빌드: `pnpm build`
- 테스트: `pnpm test`
- 린트: `pnpm lint`
- 구조적 변경, API 변경, 도메인 로직 변경 전에는 `DESIGN.md`를 읽는다.
Enter fullscreen mode Exit fullscreen mode
# CLAUDE.md

@AGENTS.md
@DESIGN.md

Claude Code는 설계 규칙과 충돌하는 변경을 임의로 우회하지 말고,
충돌을 설명한 뒤 가장 작은 대안을 제안한다.
Enter fullscreen mode Exit fullscreen mode

Claude 컨텍스트를 구조화하는 방법은 Claude Code 워크플로우에서도 다룹니다.

DESIGN.md에 넣을 내용

DESIGN.md는 에이전트가 코드에서 추론하기 어려운 질문에 답해야 합니다.

포함할 항목은 다음과 같습니다.

  1. 시스템 형태

    • 계층 구조
    • 모듈 경계
    • 의존성 방향
  2. 불변 조건

    • 항상 참이어야 하는 규칙
    • 절대 깨면 안 되는 제약
  3. 주요 설계 결정과 근거

    • 왜 이 패턴을 선택했는지
    • 어떤 사고나 요구사항 때문에 결정했는지
  4. 거부된 대안

    • 다시 도입하면 안 되는 방식
    • 에이전트가 “새 아이디어”로 제안하지 않도록 방지
  5. 데이터 및 도메인 규칙

    • 금액 표현
    • 시간대 처리
    • ID 생성 방식
    • 멀티테넌시
    • 삭제 정책
  6. API 계약의 단일 진실 원천

    • OpenAPI 사양 위치
    • 생성 코드 수정 금지
    • 에러 형식, 페이지네이션, 버전 관리 규칙
  7. 새 코드가 들어갈 위치

    • 엔드포인트
    • 유스케이스
    • 도메인 로직
    • 외부 통합
    • 미들웨어
  8. 건드리지 말아야 할 영역

    • 생성 파일
    • 동결된 레거시 모듈
    • 이미 적용된 마이그레이션

바로 사용할 수 있는 DESIGN.md 템플릿

아래 템플릿을 저장소 루트의 DESIGN.md로 복사한 뒤, 프로젝트에 맞게 수정하세요.

# DESIGN.md: 결제 API 서비스

이 파일은 아키텍처 의도와 설계 결정을 기록한다.
코드를 생성하거나 수정하기 전에 이 파일을 읽는다.

변경 사항이 이 파일의 규칙과 충돌하면,
규칙을 우회하지 말고 충돌을 설명한 뒤 대안을 제안한다.

## 시스템 형태

이 서비스는 계층형 구조를 사용한다.

http -> app -> domain <- infra

- `http/`는 라우트, 핸들러, DTO를 포함한다.
- `app/`은 유스케이스와 포트를 포함한다.
- `domain/`은 엔티티, 값 객체, 불변 조건을 포함한다.
- `infra/`는 DB, 메시지 큐, 외부 게이트웨이 클라이언트를 포함한다.

의존성 규칙:

- `domain/``http/`, `app/`, `infra/` 또는 웹 프레임워크를 임포트하지 않는다.
- `http/`는 데이터베이스나 외부 게이트웨이를 직접 호출하지 않는다.
- `http/``app/`의 유스케이스만 호출한다.
- `infra/``app/ports/`에 정의된 인터페이스를 구현한다.

## 불변 조건

- 원장 항목은 한 번 작성되면 수정하거나 삭제하지 않는다.
- 원장 수정은 기존 항목 변경이 아니라 상쇄 항목 추가로 처리한다.
- 계정 잔액은 원장 항목에서 파생한다.
- 잔액을 직접 설정하는 필드는 만들지 않는다.
- 금액은 최소 단위 정수와 ISO-4217 통화 코드로 표현한다.
- 금액 계산에 부동 소수점을 사용하지 않는다.
- 외부 결제 게이트웨이 호출은 `idempotency_key`로 멱등해야 한다.
- 명시적인 `OverdraftPolicy`가 없으면 잔액은 음수가 될 수 없다.
- 모든 쿼리는 `tenant_id`로 범위가 지정되어야 한다.

## 주요 설계 결정

### 게이트웨이 호출은 아웃박스를 사용한다

핸들러는 비즈니스 변경과 같은 DB 트랜잭션 안에서 아웃박스 행을 작성한다.
워커가 아웃박스를 읽고 결제 게이트웨이를 호출한다.

이유:

- 게이트웨이는 부하 상황에서 타임아웃될 수 있다.
- 요청 핸들러에서 직접 호출하면 지연 시간과 실패 처리가 불안정해진다.
- 재시도와 멱등성을 중앙에서 관리해야 한다.

따라서 요청 핸들러에서 결제 게이트웨이를 직접 호출하지 않는다.

### 원장에는 단일 쓰기 경로만 사용한다

`Account.post_entry()`만 원장에 기록할 수 있다.

이유:

- 두 번째 쓰기 경로가 과거 잔액 불일치 사고를 만들었다.
- 모든 잔액 변경은 동일한 도메인 불변 조건을 통과해야 한다.

새 동작은 새 쿼리나 직접 INSERT가 아니라,
애그리게이트 메서드로 추가한다.

### 원장만 이벤트 소싱을 사용한다

원장은 감사 추적이 필요하므로 이벤트 소싱을 사용한다.
나머지 시스템은 CRUD를 사용한다.

전체 시스템에 이벤트 소싱을 확장하지 않는다.

## 거부된 대안

다음 방식을 다시 도입하지 않는다.

- 애그리게이트 전반에 걸친 ORM 지연 로딩
  - 이유: N+1 문제와 불명확한 트랜잭션 경계를 만들었다.

- 잔액을 업데이트 가능한 컬럼으로 저장
  - 이유: 잔액 불일치 사고를 만들었다.
  - 잔액은 항상 원장에서 파생한다.

- 외부 `Money` 라이브러리 임의 도입
  - 이 서비스는 `domain/money.py`를 사용한다.

- 요청 스레드에서 상인에게 동기 웹훅 호출
  - 이유: 블로킹과 조용한 실패를 유발했다.
  - 알림 큐를 사용한다.

## 데이터 및 도메인 규칙

- 모든 타임스탬프는 UTC다.
- DB에는 `timestamptz`로 저장한다.
- API 경계에서는 RFC 3339 형식을 사용한다.
- 함수 경계를 넘는 naive datetime은 허용하지 않는다.
- ID는 앱 계층에서 생성한 ULID를 사용한다.
- DB auto-increment ID를 공개 API 식별자로 사용하지 않는다.
- 소프트 삭제는 사용하지 않는다.
- 삭제가 필요한 데이터는 명시적인 유스케이스로 아카이브 테이블에 이동한다.
- 모든 리포지토리 메서드는 `tenant_id` 범위를 받아야 한다.

## API 계약의 단일 진실 원천

- `api/openapi.yaml`의 OpenAPI 3.1 사양이 권위적이다.
- 요청/응답 타입은 OpenAPI 사양에서 생성한다.
- `http/generated/`의 생성 코드는 수동으로 수정하지 않는다.
- 신규 또는 변경된 엔드포인트는 먼저 `api/openapi.yaml`을 수정한다.
- 사양을 재생성한 뒤 구현한다.
- 오류 응답은 RFC 9457 `problem+json`을 따른다.
- 오류 응답은 공유 `problem()` 헬퍼를 사용한다.
- 엔드포인트별 임의 오류 형식을 만들지 않는다.

## 새 코드가 들어갈 위치

- 새 엔드포인트
  - 라우트: `http/routes/`
  - DTO: `http/dto/`
  - 유스케이스: `app/usecases/`
  - 도메인 로직: `domain/`

- 새 외부 통합
  - 인터페이스: `app/ports/`
  - 구현체: `infra/clients/`

- 인증, 로깅, 멱등성 같은 교차 관심사
  - `http/middleware/`
  - 핸들러 내부에 인라인으로 구현하지 않는다.

## 범위 외 / 건드리지 말 것

- `http/generated/`
  - OpenAPI에서 재생성된다.
  - 수동 편집하지 않는다.

- `legacy/billing_v1/`
  - 동결된 레거시 모듈이다.
  - 확장하지 않는다.

- `migrations/`
  - 이미 적용된 마이그레이션은 수정하지 않는다.
  - 새 마이그레이션을 추가한다.

## 의심스러울 때

요청된 변경이 위 규칙을 위반해야 한다면,
조용히 우회하지 않는다.

대신 다음을 수행한다.

1. 어떤 규칙과 충돌하는지 설명한다.
2. 왜 충돌하는지 설명한다.
3. 가장 작은 설계 일관적 대안을 제안한다.
Enter fullscreen mode Exit fullscreen mode

마지막 섹션이 중요합니다. 에이전트는 제약에 부딪히면 우회해서 “작동하는 코드”를 만들려는 경향이 있습니다. “우회하지 말고 플래그를 지정하라”는 지침을 명시하면 DESIGN.md가 단순 문서가 아니라 안전장치가 됩니다.

에이전트가 DESIGN.md를 읽게 만드는 방법

에이전트가 자동으로 DESIGN.md를 특별 취급하는 것은 아닙니다. 일반 파일처럼 읽고 컨텍스트로 사용합니다.

따라서 에이전트가 시작 시 읽는 지침 파일에서 참조해야 합니다.

Claude Code

CLAUDE.md에 다음을 추가합니다.

@DESIGN.md

구조적 변경, API 변경, 도메인 로직 변경 전에는 DESIGN.md를 읽는다.
DESIGN.md와 충돌하는 변경은 우회하지 말고 충돌을 설명한다.
Enter fullscreen mode Exit fullscreen mode

AGENTS.md 기반 에이전트

AGENTS.md에 다음을 추가합니다.

## 아키텍처 규칙

구조적 변경, API 변경, 도메인 로직 변경 전에는 `DESIGN.md`를 읽는다.
`DESIGN.md`의 불변 조건과 충돌하는 변경은 구현하지 말고 플래그를 지정한다.
Enter fullscreen mode Exit fullscreen mode

리뷰에서 사용하는 방법

리뷰어는 긴 설명 대신 DESIGN.md의 규칙을 기준으로 피드백할 수 있습니다.

이 변경은 DESIGN.md의 "HTTP 핸들러는 DB에 직접 접근하지 않는다" 규칙을 위반합니다.
DB 호출을 app/usecases/의 유스케이스로 이동하세요.
Enter fullscreen mode Exit fullscreen mode

에이전트는 이런 피드백을 받으면 보통 빠르게 수정합니다. 자체 에이전트 하네스를 만드는 팀도 이 피드백 루프를 활용합니다. 관련 내용은 자체 Claude Code 구축을 참고하세요.

안티 패턴

DESIGN.md가 오래된 위키 문서처럼 변하면 없는 것보다 나쁩니다. 에이전트와 인간 모두 잘못된 규칙을 믿게 됩니다.

다음 패턴을 피하세요.

1. 코드를 다시 설명하기

나쁜 예:

UserService는 사용자를 처리한다.
Enter fullscreen mode Exit fullscreen mode

이 정보는 에이전트가 코드에서 바로 읽을 수 있습니다.

좋은 예:

사용자 상태 전이는 `User.activate()`, `User.suspend()`를 통해서만 수행한다.
상태를 직접 업데이트하면 감사 이벤트가 누락된다.
Enter fullscreen mode Exit fullscreen mode

2. 튜토리얼로 만들기

DESIGN.md는 “기능 추가 방법” 문서가 아닙니다.

셸 명령, 긴 단계별 가이드, 로컬 개발 팁은 CONTRIBUTING.mdAGENTS.md에 두세요.

3. 희망을 사실처럼 쓰기

나쁜 예:

모든 쓰기는 유스케이스를 통한다.
Enter fullscreen mode Exit fullscreen mode

실제로 레거시 코드가 이를 우회한다면 에이전트는 허구에 맞춰 코드를 만들 수 있습니다.

좋은 예:

목표: 모든 쓰기는 `app/usecases/`를 통한다.
현재: `legacy/`는 이 규칙을 우회한다.
새 코드는 `legacy/` 패턴을 확장하지 않는다.
Enter fullscreen mode Exit fullscreen mode

4. 소유자와 리뷰 트리거가 없음

DESIGN.md는 PR 프로세스와 연결해야 합니다.

PR 템플릿에 다음 체크리스트를 추가하세요.

- [ ] 이 PR은 계층 경계, API 계약, 데이터 모델, 외부 의존성 중 하나를 변경한다.
- [ ] 그렇다면 `DESIGN.md`를 검토했고 필요한 경우 같은 PR에서 업데이트했다.
Enter fullscreen mode Exit fullscreen mode

5. 코드와 줄 단위로 동기화하려고 하기

DESIGN.md는 함수 시그니처 목록이 아닙니다.

자주 바뀌는 세부사항이 아니라 다음처럼 오래 유지되는 결정을 기록하세요.

  • 계층 경계
  • 트랜잭션 경계
  • 멱등성 전략
  • 데이터 모델 원칙
  • 금지된 패턴
  • API 계약 규칙

6. 다른 지침 파일과 모순되기

AGENTS.mdDESIGN.md가 같은 규칙을 다르게 말하면 에이전트는 임의로 선택할 수 있습니다.

역할을 분리하세요.

  • 운영 규칙: AGENTS.md, CLAUDE.md
  • 아키텍처 규칙: DESIGN.md

중복 작성하지 말고 참조하세요.

API 및 백엔드 코드베이스에서 특히 중요한 이유

API와 백엔드 서비스는 에이전트가 잘못 추론하기 쉬운 제약이 많습니다.

  • 계약 경계
  • 트랜잭션 의미론
  • 멱등성
  • 데이터 무결성
  • 테넌시 스코핑
  • 에러 모델
  • 버전 호환성
  • 생성 코드와 수동 코드의 경계

이 규칙들은 단일 파일만 읽어서는 명확히 보이지 않습니다. 하지만 잘못 처리하면 프로덕션 장애, 보안 문제, 금전 손실로 이어질 수 있습니다.

1. OpenAPI를 단일 진실 원천으로 지정하기

DESIGN.md에 명확히 적으세요.

- `api/openapi.yaml`이 API 계약의 단일 진실 원천이다.
- 요청/응답 타입은 OpenAPI에서 생성한다.
- 생성된 타입은 수동으로 수정하지 않는다.
- 새 엔드포인트는 먼저 OpenAPI 사양을 변경한 뒤 구현한다.
Enter fullscreen mode Exit fullscreen mode

에이전트는 빌드를 통과시키기 위해 생성 타입을 직접 수정하려는 경우가 있습니다. 이 규칙은 그런 변경을 막습니다.

Apidog에서 먼저 API 계약을 설계하고 OpenAPI 문서를 저장소로 내보내면, DESIGN.md가 그 파일을 권위 있는 계약으로 지정할 수 있습니다. 코드보다 계약을 먼저 설계해야 하는 이유는 AI 에이전트를 위한 API 설계에서 자세히 다룹니다.

2. 트랜잭션 경계 명시하기

나쁜 결과를 막으려면 트랜잭션 규칙을 명시해야 합니다.

- 외부 HTTP 호출은 DB 트랜잭션 내부에서 수행하지 않는다.
- 비즈니스 변경과 외부 호출 의도는 같은 트랜잭션에서 아웃박스에 기록한다.
- 외부 호출은 워커가 아웃박스를 통해 수행한다.
Enter fullscreen mode Exit fullscreen mode

이 규칙이 없으면 에이전트는 핸들러 안에서 외부 API를 직접 호출할 가능성이 높습니다.

3. 멱등성 규칙 명시하기

결제, 주문, 프로비저닝 API에서는 멱등성이 핵심입니다.

- 모든 결제 생성 요청은 `Idempotency-Key` 헤더를 요구한다.
- 같은 키로 재시도하면 같은 결과를 반환해야 한다.
- 게이트웨이 호출은 내부 `idempotency_key`와 연결되어야 한다.
Enter fullscreen mode Exit fullscreen mode

4. 오류 모델 고정하기

- 모든 오류 응답은 RFC 9457 `problem+json`을 따른다.
- 오류 응답은 `problem()` 헬퍼를 통해 생성한다.
- 엔드포인트별 임의 오류 래퍼를 만들지 않는다.
Enter fullscreen mode Exit fullscreen mode

이 규칙이 없으면 엔드포인트마다 다른 오류 형식이 생길 수 있습니다.

5. 인증과 테넌시 스코핑 명시하기

- 모든 리포지토리 쿼리는 `tenant_id` 범위를 포함해야 한다.
- 테넌트 범위가 없는 리포지토리 메서드는 버그다.
- 인증된 사용자 컨텍스트는 `RequestContext`에서만 읽는다.
Enter fullscreen mode Exit fullscreen mode

이런 규칙은 보안 불변 조건입니다. 반드시 문서화해야 합니다.

6. 버전 관리와 호환성 파괴 변경 정의하기

- 응답 필드 삭제 또는 이름 변경은 호환성 파괴 변경이다.
- 필드 추가는 기본적으로 비파괴 변경이다.
- 호환성 파괴 변경은 새 API 버전에서만 허용한다.
Enter fullscreen mode Exit fullscreen mode

에이전트는 필드명을 “더 깔끔하게” 바꿀 수 있습니다. DESIGN.md는 그것이 API 호환성 파괴 변경임을 알려줍니다.

백엔드에서 가장 큰 효과는 에이전트가 스키마를 발명하지 않고 OpenAPI 사양을 따르게 만드는 것입니다. Apidog 다운로드를 통해 설계 우선 API 작업 공간을 만들고, DESIGN.md가 가리킬 OpenAPI 사양을 내보내며, 에이전트가 생성한 엔드포인트가 계약과 일치하는지 테스트할 수 있습니다.

도입 체크리스트

저장소에 DESIGN.md를 추가할 때는 다음 순서로 진행하세요.

- [ ] 저장소 루트에 `DESIGN.md`를 만든다.
- [ ] 시스템 계층과 의존성 방향을 적는다.
- [ ] 절대 깨면 안 되는 불변 조건을 적는다.
- [ ] 주요 설계 결정과 이유를 적는다.
- [ ] 다시 도입하면 안 되는 거부된 대안을 적는다.
- [ ] OpenAPI 사양 위치와 생성 코드 규칙을 적는다.
- [ ] 새 코드가 들어갈 디렉터리를 적는다.
- [ ] 건드리지 말아야 할 영역을 적는다.
- [ ] `AGENTS.md` 또는 `CLAUDE.md`에서 `DESIGN.md`를 참조한다.
- [ ] PR 템플릿에 `DESIGN.md` 검토 체크박스를 추가한다.
Enter fullscreen mode Exit fullscreen mode

결론

DESIGN.md는 에이전트에게 코드의 “형태”가 아니라 “이유”를 알려주는 파일입니다.

핵심은 다음과 같습니다.

  • 에이전트가 코드에서 읽을 수 없는 설계 의도를 기록합니다.
  • AGENTS.md, CLAUDE.md를 대체하지 않고 보완합니다.
  • 불변 조건, 거부된 대안, 트랜잭션 경계, API 계약 규칙을 명시합니다.
  • 규칙은 선언적이고 테스트 가능한 문장으로 작성합니다.
  • 충돌 시 우회하지 말고 플래그를 지정하라고 지시합니다.
  • OpenAPI 사양을 단일 진실 원천으로 지정하면 API 생성 품질이 크게 좋아집니다.
  • PR 템플릿과 소유자를 통해 파일이 부패하지 않게 관리합니다.

먼저 계약을 설계하세요. Apidog를 다운로드해 API를 설계 우선으로 작성하고, DESIGN.md가 가리킬 OpenAPI 사양을 내보낸 뒤, 에이전트가 생성한 엔드포인트가 실제 계약과 일치하는지 테스트하세요.

FAQ

DESIGN.md는 AGENTS.md처럼 공식 표준인가요?

아닙니다. AGENTS.md는 Linux Foundation의 Agentic AI Foundation에서 관리하는 널리 채택된 형식입니다. DESIGN.mdARCHITECTURE.md나 ADR처럼 커뮤니티 관례에 가깝습니다. 표준이라기보다 실용적인 패턴으로 보면 됩니다.

AGENTS.md나 CLAUDE.md가 이미 있어도 DESIGN.md가 필요한가요?

아키텍처 제약이 있다면 필요합니다. AGENTS.mdCLAUDE.md는 짧은 운영 지침에 적합합니다. 깊은 설계 근거와 불변 조건은 별도의 DESIGN.md에 두고 참조하는 편이 좋습니다. 운영 파일 작성은 AGENTS.md 파일 작성 방법을 참고하세요.

DESIGN.md는 ARCHITECTURE.md와 어떻게 다른가요?

목적은 비슷합니다. 다만 DESIGN.md는 코딩 에이전트가 읽기 쉽도록 더 선언적이고, 결정과 불변 조건에 초점을 둡니다. 팀에 이미 ARCHITECTURE.md가 있고 같은 역할을 잘 수행한다면 파일명을 반드시 바꿀 필요는 없습니다.

DESIGN.md는 얼마나 길어야 하나요?

2~4페이지 정도가 실용적입니다. 중요한 것은 길이가 아니라 결정 밀도입니다. 코드에서 바로 알 수 있는 설명은 제거하고, 불변 조건과 근거를 남기세요.

에이전트가 실제로 DESIGN.md를 읽게 하려면 어떻게 해야 하나요?

에이전트가 시작 시 읽는 파일에서 참조하세요.

Claude Code:

@DESIGN.md
Enter fullscreen mode Exit fullscreen mode

AGENTS.md:

구조적 변경 전에는 `DESIGN.md`를 읽는다.
Enter fullscreen mode Exit fullscreen mode

전체 내용을 AGENTS.mdCLAUDE.md에 붙여넣지 말고 참조만 하세요.

에이전트는 항상 DESIGN.md를 따르나요?

아닙니다. 에이전트 지침은 강제 제약이 아니라 컨텍스트입니다. 그래서 규칙을 명확한 절대문으로 작성하고, 충돌 시 우회하지 말고 플래그를 지정하라고 명시해야 합니다. 리뷰 루프도 필요합니다.

DESIGN.md가 API 계약 문제에 도움이 되나요?

많이 도움이 됩니다. 특히 OpenAPI 사양을 권위 있는 계약으로 지정하면 에이전트가 스키마를 임의로 만들거나 생성 타입을 직접 수정하는 문제를 줄일 수 있습니다. Apidog 같은 도구에서 먼저 계약을 설계하면 DESIGN.md가 가리킬 명확한 대상이 생깁니다.

DESIGN.md는 저장소 어디에 두어야 하나요?

일반적으로 저장소 루트에 둡니다.

README.md
AGENTS.md
CLAUDE.md
DESIGN.md
Enter fullscreen mode Exit fullscreen mode

모노레포에서는 루트 DESIGN.md에 전체 규칙을 두고, 패키지별 DESIGN.md에 로컬 아키텍처 규칙을 둘 수 있습니다.

Top comments (0)