
| 순서 | 제목 | 내용 |
|---|---|---|
| 1편 | Claude Code Commands로 개발 워크플로우 자동화하기 | 전체 개요 |
| 2편 | /spec - 명세서 기반 코드 구현 자동화 | 가장 핵심인 구현 자동화 |
| 3편 | /create-jest - 테스트 코드 자동 생성 | 테스트 작성 자동화 (현재 글) |
| 4편 | /w-context - AI를 위한 문서 작성 | CONTEXT.md 개념과 활용 |
| 5편 | /pr + /apply-review - PR 워크플로우 자동화 | PR 생성부터 리뷰 반영까지 |
테스트 코드, 좋은 건 알아요.
근데 현실은 대개 이렇죠.
저도 똑같았습니다. 테스트가 필요 없는 게 아니라, 테스트를 쓰는 데 드는 에너지가 문제였어요.
그래서 만든 게 /create-jest입니다.
“코드 바꾸면 → 테스트가 따라온다”
라는 규칙을 고민이 아니라 시스템으로 강제해버린 명령어.
/create-jest가 하는 일 (진짜로는 “테스트 파이프라인”)실행은 한 줄입니다.
/create-jest
하지만 내부적으로는 아래를 순서대로 처리해요.
git diff로 무엇이 바뀌었는지 확인즉, “테스트 파일 만들어드립니다”가 아니라
코드 수정 →
/create-jest→ 테스트까지 끝
이 흐름을 만드는 게 목표였습니다.
테스트 자동화를 시도할 때 제일 먼저 부딪히는 문제가 이거예요.
그래서 저는 “테스트할 것 / 안 할 것”을 명확히 분리했습니다.
- `libs/**/*.ts` - 공통 라이브러리
- `hooks/**/*.ts` - 커스텀 훅
- `utils/**/*.ts` - 유틸리티 함수
- `services/**/*.ts` - 서비스 레이어
이 영역들은 보통 순수 로직이 많고, 테스트 비용 대비 효과가 커요.
즉 “자동 생성”과 궁합이 좋습니다.
- `app/**/*` - 앱 라우터 (E2E로 커버)
- `components/**/*` - React 컴포넌트 (별도 컴포넌트 테스트)
- `**/*.d.ts` - 타입 정의 파일
- `**/index.ts` - re-export만 하는 파일
- `**/__tests__/**` - 테스트 파일 자체
- `*.config.*` - 설정 파일
UI/라우팅은 단위 테스트로 무리해서 커버하기보다, E2E나 컴포넌트 테스트 전략이 더 적합하다고 판단했어요.
그래서 /create-jest는 “로직 구역”만 확실히 쌓아주는 역할을 맡습니다.
테스트가 자동으로 생기기 시작하면, 다음 문제가 옵니다.
“어디에 생겼더라?”
“왜 어떤 건 여기 있고 어떤 건 저기 있어?”
그래서 무조건 같은 규칙으로 생성하도록 했어요.
__tests__ 폴더libs/fetch/
├── core.ts
├── types.ts
├── index.ts
└── __tests__/
└── fetch.test.ts
소스랑 같은 위치에 있으니 찾기 쉽고, 모듈 단위로 묶여서 관리도 편합니다.
| 모듈 크기 | 파일 수 | 네이밍 | 예시 |
|---|---|---|---|
| 작음 | 1~3개 | {모듈명}.test.ts | fetch.test.ts |
| 큼 | 4개 이상 | {파일명}.test.ts | session.test.ts |
작은 모듈은 통합 테스트 파일 하나가 관리가 쉽고,
큰 모듈은 파일 단위로 쪼개야 유지보수가 됩니다.
여기가 /create-jest의 진짜 핵심이에요.
테스트를 못 쓰는 이유는 보통 “시간”보다도
매번 선택해야 하는 것들이 너무 많아서예요.
그래서 저는 그 선택을 명령어가 대신 하도록 만들었습니다.
it("사용자를 생성한다", () => {});
it("유효하지 않은 이메일이면 에러를 던진다", () => {});
한글 테스트명의 장점은 단순해요.
테스트는 “작성자”보다 “미래의 유지보수자”를 위한 거라서, 저는 한글이 더 실용적이었습니다.
it("정상 케이스를 처리한다", () => {
// Arrange
const input = { name: "홍길동", email: "hong@test.com" };
// Act
const result = createUser(input);
// Assert
expect(result).toEqual({ id: expect.any(String), ...input });
});
AAA(Arrange-Act-Assert)를 강제하면 좋은 점:
describe("UserService", () => {
describe("createUser", () => {
it("정상 케이스를 처리한다", () => {});
it("중복 이메일이면 에러를 던진다", () => {});
});
describe("updateUser", () => {
it("존재하는 사용자를 업데이트한다", () => {});
it("존재하지 않는 사용자면 에러를 던진다", () => {});
});
});
이 구조는 테스트가 많아질수록 효과가 커집니다.
특히 CI에서 실패했을 때 “어느 기능이 문제인지”가 바로 찍혀요.
Claude가 테스트를 생성할 때 저는 우선순위를 고정했습니다.
이렇게 하면 최소한
자동 생성 테스트가 “쓸모없는 테스트”가 되지 않게 만드는 장치예요.
테스트가 깨지기 쉬운 가장 흔한 원인이 과도한 모킹이더라고요.
내부 구현을 잔뜩 mock 해버리면, 코드가 조금만 바뀌어도 테스트가 와르르 깨집니다.
그래서 /create-jest는 원칙이 단순합니다.
// ✅ Good: 외부 의존성만 모킹
const mockFetch = jest.fn();
global.fetch = mockFetch;
// ❌ Bad: 내부 구현을 과하게 모킹
jest.mock("./internal-helper");
이렇게 하면 테스트가 “구현 디테일”에 덜 묶여서 유지보수가 쉬워집니다.
자동화의 또 다른 함정은 이거예요.
“테스트 새로 만들어줬는데… 기존 테스트 스타일이랑 완전 다르네?”
그래서 변경된 파일에 테스트가 이미 있으면 /create-jest는 이렇게 행동합니다.
즉, 전체를 다시 쓰지 않고 변경분만 안전하게 다룹니다.
(이게 안 되면 팀 프로젝트에서 바로 반발 나옵니다…)
예를 들어 libs/api/client.ts에 재시도 로직을 추가했다고 해볼게요.
# 1) 코드 수정 후 변경 파일 확인
git diff --name-only
# libs/api/client.ts
# 2) 테스트 생성/업데이트
/create-jest
그러면 결과는 이런 식으로 요약됩니다.
## 테스트 작성 완료
### 업데이트된 테스트
- libs/api/__tests__/client.test.ts
### 테스트 결과
✓ 12 tests passed
✗ 0 tests failed
### 주요 테스트 케이스
- apiFetch: GET/POST, 재시도, 에러 처리 등
- createApiClient: 인스턴스 생성, baseURL 설정 등
중요한 건 “파일 하나 늘어났네요”가 아니라,
변경한 로직(재시도)이 테스트 케이스로 바로 박제된다는 점입니다.
/spec과 같이 쓰면 “명세→구현→테스트”가 두 줄로 끝난다2편에서 다룬 /spec과 붙이면 흐름이 깔끔해져요.
/spec user-auth
/create-jest
/spec: 명세서 기반 구현 + 검증/create-jest: 변경 기반 테스트 생성 + 실행이렇게 하면 “테스트를 쓰는 사람”이 아니라,
테스트가 기본으로 따라오는 구조가 됩니다.
테스트가 선택이 아니라 루틴이 됩니다.
루틴이 되면 지속됩니다.
한글 테스트명, AAA, describe 구조…
팀원마다 다르게 쓰던 테스트가 “명령어 규칙”으로 정렬됩니다.
PR에 테스트가 항상 포함되니,
“테스트는요?”라는 질문 자체가 줄어듭니다.
수정할 때마다 테스트가 업데이트되니까,
어느 순간부터는 “테스트가 나를 지켜주는 순간”이 오더라고요.
/create-jest 명령어는 결국 규칙을 마크다운으로 적어둔 것입니다.
# create-jest.md
변경된 파일에 대한 테스트 코드를 생성하거나 업데이트합니다.
## 실행 절차
1. git diff로 변경된 파일 목록 확인
2. 테스트 대상 파일 필터링
3. 기존 테스트 여부에 따라 생성 또는 업데이트
4. 테스트 실행하여 통과 확인
## 테스트 대상 규칙
### 포함
- libs/**/*.ts
- hooks/**/*.ts
- utils/**/*.ts
- services/**/*.ts
### 제외
- app/**/*
- components/**/*
- **/*.d.ts
- **/index.ts
- **/__tests__/**
- *.config.*
## 테스트 작성 규칙
1. 한글 테스트명
2. describe 구조화
3. AAA 패턴
4. 모킹은 외부 의존성만
이렇게 “팀 룰”을 문서로 남기면, Claude는 그걸 매번 일관되게 따라줍니다.
- src/domain/**/*.ts
- src/application/**/*.ts
*.test.ts 생성tests/에 동일 폴더 구조로 생성/create-jest의 핵심은 한 문장입니다.
테스트 작성을 “의지”에서 “시스템”으로 옮기는 것.
완벽하진 않아요.
하지만 테스트 0개보다
자동 생성된 테스트 10개 + 중요한 곳 수동 보완 2개가 훨씬 낫잖아요.
다음 4편에서는 /w-context를 다룹니다.
AI가 코드를 더 잘 이해하도록 CONTEXT.md를 자동 생성하는 흐름이에요.
이 글에서 소개한 명령어들은 제가 만들고 있는 Link Dropper 프로젝트에서 실제로 사용하고 있습니다.