이번 편의 결과물: expense-tracker가 최신 버전으로 npm run dev가 정상 동작하고, MSW가 브라우저에서 활성화되었다는 로그가 콘솔에 출력됩니다. · 다루는 개념: Node 22.23/Vite 8.3/TypeScript 7.0.2/Vitest 5.0.1로 버전 확인, lib/types·lib/api·schemas 폴더 준비, MSW 2.15 설치와 빈 목업 서버 기동
이 편에서 만드는 파일
expense-tracker/
├── package.json ~ (devDependencies 버전 업, msw 추가, msw.workerDirectory 필드)
├── public/
│ └── mockServiceWorker.js + (npx msw init으로 생성)
└── src/
├── main.ts ~ (MSW 워커 시작 코드 추가)
├── mocks/
│ ├── browser.ts + (setupWorker)
│ └── handlers.ts + (빈 handlers 배열, 15편에서 채움)
├── lib/
│ ├── types/ + (빈 폴더, 03편부터 채움)
│ └── api/ + (빈 폴더, 04편부터 채움)
└── schemas/ + (빈 폴더, 13편부터 채움)개념 정리
버전을 확정하는 이유
01편에서 확인했듯 지금 expense-tracker는 TypeScript 7.0.0대, Vite 8.0.0대로 시작됐습니다. 이 과목은 조건부 타입·매핑된 타입처럼 컴파일러 동작에 민감한 문법을 다루므로, 실습 중간에 버전이 달라 결과가 다르게 나오는 일을 막기 위해 시작 시점에 패치 버전까지 고정합니다.
| 도구 | 버전 | 확인 명령 |
|---|---|---|
| Node.js | 22.23.3(LTS) | node -v |
| TypeScript | 7.0.2 | npx tsc --version |
| Vite | 8.3.0 | npm ls vite |
| Vitest | 5.0.1 | npm ls vitest |
MSW(Mock Service Worker)가 하는 일
이번 과목은 실제 백엔드 서버를 만들지 않습니다. 대신 MSW가 브라우저의 서비스 워커로 네트워크 요청을 가로채, 미리 정해둔 목업 응답을 대신 돌려줍니다. 앱 코드 입장에서는 진짜 서버에 fetch를 보내는 것과 동일하게 동작하므로, 15편에서 API 클라이언트를 완성할 때까지 백엔드 없이도 실제 네트워크 흐름을 그대로 연습할 수 있습니다.
MSW는 브라우저용 설정(setupWorker)과 Node.js 테스트용 설정(setupServer)을 따로 제공합니다. 이 과목은 브라우저에서 직접 확인하는 실습이 많으므로 msw/browser의 setupWorker를 씁니다.
미리 만들어두는 빈 폴더
lib/types, lib/api, schemas는 이번 과목 전체에서 채워 나갈 결과물의 뼈대입니다. 폴더만 먼저 만들어 두면 각 편에서 어떤 파일이 어느 폴더에 들어가는지 헷갈리지 않습니다. 지금은 안에 파일을 두지 않고, 03·04·13편에서 순서대로 채웁니다.
실습
1. Node 버전 확인
node -vv22.23.3보다 낮다면 nodejs.org 에서 22 LTS 최신 패치를 다시 설치합니다.
2. 핵심 패키지 버전 고정
npm install -D typescript@7.0.2 vite@8.3.0 vitest@5.0.1 @vitest/coverage-v8@5.0.1// expense-tracker/package.json (발췌)
{
"devDependencies": {
"@vitest/coverage-v8": "^5.0.1",
"jsdom": "^25.0.0",
"typescript": "~7.0.2",
"vite": "^8.3.0",
"vitest": "^5.0.1"
}
}3. MSW 설치와 초기화
npm install -D msw@2.15.0
npx msw init public --saveINFO Setting up mocking for the browser environment.
INFO Writing "mockServiceWorker.js"...
INFO Successfully wrote "mockServiceWorker.js"...msw init은 브라우저가 요청을 가로채는 데 필요한 public/mockServiceWorker.js를 만들고, --save가 그 위치를 package.json의 msw.workerDirectory 필드에 기록합니다.
4. 목업 서버 진입점 작성
// expense-tracker/src/mocks/handlers.ts
export const handlers = []지금은 가로챌 요청이 없어 빈 배열입니다. /api/transactions CRUD 핸들러는 15편에서 이 파일에 채웁니다.
// expense-tracker/src/mocks/browser.ts
import { setupWorker } from 'msw/browser'
import { handlers } from './handlers.ts'
export const worker = setupWorker(...handlers)5. main.ts에 워커 시작 코드 연결
// expense-tracker/src/main.ts (맨 위에 추가되는 부분만, 이하 로직은 16편과 동일)
import { worker } from './mocks/browser.ts'
if (import.meta.env.DEV) {
void worker.start({ onUnhandledRequest: 'bypass' })
}import.meta.env.DEV는 Vite가 개발 서버에서만 참이 되도록 주입하는 값이라, 프로덕션 빌드에는 목업 코드가 실행되지 않습니다. onUnhandledRequest: 'bypass'는 핸들러가 없는 요청(지금은 전부)을 가로채지 않고 그대로 통과시키라는 옵션입니다. void는 worker.start()가 반환하는 프라미스를 의도적으로 기다리지 않는다는 표시입니다.
6. 새 폴더 준비
mkdir -p src/lib/types src/lib/api src/schemas이 폴더들은 지금 비어 있습니다. 빈 폴더는 git에 올라가지 않으므로, 03·04·13편에서 첫 파일을 넣을 때 폴더도 함께 생깁니다.
7. 실행과 확인
npm run dev확인
- 브라우저 콘솔에
[MSW] Mocking enabled.가 출력된다. - 개발자 도구의 애플리케이션 탭에서 등록된 서비스 워커 목록에
mockServiceWorker.js가 보인다. npx tsc --version이Version 7.0.2를 출력한다.npm run verify가 여전히 통과한다(핸들러가 비어 있어 기존 기능에는 영향이 없다).
직접 해보기
worker.start()의 옵션을{ onUnhandledRequest: 'warn' }으로 바꿔보고, 앱이 시작될 때 콘솔에 어떤 경고가 추가로 뜨는지 확인한 뒤'bypass'로 되돌립니다.package.json을 열어msw init --save가 추가한msw.workerDirectory필드를 찾아봅니다.
정답 보기
1번은 mountStatsPanel, mountTransactionForm 등에서 아직 실제 네트워크 요청을 보내지 않으므로 당장은 경고가 뜨지 않을 수 있습니다. 15편에서 API 클라이언트가 fetch를 실제로 호출하기 시작하면, 핸들러가 없는 요청마다 warn 옵션이 콘솔에 경고를 남기는 차이가 드러납니다.
2번은 { "msw": { "workerDirectory": ["public"] } } 형태로 추가되어 있습니다. MSW가 다음에 mockServiceWorker.js를 갱신할 위치를 기억해두는 설정입니다.
자주 하는 실수
| 증상 | 원인 | 고치는 법 |
|---|---|---|
| 콘솔에 mockServiceWorker.js를 찾을 수 없다는 오류 | npx msw init public --save를 건너뜀 | 초기화 명령을 다시 실행해 public/mockServiceWorker.js를 생성한다 |
| 프로덕션 빌드에도 목업 코드가 실행됨 | import.meta.env.DEV 조건을 빠뜨림 | 워커 시작 코드를 반드시 if (import.meta.env.DEV) 안에 둔다 |
| npm run build에서 typescript 버전 관련 경고 | package.json과 실제 설치된 버전이 어긋남 | npm install을 다시 실행해 lock 파일과 버전을 맞춘다 |