Vitest — 단위·통합
함수·컴포넌트 수준의 빠른 테스트. 이름대로 Vite 위에 있어서(7장) 빌드 설정을 테스트가 그대로 공유한다 — 예전엔 이 설정 맞추기가 별도의 고생이었다. React 컴포넌트는 Testing Library를 얹어 “사용자가 보는 대로” 검증한다.
도구 이름은 바뀌어도 네 겹의 역할은 바뀌지 않는다
린터Linter포매터FormatterE2E 테스트End-to-End TestCIContinuous Integration각 겹은 잡는 것이 다르다 — 하나로 다른 것을 대신할 수 없다.
| 겹 | 잡는 것 | 도구 (2026 기준) | 언제 도나 |
|---|---|---|---|
| 타입 검사 | 형태가 안 맞는 코드 | tsc (--noEmit) | 에디터 상시 + CI |
| 린트 | 버그 냄새 나는 패턴 | ESLint 10, Biome, oxlint | 에디터 상시 + CI |
| 포맷 | 겉모양 불일치 | Prettier, Biome | 저장할 때 |
| 테스트 | 동작이 틀린 코드 | Vitest, Playwright | 수시 + CI |
4장에서 본 분업의 반복이다 — 빌드 도구가 타입을 벗기고, tsc는 검사만 한다.
CI에 tsc --noEmit이 없으면 타입 에러가 있는 코드도 빌드가 통과해 버린다.
프로젝트에 이 한 줄이 있는지가 타입스크립트를 “쓰는” 것과 “믿는” 것의 차이다.
eslint.config.js(flat config)가 기본이 됐고, 10에서는 .eslintrc 지원이 제거됐다어느 쪽이든 에디터의 저장 시 자동 실행(format on save)까지 붙여야 완성이다. 도구가 있는데 손으로 돌리고 있으면 절반만 쓰는 것이다.
Vitest — 단위·통합
함수·컴포넌트 수준의 빠른 테스트. 이름대로 Vite 위에 있어서(7장) 빌드 설정을 테스트가 그대로 공유한다 — 예전엔 이 설정 맞추기가 별도의 고생이었다. React 컴포넌트는 Testing Library를 얹어 “사용자가 보는 대로” 검증한다.
Playwright — E2E
진짜 브라우저로 핵심 시나리오를 통째로 검증한다. 느리고 비싸므로 수는 적게, 돈이 걸린 경로(가입·결제·핵심 플로우)에만. 이 레포가 다크 모드·확대 같은 브라우저 검증에 쓰는 도구이기도 하다.
비율의 감각만 챙기면 된다 — 빠르고 싼 테스트를 많이, 느리고 비싼 테스트를 조금. 그 반대가 되면 CI가 느려지고 테스트가 미움받기 시작한다.
네 겹이 다 있어도 로컬에서만 돌면 없는 것과 같다. 잊는 사람이 반드시 생기기 때문이다. GitHub Actions 기준으로 뼈대는 이 정도다 —
# .github/workflows/ci.yml — 핵심만on: [pull_request]jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: pnpm install --frozen-lockfile # 잠금 파일과 다르면 실패 (5장) - run: pnpm exec tsc --noEmit # 타입 - run: pnpm lint # 린트 (+포맷 검사) - run: pnpm test # 테스트 - run: pnpm build # 빌드 자체도 검사다전부 갖추는 게 항상 옳은 건 아니다 — 단계별 최소선은 이 정도다.
| 단계 | 최소선 |
|---|---|
| 혼자 실험 | TypeScript + 포매터. 이 둘은 공짜나 다름없다 |
| 혼자 운영 | + 린트, CI에서 tsc·빌드. 미래의 나는 남이다 |
| 둘 이상 | + 테스트(핵심 로직부터), PR마다 CI 필수화 |
| 돈이 걸림 | + E2E(결제·가입 경로), 커버리지보다 경로를 본다 |