이번 편의 결과물: 14~16편에서 같은 로그인→등록 흐름을 세 번 다룰 때, 각 계층이 무엇을 맡을지 미리 정합니다. 코드는 바꾸지 않습니다. · 다루는 개념: 테스트 피라미드, MSW의 네트워크 레벨 모킹 철학, 계층별 검증 대상·비대상 경계
이 편에서 만드는 파일
개념 편입니다. 새로 만들거나 고치는 파일이 없습니다. 14편부터 test/, e2e/ 아래에 실제 테스트 파일을 만듭니다.
개념 정리
테스트 피라미드 — 계층마다 다루는 범위가 다르다
| 계층 | 검증 대상 | 이 과목의 도구 | 실행 속도 |
|---|---|---|---|
| 단위(unit) | 함수·훅·컴포넌트 하나의 로직 | Vitest + RTL | 빠름(밀리초) |
| 통합(integration) | 여러 컴포넌트 + 네트워크 요청이 함께 동작하는 흐름 | Vitest + RTL + MSW | 중간(초 단위) |
| E2E(end-to-end) | 실제 브라우저에서 전체 사용자 시나리오 | Playwright | 느림(초–분) |
피라미드라는 이름은 아래로 갈수록(단위) 개수를 많이 두고, 위로 갈수록(E2E) 개수를 적게 둔다는 뜻입니다. 이유는 단순합니다. E2E는 실제 브라우저를 띄우고 전체 스택을 거치기 때문에 느리고 깨지기 쉽지만, 단위 테스트는 함수 하나만 검증해 빠르고 안정적입니다.
각 계층이 검증하지 않는 것
계층을 나누는 이유는 “무엇을 볼지”뿐 아니라 “무엇을 안 볼지”를 정하는 데 있습니다.
- 단위 테스트가 안 보는 것: 실제 네트워크 요청, 여러 컴포넌트 간 상호작용, 브라우저 렌더링 전체.
useBooks훅을 테스트할 때 실제 API 서버를 띄우지 않습니다. - 통합 테스트가 안 보는 것: 실제 브라우저의 CSS 레이아웃, 실제 서버(대신 MSW가 흉내). 로그인 폼 제출 후 상태 변화는 보지만, 화면에 실제로 픽셀이 어떻게 그려지는지는 보지 않습니다.
- E2E 테스트가 안 보는 것: 내부 함수 하나하나의 모든 분기. 로그인부터 책 등록까지 “잘 되는 흐름 1개”만 확인하고, 모든 예외 케이스를 E2E로 반복하지 않습니다.
MSW는 왜 네트워크 레벨에서 목킹하는가
MSW(Mock Service Worker)는 함수를 가짜로 바꾸는 대신, 실제 네트워크 요청을 가로챕니다. 코드 입장에서는 fetch를 평소처럼 호출하고, MSW가 그 요청을 가로채 미리 정의한 응답을 돌려줍니다.
| 방식 | 코드가 아는 것 | 실제 fetch 호출 여부 |
|---|---|---|
| 함수 목(mock) | “이 함수는 가짜다”를 코드가 알아야 함 | 호출 안 함 |
| MSW(네트워크 레벨) | 평소와 똑같이 fetch 호출 | 호출은 하되 네트워크 계층에서 가로챔 |
이 방식의 장점은 테스트 코드와 실제 코드가 같은 API 호출 경로를 씁니다. 즉 테스트를 위해 컴포넌트 코드를 바꿀 필요가 없습니다. 15편에서 이 핸들러를 통합 테스트에, 16편에서는 실제 json-server/mock API로 E2E를 검증합니다.
직접 해보기
”로그인 후 책을 등록하면 목록에 반영된다”는 시나리오를 단위 테스트, 통합 테스트, E2E 테스트로 각각 어떻게 쪼갤지 한 문장씩 적어보세요.
단위: 책 등록 폼의 검증 로직이 잘못된 입력을 거부하는지. 통합: 로그인 → 폼 제출 → MSW 응답 → 목록 갱신까지 컴포넌트 조합이 맞물려 동작하는지. E2E: 실제 브라우저에서 그 전체 흐름이 사용자 눈에 보이는 화면으로 이어지는지.
자주 하는 실수
| 증상 | 원인 | 고치는 법 |
|---|---|---|
| 모든 케이스를 E2E로 작성한다 | 계층 구분 없이 “확실한” 테스트만 신뢰 | 예외 케이스는 단위·통합으로 내리고 E2E는 대표 흐름만 |
| 단위 테스트에서 실제 fetch를 호출한다 | 네트워크 목킹을 생략 | Vitest 환경에서도 MSW 서버를 켜서 요청을 가로채기 |
| 테스트가 구현 세부사항에 의존한다 | 내부 상태 변수를 직접 검사 | 사용자가 보는 결과(화면 텍스트, 역할)로 검증 |