Agentic Coding 시대의 Repo 부트스트래핑 가이드 Part 2: Go + Templ + HTMX To-Do 앱으로 직접 만들어 보기
이 글은 Claude Opus 4.7 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.
Part 1 에서는 2026년 5월 기준 de-facto 가 된 spec 문서들의 지형도와 best practices 를 정리했습니다. 2편에서는 가상의 Go + Templ + HTMX 기반 To-Do 앱 gotodo 를 새로 부트스트래핑한다고 가정하고, 각 문서를 실제로 어떻게 채우는지 발췌 형태로 따라갑니다.
가상 프로젝트: gotodo#
스택은 다음과 같습니다.
- Go 1.23 — 표준 라이브러리 중심
- templ — Go 네이티브 SSR 템플릿 (type-safe)
- HTMX 2.0 — 클라이언트 JS 최소화
- SQLite +
modernc.org/sqlite— CGO 없는 순수 Go 드라이버
목표는 단순합니다. 할 일 추가/완료/삭제만 되는 SSR 미니멀 앱. 1인 로컬 사용을 가정합니다.
Step 0: git init 직후의 1차 골격#
git init 직후 가장 먼저 만드는 건 파일이 아니라 디렉터리 구조의 합의 입니다. Vertical Slice Architecture(VSA) 를 따른다는 가정으로 다음과 같이 잡습니다.
gotodo/
├── AGENTS.md
├── CLAUDE.md # -> AGENTS.md (symlink)
├── GEMINI.md # -> AGENTS.md (symlink)
├── README.md
├── ARCHITECTURE.md
├── DESIGN.md
├── DEVELOPMENT.md
├── Makefile
├── go.mod
├── cmd/server/main.go
├── features/
│ └── task/ # feature slice: 한 폴더에 핸들러+스토어+뷰+테스트
│ ├── handler.go
│ ├── handler_test.go
│ ├── store.go
│ ├── store_test.go
│ └── views.templ
├── internal/
│ ├── db/db.go
│ └── server/server.go
├── migrations/
│ └── 001_create_tasks.sql
├── static/
│ └── htmx.min.js
└── docs/
├── adr/0001-htmx-over-spa.md
└── specs/001-task-crud.md
VSA 채택 이유는 Part 1 에서 가볍게 언급했고, 곧 ADR-0001 로 다시 적습니다. 핵심만 짚으면, 한 변경을 위해 에이전트가 들고 다녀야 할 컨텍스트가 한 폴더 안에 닫혀 있다는 점입니다.
Step 1: README.md — agent-friendly 진입점#
README 는 사람과 에이전트가 동시에 보는 진입점입니다. 3줄 quick start + 무엇/무엇이 아닌지 + 다음에 볼 문서들, 이 세 블록이면 충분합니다.
# gotodo
A minimal SSR-based To-Do app. Go + Templ + HTMX + SQLite.
Single-user, local-first. No JS framework, no build step.
## Quick start
```bash
git clone https://github.com/example/gotodo
cd gotodo
make dev # http://localhost:8080
What it is / What it isn’t#
- It is: 학습 목적의 미니멀 SSR 앱. HTMX 의 hypermedia 패턴을 실험합니다.
- It isn’t: 멀티 유저 SaaS, 모바일 앱, 오프라인 동기화 기능.
Where to go next#
AGENTS.md— 에이전트가 따라야 할 규칙 (사람도 읽으세요)ARCHITECTURE.md— 시스템 구조와 도메인 모델DESIGN.md— 시각 디자인 시스템 (컬러, 타이포, 컴포넌트)DEVELOPMENT.md— 매일 쓰는 명령어docs/specs/— 진행 중인 feature specdocs/adr/— 큰 의사결정의 기록
README 가 1500줄이 되는 가장 흔한 이유는, "혹시 누가 못 찾을까 봐" 모든 걸 여기에 적기 때문입니다. **다른 문서로 위임하는 1줄 포인터** 가 더 친절합니다.
---
## Step 2: `AGENTS.md` + symlink 설정
`AGENTS.md` 는 단일 진실 원본입니다. 다음은 `gotodo` 의 발췌입니다.
```markdown
# AGENTS.md
이 문서는 사람과 에이전트(Claude Code, Codex CLI, Cursor 등)가
이 repo 에서 일할 때 공통으로 따르는 규칙입니다.
## 1. 프로젝트 한 줄 요약
Go + Templ + HTMX + SQLite 로 만든 SSR 기반 미니멀 To-Do 앱.
싱글 유저, 로컬 우선.
## 2. 자주 쓰는 명령어
| Task | Command |
|--------------|------------------|
| 개발 서버 | `make dev` |
| 테스트 | `make test` |
| 린트 | `make lint` |
| 빌드 | `make build` |
| DB 마이그레이션 | `make migrate` |
세부는 `DEVELOPMENT.md` 참조.
## 3. 디렉터리 한 줄 안내
- `cmd/server/` — main 진입점
- `features/<name>/` — feature slice (handler + store + view + test)
- `internal/db/` — DB 초기화
- `internal/server/` — HTTP 서버, 라우팅
- `migrations/` — SQL 마이그레이션
- `docs/` — ADR 와 spec
자세한 구조와 의도는 `ARCHITECTURE.md` 참조.
## 4. 작업 규칙
### 4-1. Vertical Slice 안에서 일하라
새 feature 는 `features/<name>/` 폴더 안에 닫아야 합니다.
다른 feature 의 코드를 import 하지 마세요. 공통 로직이 필요해지면
먼저 issue 를 열고 논의하세요.
### 4-2. 테스트가 먼저
핸들러와 스토어 변경은 항상 실패하는 테스트 → 통과로 갑니다.
Templ 뷰의 텍스트 변경처럼 명백한 케이스는 예외입니다.
### 4-3. SQL 은 인라인으로, ORM 금지
`database/sql` 표준 라이브러리만 사용합니다. ORM/쿼리빌더는
이 프로젝트의 범위에서 과합니다 (ADR-0002 참조).
### 4-4. 클라이언트 JS 는 HTMX 외에 추가 금지
ADR-0001 의 결정. 새 JS 라이브러리를 추가하고 싶다면 먼저 ADR 로 제안하세요.
## 5. 작업 완료 전 체크리스트
- [ ] `make test` 통과
- [ ] `make lint` 통과 (exit code 0)
- [ ] 변경된 feature 의 `*.templ` 가 `templ generate` 로 재생성됨
- [ ] `docs/specs/` 에 해당하는 spec 이 있고 acceptance criteria 가 만족됨
## 6. 보안/시크릿
- `.env` 와 `*.db` 파일은 절대 커밋하지 않습니다.
- DB 파일 경로는 `GOTODO_DB_PATH` 환경변수로만 받습니다.
## 7. 도구별 보강
### Claude Code
- `~/.claude/commands/release.md` 에 `/release` 가 정의되어 있습니다.
- 릴리스 전 항상 `/release dry-run` 을 먼저 실행하세요.
### Cursor
- `.cursor/rules/templ.mdc` 가 `*.templ` 파일 편집 시 자동 적용됩니다.
- `templ generate` 를 빠뜨리지 않도록 강제합니다.
symlink 설정은 다음 한 번이면 끝입니다.
ln -s AGENTS.md CLAUDE.md
ln -s AGENTS.md GEMINI.md
git add AGENTS.md CLAUDE.md GEMINI.md
이렇게 두면 Claude Code 든 Codex CLI 든 Gemini CLI 든 동일한 규칙을 읽습니다.
Claude Code 의 글로벌 CLAUDE.md 와의 관계#
~/.claude/CLAUDE.md 에 사용자별 글로벌 규칙(예: “한국어 경어체로 답변하라”, “git 커밋 메시지는 Conventional Commits 로”) 이 있다면, 그것은 그대로 둡니다. 프로젝트의 ./CLAUDE.md(→ AGENTS.md) 는 그 위에 쌓이므로, 프로젝트 규칙이 글로벌 규칙을 덮어쓰거나 보완합니다.
Step 3: ARCHITECTURE.md — 도메인 모델과 Templ 컴포넌트 구조#
ARCHITECTURE 는 “조립도” 입니다. 다음은 발췌입니다.
# ARCHITECTURE
## 시스템 다이어그램
```mermaid
flowchart LR
Browser["Browser<br/>(HTMX)"] -- HTTP --> Server["Go HTTP Server<br/>(net/http)"]
Server --> Feature["features/task<br/>handler+store+view"]
Feature --> DB[("SQLite<br/>tasks.db")]
style Browser fill:#87CEEB,color:#000000
style Server fill:#90EE90,color:#000000
style Feature fill:#FFD700,color:#000000
style DB fill:#FFB6C1,color:#000000
```
## 도메인 모델
가장 중요한 엔티티는 `Task` 하나입니다.
```go
type Task struct {
ID int64
Title string // 1..200 chars, trim
Done bool
CreatedAt time.Time // UTC
}
```
제약사항:
- `Title` 은 trim 후 빈 문자열이면 400 응답.
- `Title` 길이는 200자 초과 시 400.
- `Done` 토글은 idempotent.
## HTTP 라우트
| Method | Path | 응답 |
|--------|-----------------------|-------------------------------|
| GET | `/` | 전체 페이지 (full page) |
| POST | `/tasks` | 새 row partial (`<li>`) |
| POST | `/tasks/{id}/toggle` | 갱신된 row partial |
| DELETE | `/tasks/{id}` | 빈 응답 (HTMX 가 row 제거) |
HTMX 의 부분 응답 패턴(out-of-band swap)을 사용합니다. JSON 은 쓰지 않습니다.
## Templ 컴포넌트 구조
- `views.Layout(title)` — 전체 페이지 셸
- `views.TaskList(tasks)` — `<ul>` 컨테이너
- `views.TaskRow(t)` — 하나의 `<li>` (POST/toggle/delete 의 응답이 곧 이 컴포넌트)
- `views.NewTaskForm()` — 상단 입력 폼
핵심 원칙: **HTTP 핸들러는 한 컴포넌트만 렌더링** 한다. 페이지 한 덩어리를 통째로 반환하는 경로는 `GET /` 뿐.
## 의존성 흐름
```
cmd/server/main.go
└─ internal/server.New(db)
└─ features/task.NewHandler(store)
└─ features/task.NewStore(db)
└─ internal/db.Open()
```
각 feature 패키지는 자기 `Store` 와 `Handler` 의 인터페이스를 자기 폴더 안에서 정의합니다.
다른 feature 의 internal 패키지를 import 하지 않습니다.
Tip: Mermaid 다이어그램의 배경색을 밝게 쓸 때는
color:#000000을 함께 지정해야 다크 테마에서도 글자가 보입니다. 이 블로그의 CLAUDE.md 에도 같은 규칙이 적혀 있습니다.
Step 4: DESIGN.md — 시각 디자인 시스템#
DESIGN.md 는 비교적 새 컨벤션입니다. 2025년 후반 Google Stitch 가 표준 포맷 을 제안했고, VoltAgent 의 awesome-design-md 가 Linear, Vercel, Stripe, Notion 등 73개 사이트의 실제 DESIGN.md 를 모아 사실상 보급의 허브 역할을 하고 있습니다.
역할은 한 문장으로 정리됩니다. AGENTS.md 는 “어떻게 빌드하는가”, DESIGN.md 는 “어떤 모양인가” 입니다. 새 화면이나 컴포넌트를 추가할 때 에이전트가 매번 “버튼 색은 뭘로 할까”, “간격은 얼마로 할까” 를 새로 결정하지 않고, 이 파일을 단일 진실 원본으로 참조하게 만드는 게 목표입니다.
다음은 gotodo 의 발췌입니다. 1인 로컬 앱이라 의도적으로 작게 잡았습니다.
# DESIGN
## 1. Visual Theme & Atmosphere
**Terminal-minimal**. CLI 도구를 GUI 로 옮긴 듯한 인상.
이미지 없음, 그라데이션 없음, 애니메이션 최소. 정보 밀도와 빠른 조작감이 미관보다 우선.
## 2. Color Palette & Roles
| Token | Hex | Role |
|---------------|-----------|--------------------------------------|
| `--bg` | `#0E1116` | 페이지 배경 |
| `--surface` | `#161B22` | 카드/리스트 항목 배경 |
| `--fg` | `#E6EDF3` | 기본 텍스트 |
| `--muted` | `#8B949E` | 보조 텍스트, 완료된 task |
| `--accent` | `#3FB950` | 활성 상태, primary button |
| `--danger` | `#F85149` | 삭제, 에러 상태 |
| `--border` | `#30363D` | 1px 분할선 |
다크 테마만 지원합니다. 라이트 테마는 v2 에서 검토 예정.
## 3. Typography Rules
전부 시스템 모노스페이스 스택. 별도 웹폰트를 다운로드하지 않습니다.
```css
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo,
Consolas, "Liberation Mono", monospace;
```
| Element | Size | Weight | Line-height |
|-------------|------|--------|--------------|
| `<h1>` | 24px | 600 | 1.3 |
| 본문 | 16px | 400 | 1.5 |
| Task title | 16px | 400 | 1.4 |
| Hint/meta | 13px | 400 | 1.4 |
## 4. Component Stylings
### Button — Primary (`+ Add`)
- bg: `--accent`, fg: `--bg`, padding: `8px 16px`, radius: `4px`
- Hover: opacity 0.9
- Disabled: opacity 0.4, cursor not-allowed
### Button — Danger (`✕`)
- bg: transparent, fg: `--danger`, radius: `4px`
- Hover: bg `rgba(248, 81, 73, 0.1)`
### Text Input
- bg: `--surface`, fg: `--fg`, border: 1px solid `--border`, radius: `4px`
- Focus: border-color `--accent`, outline 없음
- Placeholder: `--muted`
### Task Row (`<li>`)
- 가로 layout: `[checkbox] [title] ........ [delete]`
- padding: `12px 16px`, border-bottom: 1px solid `--border`
- 완료된 task: title 에 `text-decoration: line-through`, color `--muted`
## 5. Layout Principles
- **Spacing scale**: 4 / 8 / 12 / 16 / 24 / 32 (8px base, 4 와 12 만 예외)
- **Container**: max-width 640px, 가운데 정렬 (1인 앱은 좁은 폭이 자연스럽다)
- **Whitespace**: 항목 사이 0, 섹션 사이 24px. 빽빽함을 두려워하지 않는다.
## 6. Depth & Elevation
평면적 디자인을 유지합니다. shadow 는 다음 두 경우만 허용합니다.
- focus 가 들어간 input: `0 0 0 2px rgba(63, 185, 80, 0.3)`
- 에러 토스트(있다면): `0 4px 12px rgba(0, 0, 0, 0.4)`
## 7. Do's and Don'ts
**Do**
- 모노스페이스 폰트로 일관된 그리드 정렬을 유지한다.
- 상태 변화는 색으로 표현한다 (애니메이션 대신).
- 모든 상호작용은 키보드로도 가능해야 한다 (Tab/Enter/Space).
**Don't**
- 그라데이션, 이미지, 아이콘 폰트를 추가하지 않는다 (절대).
- 라이트 테마용 색을 임의로 도입하지 않는다 (ADR 로 제안 후).
- transition 시간을 200ms 보다 길게 두지 않는다.
## 8. Responsive Behavior
단일 컬럼 레이아웃이라 별도 breakpoint 가 거의 필요 없습니다.
- `< 480px`: container padding 16px → 8px
- 터치 타깃 최소 44×44px (delete 버튼 포함)
## 9. Agent Prompt Guide
새 UI 컴포넌트를 만들 때 에이전트에 던질 짧은 프롬프트 템플릿:
> Style this component using the tokens in `DESIGN.md`.
> Use `--accent` only for the primary action. Match the existing
> `TaskRow` density. Mono font, no images, no gradients.
색만 빨리 참조하고 싶을 때:
> Primary action → `--accent` (#3FB950). Destructive → `--danger` (#F85149).
> Surfaces → `--bg` / `--surface`. Text → `--fg` / `--muted`.
왜 이 9개 섹션인가#
awesome-design-md 의 모든 예제가 같은 9개 섹션을 가집니다. 처음에는 “한 페이지짜리 앱에 9개나?” 싶지만, 막상 적어 보면 각 섹션이 매우 짧아도 충분합니다(gotodo 의 위 예제는 전체가 100줄 이하). 중요한 건 에이전트가 헤매지 않도록 미리 결정해 두는 것 이지, 결정의 양이 아닙니다.
Templ 컴포넌트가 토큰을 참조하게 만들기#
DESIGN.md 만 두면 잊혀집니다. 토큰을 실제 CSS 로 옮기고, Templ 컴포넌트가 그 토큰만 사용하게 강제해야 살아 있는 문서가 됩니다.
<!-- static/tokens.css : DESIGN.md 의 토큰을 그대로 옮긴 단일 파일 -->
:root {
--bg: #0E1116;
--surface: #161B22;
--fg: #E6EDF3;
--muted: #8B949E;
--accent: #3FB950;
--danger: #F85149;
--border: #30363D;
}
// features/task/views.templ (발췌)
templ TaskRow(t Task) {
<li class="task-row">
<button class="btn-toggle"
hx-post={ fmt.Sprintf("/tasks/%d/toggle", t.ID) }
hx-target="closest li" hx-swap="outerHTML">
if t.Done { ☑ } else { ☐ }
</button>
<span class={ "title", templ.KV("done", t.Done) }>{ t.Title }</span>
<button class="btn-danger"
hx-delete={ fmt.Sprintf("/tasks/%d", t.ID) }
hx-target="closest li" hx-swap="delete">✕</button>
</li>
}
이러면 새 컴포넌트를 만들 때도 에이전트가 tokens.css 의 변수만 쓰게 됩니다.
awesome-design-md 활용 팁#
처음 DESIGN.md 를 쓰는 사람에게 가장 막막한 부분은 “톤” 입니다. 그럴 때는 awesome-design-md 에서 자기 프로젝트의 톤과 가까운 사이트를 골라 그 DESIGN.md 를 그대로 복사한 뒤 토큰만 바꿔 시작 하는 게 빠릅니다. 예를 들어 gotodo 처럼 미니멀/모노스페이스 톤이라면 Vercel 이나 Ollama 의 DESIGN.md 가 좋은 출발점입니다.
한 가지 주의. awesome-design-md 의 DESIGN.md 들은 마케팅 사이트 기준이라 섹션이 풍부합니다. 1인 앱이나 내부 도구에는 그대로 가져오면 과합니다. 자기 프로젝트 규모에 맞춰 5~10% 까지 줄이는 것을 두려워하지 마세요.
Step 5: 첫 ADR — docs/adr/0001-htmx-over-spa.md#
ADR 은 짧을수록 좋습니다. Michael Nygard 포맷을 거의 그대로 씁니다.
# ADR-0001: HTMX over SPA
## Status
Accepted (2026-05-28)
## Context
`gotodo` 는 1인 로컬 사용을 가정한 학습 프로젝트입니다.
SPA 를 채택하면 다음이 따라옵니다.
- Node.js 빌드 파이프라인 (vite/esbuild)
- 클라이언트 라우팅
- JSON API 와 SSR 의 이원화
이 모든 비용이 학습 목적과 1인 사용 가정에 비추어 과합니다.
## Decision
다음을 채택합니다.
- 모든 페이지/부분 응답은 서버에서 HTML 로 렌더링한다 (templ).
- 인터랙션은 HTMX 의 attribute 만으로 작성한다 (`hx-post`, `hx-target`, `hx-swap`).
- 추가 클라이언트 JS 라이브러리는 금지한다.
## Consequences
### Positive
- 빌드 파이프라인이 `make build` 한 줄로 끝난다.
- 핸들러가 반환하는 응답이 곧 사용자에게 보이는 화면이라 디버깅이 쉽다.
- 에이전트가 "JSON 응답을 SPA 가 어떻게 그릴까" 를 추측할 필요가 없다.
### Negative
- 복잡한 클라이언트 상태가 필요한 화면(드래그앤드롭, 오프라인 큐 등)이 생기면 재검토 필요.
- HTMX 의 OOB swap 패턴에 익숙해지는 학습 비용.
## Alternatives considered
- **Next.js (App Router)** — 빌드 파이프라인 비용 과다.
- **Alpine.js + plain JSON API** — 응답 형태 이원화로 핸들러가 두 가지 모드를 가져야 함.
- **Vanilla JS + fetch** — 작성 비용은 낮지만 일관된 패턴을 강제하기 어려움.
ADR 을 적어 두면, 6개월 뒤 에이전트에게 “React 로 바꿔 줘” 라는 요청이 들어왔을 때 “이 결정은 ADR-0001 에 의해 이미 거부된 옵션입니다” 라고 답할 근거가 생깁니다.
Step 6: DEVELOPMENT.md — 매일 쓰는 명령어#
AGENTS.md 의 명령어 표는 매우 짧게, 자세한 흐름은 DEVELOPMENT.md 에 둡니다.
# DEVELOPMENT
## 사전 요구사항
- Go 1.23+
- `templ` CLI (`go install github.com/a-h/templ/cmd/templ@latest`)
- `golangci-lint` (`brew install golangci-lint`)
## 자주 쓰는 명령어
```bash
make dev # templ generate --watch + air (http://localhost:8080)
make test # go test ./...
make lint # golangci-lint run
make build # CGO_DISABLED=1 go build -o bin/gotodo ./cmd/server
make migrate # 누적된 migrations/*.sql 을 순서대로 적용
make clean # bin/, *.db, templ 생성물 제거
```
## 환경변수
| 변수 | 기본값 | 설명 |
|---------------------|----------------|---------------------|
| `GOTODO_DB_PATH` | `./gotodo.db` | SQLite 파일 경로 |
| `GOTODO_LISTEN_ADDR`| `:8080` | 서버 바인딩 주소 |
`.env.example` 를 복사해서 `.env` 를 만들면 `make dev` 가 자동으로 로드합니다.
## 테스트 작성 규칙
- 핸들러 테스트는 `httptest.NewServer` 로 실제 라우터에 붙입니다 (mock 금지).
- 스토어 테스트는 임시 SQLite 파일로 돌립니다 (`t.TempDir()`).
- 통합 테스트가 5\~10초 안에 끝나는 한, 모킹보다 실제 의존성을 선호합니다.
## 커밋 컨벤션
[Conventional Commits](https://www.conventionalcommits.org/).
PR 제목도 같은 규칙을 따릅니다. `commitlint` 가 CI 에서 검증합니다.
```
feat(task): add toggle endpoint
fix(store): handle empty title after trim
docs(adr): record HTMX-over-SPA decision
```
Step 7: 첫 feature spec — docs/specs/001-task-crud.md#
feature 단위 spec 은 짧고 검증 가능해야 합니다. 다음은 발췌입니다.
# SPEC-001: Task CRUD
## Background
`gotodo` 의 최소 기능 단위. 사용자가 할 일을 추가/완료/삭제할 수 있어야 한다.
## Goals
- 한 페이지에서 할 일을 입력하고 즉시 목록에 추가한다 (페이지 새로고침 없이).
- 각 항목을 클릭/체크하면 완료 상태가 토글된다.
- 삭제 버튼으로 항목을 제거한다.
- 모든 변경은 SQLite 에 즉시 반영된다.
## Non-goals
- 사용자 인증
- 마감일/우선순위
- 다중 사용자, 다중 디바이스 동기화
## Acceptance criteria
- [ ] `GET /` 가 현재 할 일 목록과 새 항목 입력 폼을 렌더링한다.
- [ ] `POST /tasks` 가 `title` 폼 값을 받아 새 항목을 저장하고, `TaskRow` 부분 응답을 반환한다.
- [ ] `title` 이 trim 후 빈 문자열이면 400 을 반환한다.
- [ ] `title` 길이가 200자 초과면 400 을 반환한다.
- [ ] `POST /tasks/{id}/toggle` 이 `Done` 을 뒤집고 갱신된 `TaskRow` 를 반환한다.
- [ ] `DELETE /tasks/{id}` 가 항목을 제거하고 빈 응답을 반환한다 (HTMX 가 DOM 에서 제거).
- [ ] 위 모든 동작에 대한 핸들러/스토어 테스트가 있다.
## Open questions
- 동일한 title 을 가진 항목을 허용할 것인가? → **허용**. 사용자가 일부러 둘 수 있음.
- 정렬 기준은? → `CreatedAt DESC` 로 시작. 나중에 spec 으로 분리 가능.
이 spec 1장이 있으면, 에이전트가 첫 작업을 시작할 때 어디까지가 범위이고 어디부터가 다른 spec 인지 명확해집니다.
검증: Claude Code 에 작업을 시켜 보기#
여기까지 부트스트래핑이 끝났습니다. 진짜 가치가 나오는 건 다음 순간입니다. 빈 features/task/ 폴더로 가서, 에이전트에게 이렇게만 던집니다.
docs/specs/001-task-crud.md 를 보고 task feature 를 구현해 주세요.
부트스트래핑이 잘 되어 있는 repo 에서 에이전트가 보이는 행동은 대략 다음과 같습니다.
AGENTS.md부터 읽고, “VSA 안에서 일하라”, “테스트 먼저”, “ORM 금지”, “HTMX 외 JS 금지” 같은 규칙을 컨텍스트에 적재합니다.ARCHITECTURE.md의 라우트 표와 Templ 컴포넌트 구조를 확인, 어떤 핸들러가 어떤 컴포넌트를 반환해야 하는지 파악합니다.DESIGN.md의 토큰과 컴포넌트 스타일을 확인, 새 마크업에 임의의 색이나 폰트를 도입하지 않고tokens.css의 변수만 참조합니다.docs/specs/001-task-crud.md의 acceptance criteria 를 그대로 테스트 케이스로 풀어 먼저 작성합니다.- 빨간 테스트를 통과시키는 최소 구현을
features/task/안에서 작성합니다. make test와make lint를 직접 돌려 보고 결과를 확인합니다.- ADR-0001 을 근거로, 도중에 “여기서 Alpine.js 를 추가하면 편할 것 같은데” 같은 일탈을 스스로 거부합니다.
부트스트래핑이 부실하면 위 흐름의 절반 이상이 사용자와의 핑퐁(“테스트 먼저 작성해 주세요”, “ORM 쓰지 마세요”, “이 폴더 안에서만 작업해 주세요”) 으로 채워집니다. 매번 같은 말을 반복하는 대신, 문서에 한 번 적어 두는 편이 훨씬 쌉니다.
부트스트래핑 체크리스트#
여러분의 다음 신규 프로젝트에 가져다 쓸 수 있는 한 장 짜리 체크리스트로 정리합니다.
Day 1 (git init 직후)#
-
README.md— 3줄 quick start + 무엇/무엇이 아닌지 + 다음 문서 포인터 -
AGENTS.md— 200~400줄 이내, 자주 쓰는 명령 표, 디렉터리 한 줄 안내, 작업 규칙, 완료 체크리스트 -
CLAUDE.md/GEMINI.md—AGENTS.md로의 symlink (또는 짧은 보강 파일) -
ARCHITECTURE.md— 시스템 다이어그램(Mermaid), 도메인 모델, 의존성 흐름 -
DESIGN.md— UI 가 있는 프로젝트라면 Stitch 9개 섹션. awesome-design-md 의 유사 톤 사이트에서 출발해도 좋음 -
DEVELOPMENT.md— 빌드/테스트/실행 명령, 환경변수, 커밋 컨벤션 -
Makefile—dev/test/lint/build최소 4개 타깃 -
.gitignore— 시크릿/빌드 결과물/DB 파일 제외
첫 feature 시작 전#
-
docs/adr/0001-*.md— 가장 큰 첫 의사결정(스택 선택, 아키텍처 패턴) 기록 -
docs/specs/001-*.md— 첫 feature 의 Background/Goals/Non-goals/Acceptance criteria
자동 검증 장치 (있으면 좋음)#
- CI 에서
README.md의 quick start 명령이 실제로 동작하는지 검증 - CI 에서
make test/make lint강제 - commitlint 또는 PR title lint 로 커밋 메시지 컨벤션 강제
-
templ generate같은 코드젠 출력물의 dirty diff 검출
1~2개월 뒤 주기적으로 점검#
-
AGENTS.md가 600줄을 넘기지 않았는가? → 넘었다면 분리 - 같은 정보가 두 문서에 중복되어 있지 않은가?
- 완료된 spec 은
docs/specs/archive/로 이동했는가? - ADR 이 6개월 이상 새 항목 없이 멈춰 있지는 않은가? (의사결정 자체가 멈췄는지 점검)
마무리#
2년 전이라면 신규 git repo 의 1일 차 작업은 “README 작성 + go mod init” 두 줄로 끝났습니다. 지금은 AGENTS.md 를 시작으로 한 spec 문서 셋이 그만큼의 자리를 차지합니다. 부담스럽게 들릴 수 있지만, 실제로는 정반대입니다. 매 세션마다 같은 규칙을 사람이 반복해서 말하지 않게 만드는 일회성 비용입니다.
핵심은 다음 세 가지로 요약됩니다.
AGENTS.md를 단일 진실 원본으로 두고 도구별 파일은 symlink 또는 짧은 보강으로.- 정보 유형별로 1차 거주지 1곳 — 같은 문장을 두 문서에 적지 말기.
- 검증 가능한 명령어와 acceptance criteria — 에이전트는 실행해서 결과를 보는 쪽으로 자연스럽게 흐릅니다.
이 정도만 지키면, 에이전트가 만드는 결과물의 품질이 운에서 규율로 옮겨갑니다. 여러분의 다음 신규 프로젝트에서 시도해 보시면, 첫 PR 의 모양이 꽤 달라질 겁니다.
다음 새 repo 만들 때 위 체크리스트를 한 번 꺼내 보시기 바랍니다.