"'테스트 충분해?' 물지 마. '이거 테스트 값어치해?' 물어. 케이스당 하나."
실제로 작동하는 frame
'테스트 충분해?' 는 답 불가. 어딘가에서 ONE 테스트 더 있었으면 잡혔을 regression 이 항상 있어. 모든 미팅과 코드 리뷰에서 작동하는 frame 은 per-thing: 이거 테스트 값어치해? 두 요인:
- Cost of failure — 이게 깨지면 얼마 들어? 너의 시간? 사용자의 시간? 돈? 신뢰? 대략 정량화.
- Cost of the test — 짜는 데 얼마 걸려? 돌리는 데 얼마 걸려? 얼마나 자주 업데이트해야 해?
높은 cost-of-failure + 낮은 cost-of-test = 명백한 yes. 낮은 + 높은 = 명백한 no. 중간 모든 거 판단 — 명시적 framing 이 판단을 방어 가능하게 만들어.
Unit / Integration / E2E 스펙트럼, 다시 가격 매김
각 레이어가 다른 비용 특성:
- Unit (Vitest) — 짜기 쌈 (~5분), 돌리기 쌈 (~30ms), 깨지면 좁은 blast radius (함수 하나). 최적: 순수 로직, edge case, '입력 X 가 출력 Y 산출' 표현 가능한 거.
- Integration (Vitest + MSW + RTL) — 중간 비용 (짜는 데 ~15분, 돌리는 데 ~500ms), 중간 blast radius. 최적: mock 된 API 와 컴포넌트 인터랙션, 라우트 핸들러, multi-step 흐름.
- E2E (Playwright) — 비쌈 (안정적인 거 짜는 데 ~30분, 돌리는 데 ~5초, 유지 brittle), 넓은 blast radius. 최적: critical 사용자 여정 — 가입, 결제, 결제, 레이어 사이 seam 깨지면 진짜 돈이나 신뢰 비용 드는 거.
'이거 테스트 하지 마' 케이스
똑같이 중요: 뭘 테스트 하지 말지 알기. 흔한 후보:
- 프레임워크 코드. React 가 네가 넘긴 prop 렌더했어; 이건 React 테스트, 너의 거 아냐.
- 사소한 getter / setter. 테스트가 코드보다 길어.
- 순수 자료구조. Const 배열은 테스트 필요 없어.
- 장식적 스타일링. 디자이너가 padding 미세 조정할 때마다 테스트 업데이트 필요하면, 테스트가 동작 아니라 구현을 테스트하는 거.
- 지워지고 있는 코드. 죽어가는 거에 테스트 투자할 가치 없음.
'이거 테스트해야 해?' 는 '이거 문서화해야 해?' 와 같은 답 가짐 — 보통 no, 가끔 yes, 기준 비슷. 둘 다 future-you 에게 serve. 둘 다 지속 유지 비용. 둘 다 잘못된 이유로 쓰면 실패 ('docs 있어야 해' / '테스트 있어야 해' 가 둘 다의 사형 선고).
'E2E 추가할 때' 트리거
대부분 프로젝트는 첫날 E2E 필요 없어. 이 트리거 중 하나 발동할 때 E2E 테스트 추가:
- 실제 브라우저 테스트만 잡았을 버그가 프로덕션에 도달.
- Critical 흐름 (auth, 결제) 가 refactor 됨 — 숨 안 참고 refactor 할 수 있게 E2E 먼저 짜.
- 여러 팀이 같은 surface 에 ship 하고 integration regression 이 주간으로 침.
- 제품이 유료 고객 가지고 regression 비용이 진짜 돈이 됨.
이 중 어느 것도 참 아니면 너의 테스트 예산은 unit + integration 에 더 잘 쓰여. 선제적으로 추가된 E2E 는 아무도 안 돌리는 유지 부채가 돼.
리소스로서의 테스트 예산
테스팅에 쓸 수 있는 주의력이 유한해. 예산 포함: 짜는 시간, 유지 시간, CI 분, 실패 읽을 때 정신적 부하. Suite 가 예산 터질 때까지 자라게 두는 대신 suite 를 예산에 맞게 사이즈 — 그게 시니어 엔지니어 움직임. Pyramid (또는 trophy, 뭐든) 는 예산 할당 사고 위한 TOOL. 처방이 아냐.