콘텐츠로 이동

3. 게이트 먼저

터미널 창
ls docs/plans/*-charcount.md && git status --short

두 번째 명령은 아무것도 찍히지 않아야 합니다. 1단계에서 스캐폴딩과 스펙·기록표를, 2단계에서 계획을 각각 커밋해 두었기 때문입니다. 계획 파일이 없거나 트리가 깨끗하지 않으면 2. 계획을 파일로로 돌아갑니다.

의존성을 설치하고, 게이트 설정은 Prompt 2번 틀로 시킵니다. 게이트마다 일부러 어긋나게 해서 실패를 먼저 봅니다. 실패를 먼저 보는 이유는 Lint와 Build가 다룹니다.

  1. 템플릿 의존성과 게이트용 개발 의존성을 설치합니다.
터미널 창
npm install
npm install --save-dev vitest jsdom eslint @eslint/js typescript-eslint @playwright/test
npx playwright install chromium
  1. worktree 디렉터리와 Playwright 산출물을 먼저 무시합니다. worktree는 7단계에서 필요합니다. Playwright는 실행마다 test-results/를 다시 쓰므로, 무시하지 않으면 뒤 단계의 git add -A가 이 파일을 커밋하고 다음 시작 상태의 깨끗한 트리 요구를 흔듭니다. 첫 줄은 나의 기본 세팅의 것과 같습니다. Vite 템플릿의 .gitignore가 이미 있으므로 덧붙입니다.
터미널 창
printf '\n.claude/worktrees/\ntest-results/\nplaywright-report/\n' >> .gitignore
git check-ignore -v .claude/worktrees/ test-results/

두 경로 모두 .gitignore의 규칙과 함께 출력되어야 합니다.

  1. 게이트 설정 프롬프트(2번 틀):
lint, 단위 테스트, 빌드, e2e 네 가지 게이트를 설정해 주세요.
완료 기준: npm run lint, npm test, npm run build, npm run e2e 네 명령이 모두 exit 0.
"동작하게"로 쓰지 않습니다.
범위: 포함 — eslint flat config(@eslint/js + typescript-eslint), vitest(environment jsdom,
exclude에 **/.claude/worktrees/** 와 **/e2e/** 포함), playwright(testDir e2e, webServer로
npm run dev), package.json scripts, jsdom 환경과 HTTP 문서 응답을 확인하는 최소
smoke test 각 하나.
제외 — 앱 기능 구현과 기능 테스트. smoke test는 유지하고 테스트가 없을 때 통과시키는
옵션은 쓰지 않습니다.
구현 전에 만들 파일과 고칠 파일 목록을 먼저 보여 주세요.
각 게이트를 설정한 뒤에는 일부러 어긋난 파일을 하나 만들어 그 게이트가 exit 0이 아닌
값을 내는 것을 보여 주고, 그 파일을 지운 뒤 exit 0을 다시 보여 주세요.
  1. 모델이 보여 준 실패와 복원 후 초록을 믿지 말고 직접 한 번 더 합니다. smoke test는 남긴 상태에서 다음 네 실패와 복원 후 성공을 확인합니다.
터미널 창
echo 'export const unused = 1; const dead = 2;' > src/dead.ts && npm run lint; echo "lint exit=$?"; rm src/dead.ts
echo 'import { test, expect } from "vitest"; test("red", () => { expect(1).toBe(2); });' > src/red.test.ts && npm test; echo "test exit=$?"; rm src/red.test.ts
echo 'const broken: number = "not a number"; export { broken };' > src/build-red.ts
npm run build; echo "build exit=$?"
rm src/build-red.ts
echo 'import { test, expect } from "@playwright/test"; test("red", async ({ page }) => { await page.goto("/"); await expect(page.locator("#nope")).toBeVisible({ timeout: 1000 }); });' > e2e/red.spec.ts
npm run e2e; echo "e2e exit=$?"
rm e2e/red.spec.ts
npm run lint && npm test && npm run build && npm run e2e; echo "green exit=$?"

네 실패 모두 exit 0이 아닌 값을 냅니다. 모델이 생성한 설정이 대략 다음 형태입니다. 프롬프트가 다른 형태를 내면 이 형태로 맞춰 봅니다.

vite.config.ts
/// <reference types="vitest/config" />
import { defineConfig } from 'vite';
export default defineConfig({
test: {
environment: 'jsdom',
exclude: ['**/node_modules/**', '**/.claude/worktrees/**', '**/e2e/**'],
},
});
eslint.config.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
{ ignores: ['dist/**', 'node_modules/**', '.claude/**', 'playwright-report/**', 'test-results/**'] },
js.configs.recommended,
...tseslint.configs.recommended,
);
playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './e2e',
use: { baseURL: 'http://localhost:5173', viewport: { width: 1280, height: 720 } },
webServer: { command: 'npm run dev', url: 'http://localhost:5173', reuseExistingServer: true },
});
"scripts": {
"lint": "eslint .",
"test": "vitest run",
"e2e": "playwright test"
}
  1. 프로젝트 CLAUDE.md를 만듭니다. 검증 명령을 적어 두면 이후 세션이 “완료”라고 말하기 전에 무엇을 돌릴지 압니다. 이 규칙이 강제가 아니라 조언이라는 점은 CLAUDE.md 실전 가이드가 다룹니다. 6단계에서 그 규칙이 지켜지지 않는 경우를 겪습니다.
# charcount
- 변경을 마치면 npm run lint && npm test && npm run build 를 실행하고 출력을 보여준다
- 화면 변경은 npm run e2e 도 실행한다
- 글자 수 계산은 src/countChars.ts 의 순수 함수 하나에만 둔다
- push는 사람이 한다. 커밋까지만 한다
  1. 끝 비용과 컨텍스트 사용률을 읽어 docs/tutorial-log.md의 “3. 게이트” 행에 적습니다. 메모 열에는 “모델이 보여 준 실패를 직접 재현했는가”를 적습니다.

  2. 네 게이트가 초록이면 기록표까지 함께 커밋하고 이후 리뷰의 기준점을 보존합니다. git add -A가 기록표를 함께 담습니다.

터미널 창
git add -A && git commit -m "chore: 게이트 설정"
git tag tutorial-gates
git rev-parse tutorial-gates

이 태그는 8단계 리뷰의 기준점입니다. 이후 단계에서 옮기지 않습니다. 태그가 이미 있다면 덮어쓰지 말고 올바른 3단계 완료 커밋을 가리키는지 확인합니다.

터미널 창
npm run lint && npm test && npm run build && npm run e2e; echo "green exit=$?"

green exit=0이어야 합니다. 그리고 4번에서 본 네 실패는 exit 0이 아닌 값이었습니다.

값은 6번에서 이미 적었습니다. 시작 상태를 확인한 직후 시작 비용을, 커밋 직전에 끝 비용과 컨텍스트 사용률을 각각 적고 차액으로 읽습니다. 세션 수는 이 단계에서 연 세션 개수입니다. 기록표를 커밋한 뒤 /clear해 4단계를 새 세션으로 시작합니다.

새 게이트가 처음부터 초록이면 그 게이트가 아무것도 검사하지 않는지 의심합니다. 판정 기준은 검사는 통과하는데 실제로는 깨져 있을 때에 있습니다. npm test가 테스트 파일이 없다고 실패하면 smoke test 파일 경로와 vitest의 수집 설정을 확인합니다. .claude/ 전체를 무시하면 안 됩니다. 이유는 나의 기본 세팅에 있습니다.