# Vitest로 TDD 개발 환경 구축하기

## 들어가며

테스트는 이제 “하면 좋은 것”이 아니라  
**안 하면 불안한 것**이 되었습니다.

하지만 여전히 많은 개발자들이 이렇게 느낍니다.

* TDD는 이상적인데, 현실에서는 너무 느린 것 같다
    
* Jest 설정은 점점 복잡해진다
    
* Rollup 라이브러리에서는 테스트를 어디까지 해야 할지 모르겠다
    

이 글에서는 이런 고민을 전제로,

> **Vitest를 이용해 “현실적으로 돌아가는 TDD 개발 환경”을 구축하는 방법**

을 **Rollup 기반 TypeScript 라이브러리** 기준으로 정리합니다.

---

## 1\. 요즘에도 TDD는 쓰일까?

결론부터 말하면:

> **TDD의 “철학”은 여전히 유효하지만,  
> 순수한 형태의 TDD만 고집하는 팀은 줄어들고 있다.**

### 과거의 TDD

* Red → Green → Refactor를 엄격히 반복
    
* 단위 테스트 중심
    
* 개발자 개인의 설계 도구
    

### 현재의 TDD

* 테스트를 **설계의 기준**으로 사용
    
* 단위 테스트 + 통합 테스트를 상황에 맞게 조합
    
* CI/CD와 결합된 **안전망 역할**
    

즉,  
**TDD는 사라진 것이 아니라 “확장된 테스트 전략의 일부”가 되었습니다.**

---

## 2\. TDD / BDD / ATDD, 무엇이 다른가?

테스트 기반 개발 방식은 하나가 아닙니다.

| 구분 | TDD | BDD | ATDD |
| --- | --- | --- | --- |
| 중심 질문 | 이 코드는 어떻게 동작해야 하는가? | 사용자는 어떻게 행동하는가? | 언제 이 기능이 완료되었다고 말할 수 있는가? |
| 관점 | 코드/함수 | 행동/시나리오 | 요구사항/비즈니스 |
| 주 사용 주체 | 개발자 | 개발자 + 기획 | 개발자 + 기획 + QA |
| 주 사용 레벨 | 단위 테스트 | 통합/행위 테스트 | 인수/릴리즈 기준 |

요즘 실무에서 가장 흔한 패턴은 다음과 같습니다.

```typescript
핵심 로직 → TDD
유스케이스 → BDD 스타일 테스트
릴리즈 기준 → ATDD 일부 적용
```

이 글에서는 그중에서도  
**라이브러리 개발에 가장 적합한 TDD**에 집중합니다.

---

## 3\. 테스트 환경을 구축했을 때의 진짜 장점

테스트의 가장 큰 가치는  
“버그를 잡는다”가 아닙니다.

### 1️⃣ 리팩토링이 가능해진다

* 테스트는 **안전망**
    
* 내부 구현을 바꿔도 외부 동작을 고정할 수 있음
    

### 2️⃣ 버그를 조기에 차단한다

* 로컬/CI 단계에서 실패
    
* 운영 장애 비용 급감
    

### 3️⃣ 코드가 문서가 된다

```ts
it('returns normalized user object', () => {
  expect(parseUser(input)).toEqual({...});
});
```

테스트는 **실행 가능한 스펙**입니다.

### 4️⃣ 협업과 리뷰가 쉬워진다

* “이 코드의 의도가 무엇인지”를 테스트로 설명 가능
    
* 리뷰가 구현이 아닌 **설계 중심**으로 이동
    

---

## 4\. 왜 요즘은 Jest보다 Vitest인가?

Vitest가 선호되는 이유는 단순합니다.

### ✅ 빠르다

* Vite 기반
    
* watch 모드에서 즉각적인 피드백
    

### ✅ ESM/TypeScript 친화적

* 별도의 복잡한 트랜스폼 설정이 거의 없음
    
* Rollup/Vite 프로젝트와 설정 공유 가능
    

