상황
릴리즈 검증이 전부 수동으로 이루어졌습니다. 릴리즈마다 QA팀이 TC(테스트 케이스) 항목을 하나씩 수동으로 확인해야 했고, 영향도가 큰 릴리즈는 최소 2일 이상의 QA 기간이 소요됐습니다. 핵심 사용자 흐름(주문·결제 등)에 대한 자동화 검증이 전혀 없었습니다.
문제
자동화 검증 부재로 발생하는 문제는 두 가지였습니다.
첫째, 회귀 버그 탐지 지연. 코드 변경이 다른 흐름에 의도치 않은 영향을 미쳐도 QA 단계에서야 발견됐습니다. 발견이 늦을수록 수정 비용이 높아지고, 핫픽스가 잦아졌습니다.
둘째, QA 병목. 릴리즈 주기를 단축하려 해도 QA 소요 시간이 변수가 됐습니다. 영향도 범위가 클수록 QA 기간도 함께 늘어나는 구조였습니다.
접근과 판단
"어떤 테스트부터 써야 하는가"를 먼저 정의했습니다.
모든 곳에 테스트를 쓰는 것은 비현실적입니다. 테스트 작성에도 공수가 들고, 잘못된 곳에 쓴 테스트는 유지보수 부담만 늘립니다. 우선순위 기준을 먼저 정했습니다: 버그 발생 시 사용자에게 직접 피해가 생기는 흐름부터.
결제 실패, 주문 누락, 장바구니 손상 — 이런 흐름은 버그 하나가 실시간으로 고객 이탈과 매출 손실로 이어집니다. 이 기준으로 테스트 범위를 정하면, 제한된 공수 안에서 가장 높은 위험을 먼저 커버할 수 있습니다.
테스트 레이어를 두 단계로 분리했습니다.
- 통합 테스트 (Testing Library + Jest): 컴포넌트 간 상호작용, API 연동 레이어를 테스트합니다. 빠르고 격리된 환경에서 비즈니스 로직의 정확성을 검증합니다.
- E2E 테스트 (Playwright): 브라우저에서 실제 사용자 흐름 전체를 검증합니다. 핵심 플로우(로그인→장바구니→결제)를 대상으로 하며, 단위/통합 테스트로 잡기 어려운 환경 의존성 버그를 잡습니다.
컨벤션 문서를 함께 작성했습니다.
테스트 코드도 코드입니다. 팀 전체가 일관된 방식으로 테스트를 작성하지 않으면, 테스트가 늘어날수록 읽기 어려운 코드가 됩니다. Given-When-Then 패턴과 접근성 기반 선택자 우선순위(role → label → placeholder → test-id 순)를 컨벤션으로 정의했습니다.
PR 양식에 E2E 체크항목을 추가하고 AI 도구 연동을 설계했습니다.
PR 설명 양식에 E2E 테스트 실행 항목을 추가하고, AI 코딩 도구가 해당 항목을 읽어 테스트 케이스를 자동 생성하도록 연동했습니다. 테스트 작성 진입 비용을 낮추는 것이 목적이었습니다.
결과
| 항목 | 비교 | 값 (%) |
|---|---|---|
| 회귀 버그 발생률 Before | 30 % | |
| 회귀 버그 발생률 After | 5 % | |
| 수동 QA 소요(상대값) Before | 100 % | |
| 수동 QA 소요(상대값) After | 25 % |
- 테스트 커버리지 0% → 25%: 핵심 비즈니스 로직과 사용자 흐름 우선 커버
- 회귀 버그 발생률 30% → 5%: Jira 기반 버그 추적 데이터
- 고객 이탈률 12% 감소: GA 기반, 해당 기간 다른 대규모 변경 없었음
- 수동 QA 2일 → 반나절: QA팀 TC별 공수 히스토리 기반 역산 (자동화 커버 비율 적용)
- 테스트 작성 시간 약 30% 단축: 컨벤션 표준화 + AI 초안 생성 연동 효과
배운 것
테스트 우선순위는 "무엇이 가장 무서운가"에서 출발해야 합니다. 커버리지 숫자를 높이는 것이 목표가 되면, 비즈니스 위험이 낮은 유틸 함수를 테스트하느라 정작 결제 흐름은 테스트가 없는 역설이 생깁니다.
테스트 가능한 코드 구조가 먼저입니다. 의존성이 강하게 결합된 코드는 테스트하기 어렵습니다. 테스트를 쓰려다 코드 구조 문제를 발견하게 되고, 결국 리팩토링으로 이어지는 경우가 많았습니다. 테스트는 코드 설계의 피드백 루프이기도 합니다.