Hook
CI 파이프라인이 15분 걸립니다. 그중 12분은 E2E 테스트입니다. 그리고 30%는 랜덤하게 실패합니다. “이 실패가 진짜 버그인가, 아니면 타이밍 이슈인가?” 매 PR마다 이 질문을 던집니다.
전통적 E2E 우선 테스트는 AI 주도 개발에서 더 심각합니다 — AI가 만든 코드가 많을수록 검증해야 할 것이 많아지는데, 느린 E2E가 병목이 되기 때문입니다. 이 글에서는 바텀업 레이어드 테스팅으로 이 문제를 해결한 방법을 공유합니다.
TL;DR
- E2E 우선 접근은 느리고 불안정합니다 — flaky 30%, CI 차단 빈번
- 4계층 바텀업: Unit → Component → Contract → E2E Smoke (3~10개만)
- 컨트랙트 테스트가 통합 테스트를 대체 — 실제 API 호출 없이 데이터 모양 검증
- CDC (Consumer-Driven Contracts) 로 컴포넌트와 API가 동일 스키마 검증
Background: 왜 E2E 우선이 실패하는가
전통적 접근의 문제
전통적 테스트 피라미드:
E2E (많음) ← 느림, 불안정, CI 차단
/ \
/ \
/ 통합 테스트 \ ← DB/API 의존, 환경 민감
/______________\
/ Unit (적음) \ ← 빠르지만 커버리지 낮음
/__________________\
| E2E 문제 | 영향 |
|---|---|
| 느림 | 전체 suite 5~15분 → PR 피드백 지연 |
| 불안정 (flaky) | 타이밍, 네트워크, 환경 → ~30% 랜덤 실패 |
| 디버깅 어려움 | 실패 지점 파악이 힘듦 |
| 비즈니스 로직 검증 부적합 | UI 클릭 흐름은 비즈니스 로직을 직접 검증하지 않음 |
| i18n 검증 부적합 | 로케일별 문자열을 E2E로 검증하는 것은 비효율 |
Solution: 4계층 레이어드 테스팅
역전된 피라미드
E2E Smoke (3~10개) ← 핵심 사용자 여정만, 배포 시
/__________________\
/ Contract (100%) \ ← 모든 엔드포인트, 매 PR
/______________________\
/ Component (80%+) \ ← 단일 컴포넌트, 모킹된 API
/__________________________\
/ Unit (90%+) \ ← 순수 함수, 매 커밋
/______________________________\
계층별 상세
| 레이어 | 내용 | 도구 | 속도 | 커버리지 목표 |
|---|---|---|---|---|
| L0 Unit | 순수 함수 (포매터, 파서, 검증자) | Vitest | <100ms | 90%+ |
| L1 Component | 단일 컴포넌트, 모킹된 API | Playwright CT / Vitest | <500ms | 80%+ |
| L2 Contract | API 응답이 스키마 준수 | Zod (OpenAPI 생성) | <500ms/엔드포인트 | 100% 엔드포인트 |
| L3 E2E Smoke | 핵심 사용자 여정만 | Playwright (배포된 환경) | ~2분 | 5~10개/서비스 |
L0 Unit — 순수 함수
순수 함수는 부작용이 없고 결정론적입니다. 가장 빠르고 안정적인 테스트 계층입니다.
// 포매터, 파서, 검증자, 유틸 함수
describe('formatWeight', () => {
it('정수 파운드를 포맷한다', () => {
expect(formatWeight(135, 'lbs')).toBe('135 lbs');
});
});
L1 Component — 격리된 컴포넌트
단일 컴포넌트를 모킹된 API와 함께 테스트합니다. 실제 API 호출 금지 — 데이터 모양은 컨트랙트 테스트가 보장합니다.
// React: Playwright CT
test('운동 카드가 로딩 상태를 표시한다', async ({ mount }) => {
const component = await mount(<WorkoutCard loading={true} />);
await expect(component.getByText('로딩 중')).toBeVisible();
});
L2 Contract — 스키마 준수 검증
API 응답이 OpenAPI/Zod 스키마를 준수하는지 검증합니다. 이것이 통합 테스트를 대체합니다.
API (생산자) 컴포넌트 (소비자)
┌──────────┐ ┌──────────┐
│ 실제 API │──── 응답 ────→ │ 컴포넌트 │
│ 응답 │ │ 테스트 │
└────┬─────┘ └────┬─────┘
│ │
│ ┌──────────┐ │
└── 검증 ──→│ Zod 스키마│←── 검증 ───┘
└──────────┘
CDC (Consumer-Driven Contracts)
CDC의 핵심: 컴포넌트(소비자)와 API(생산자) 양쪽이 동일한 Zod 스키마에 대해 검증합니다:
- 컴포넌트 테스트는 스키마에서 생성된 모킹 데이터 사용 (유효한 모양 보장)
- 컨트랙트 테스트는 실제 API 응답 검증
- 양쪽 통과 시 통합이 보장됨
L3 E2E Smoke — 최후의 수단
핵심 사용자 여정만 E2E로 검증합니다:
| 스모크 시나리오 | 설명 |
|---|---|
| 로그인 → 핵심 기능 → 저장 | 가장 기본적인 사용자 흐름 |
| 결제 (있다면) | 결제는 반드시 E2E |
| 오프라인 전환 (PWA) | 오프라인 동작 검증 |
절칙: E2E에서 비즈니스 로직을 테스트하지 않습니다. 비즈니스 로직은 L0/L1에서, 데이터 모양은 L2에서 검증합니다.
i18n 테스트 전략
느린 E2E로 i18n을 검증하지 않습니다:
| 계층 | i18n 검증 내용 |
|---|---|
| Component | gettext 문자열 해상도 검증 |
| Contract | API 에러 메시지가 영어 msgid인지 확인 |
| (선택) | 로케일 전환 후 렌더링 검증 |
분야별 커버리지 기준
| 영역 | 최소 커버리지 | 이유 |
|---|---|---|
| 결제 | 90% | 금전적 영향 |
| 인증 | 90% | 보안 |
| 핵심 비즈니스 로직 | 80% | 핵심 가치 |
| 유틸리티 | 60% | 부작용 적음 |
CI/CD 통합
| 단계 | 트리거 | 최대 소요 | 차단 |
|---|---|---|---|
test:unit | 매 커밋/푸시 | 10초 | PR |
test:components | 매 PR | 30초 | PR |
test:contracts | 매 PR | 20초 | PR |
openapi:validate | 매 PR | 5초 | PR |
test:e2e | main 머지 시 | 2분 | 배포 |
안티패턴 (금지)
- E2E에서 비즈니스 로직 테스트
- E2E에서만 i18n 테스트
- 컴포넌트 테스트에서 실제 API 호출
Result: 전환 전후
| 지표 | E2E 우선 (Before) | 레이어드 (After) |
|---|---|---|
| CI 시간 (PR당) | 12~15분 | 1~2분 (E2E 제외) |
| flaky 비율 | ~30% | 5% 미만 (스모크 10개만) |
| 커버리지 | E2E에 집중, Unit 낮음 | Unit 90%+, Component 80%+ |
| 데이터 모양 검증 | 수동/암묵적 | 100% 자동 (Contract) |
Takeaway
E2E는 “사용자 여정 검증”이지 “비즈니스 로직 검증”이 아닙니다 — 비즈니스 로직은 순수 함수(Unit)와 컴포넌트 격리(Component)로 검증하는 것이 빠르고 안정적입니다. E2E는 “로그인 → 기능 사용 → 저장” 같은 핵심 여정이 실제로 작동하는지만 확인하면 됩니다. 느린 E2E에 비즈니스 로직 검증을 맡기면 CI가 느려지고 flaky가 증가합니다
컨트랙트 테스트가 통합 테스트를 대체합니다 — 컴포넌트와 API가 동일한 Zod 스키마에 대해 검증하면(CDC), 실제 통합을 테스트하지 않아도 “데이터 모양이 맞다”는 것을 보장할 수 있습니다. 이 접근은 DB 환경이나 네트워크에 의존하지 않으므로 결정론적이고 빠릅니다. 100% 엔드포인트를 20초 안에 검증할 수 있습니다
AI 주도 개발에서는 빠른 피드백이 더 중요합니다 — AI 에이전트가 생성하는 코드량이 많을수록, 검증 주기가 짧아야 합니다. Unit 10초 + Component 30초면 AI가 만든 코드를 즉시 검증할 수 있습니다. 15분짜리 E2E를 기다리는 동안 AI는 다음 작업을 진행할 수 없습니다. 레이어드 테스팅은 AI 개발 속도를 뒷받침하는 인프라입니다
| ← 이전 | 시리즈: AI 주도 개발 거버넌스 | 다음 → |
|---|---|---|
| (4) gettext 원문 키 | (5) 레이어드 테스팅 | (6) 3-Tier CI 게이트 |
게이트웨이 On-promise 제품 팀에서 시스템 모니터링 및 관리를 쉽게 다가갈 수 있도록 하기 위한 업무를 하고 있습니다.
Contact: lhjnano@gmail.com