### ✅ TDD에 최적화된 개발 경험

* `vitest --watch` 기본 루프
    
* Jest와 거의 동일한 API (`expect`, `mock`, `spy`)
    

즉,

> **“요즘 프론트엔드 빌드 환경에 맞게 다시 설계된 테스트 러너”**

가 Vitest입니다.

---

## 5\. Rollup 라이브러리에서의 테스트 원칙

이 글의 가장 중요한 전제입니다.

### ❌ 잘못된 접근

* `dist` 결과물을 테스트
    
* Rollup 설정에 테스트 로직을 포함
    

### ✅ 올바른 접근

* **테스트는 항상** `src` 기준
    
* Rollup은 빌드 전용
    
* 테스트와 빌드는 책임 분리
    

> 라이브러리 테스트의 목적은  
> **“번들이 잘 나오는지”가 아니라  
> “공개 API가 의도대로 동작하는지”** 입니다.

---

## 6\. Vitest + Rollup 기반 TDD 환경 구축

### 6-1. 디렉토리 구조

```txt
my-lib/
├─ src/
│  ├─ index.ts
│  └─ sum.ts
├─ test/
│  └─ sum.test.ts
├─ rollup.config.mjs
├─ vitest.config.ts
├─ tsconfig.json
├─ tsconfig.build.json
├─ tsconfig.test.json
└─ package.json
```

---

### 6-2. TypeScript 설정 분리

#### [`tsconfig.build`](http://tsconfig.build)`.json` (빌드용)

```json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "rootDir": "src",
    "declaration": true,
    "sourceMap": true
  },
  "include": ["src"]
}
```

#### `tsconfig.test.json` (테스트용)

```json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "noEmit": true,
    "types": ["vitest/globals", "node"]
  },
  "include": ["src", "test"]
}
```

---

### 6-3. Vitest 설정

```ts
// vitest.config.ts
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    environment: "node",
    globals: true,
    include: ["test/**/*.test.ts"],
    clearMocks: true,
    restoreMocks: true
  }
});
```

---

### 6-4. Rollup 설정 (빌드 전용)

```js
// rollup.config.mjs
import typescript from "@rollup/plugin-typescript";

export default {
  input: "src/index.ts",
  output: [
    { file: "dist/index.esm.js", format: "esm", sourcemap: true },
    { file: "dist/index.cjs.js", format: "cjs", sourcemap: true }
  ],
  plugins: [
    typescript({ tsconfig: "./tsconfig.build.json" })
  ]
};
```

---

### 6-5. package.json 스크립트

```json
{
  "scripts": {
    "dev:test": "vitest",
    "test": "vitest run",
    "typecheck": "tsc -p tsconfig.test.json",
    "build": "rollup -c",
    "prepublishOnly": "npm run typecheck && npm run test && npm run build"
  }
}
```

이제 개발 중에는:

```bash
npm run dev:test
```

→ **Red / Green / Refactor 루프가 즉시 돌아갑니다.**

---

## 7\. “진짜 TDD답게” 사용하는 운영 팁

* watch 모드는 항상 켜두기
    
* 테스트는 구현이 아닌 **행동/계약을 고정**
    
* 외부 의존(시간, 랜덤, 네트워크)은 mock으로 통제
    
* 커버리지는 목표가 아니라 **빈 구간을 찾는 도구**
    

---

## 마치며

Vitest로 TDD 환경을 구축한다는 것은  
단순히 테스트 러너를 바꾸는 문제가 아닙니다.

> **“코드를 바꿔도 괜찮은 상태”를 만드는 일**입니다.

Rollup 기반 라이브러리 개발에서  
Vitest + TDD 조합은 다음을 가능하게 합니다.

* 자신 있는 리팩토링
    
* 안정적인 공개 API
    
* CI/CD 자동화의 기반
    
* 협업 가능한 코드베이스
    

---

## **🧾 작성 참고**

***이 글은 ChatGPT의 도움을 받아 내용을 정리하였습니다.***
