대규모 엔지니어링 팀에서 사용하는 프론트엔드 테스트 전략과 각 테스트 종류의 특징, 장단점, 도구를 소개하는 실용 가이드입니다.
프론트엔드 테스트는 복잡합니다. 사용자들은 기능이 가득한 잦은 릴리스를 기대합니다. 하지만 새로운 기능이 추가될수록 더 큰 복잡성이 생기며, 이는 반드시 테스트되어야 합니다.
강력한 테스트 스위트는 이전보다 더 중요해졌지만, 올바른 도구를 고르는 것은 여전히 쉽지 않습니다. 모든 도구가 "쉽고, 불안정하지 않고, 빠르다"고 홍보하지만, 세부사항에는 주의가 필요합니다.
이 가이드에서는 대규모 엔지니어링 팀에서 실제로 사용하는 프론트엔드 테스트 기법을 소개합니다. 이를 통해 쉽고, 유지보수가 용이하며, 다양한 상황을 아우르는 현실적인 테스트 전략을 수립할 수 있습니다. 또한, 피해야 하는 함정들도 함께 짚어드립니다.
이 가이드는 수익을 창출하는 애플리케이션을 가진 팀을 위한 것입니다. 테스트 스위트를 유지함으로써 개발 속도와 신뢰성이 기하급수적으로 향상됩니다. 아직 제품-시장 적합성이 없는 소규모 팀이나 스타트업이라면 이 가이드를 건너뛰세요. 아이디어를 발전시키는 동안은 수동 테스트에 집중하는 것이 효과적입니다.
우리를 신뢰해도 될까요? OpenAI, Twilio, Adobe, MongoDB, Shopify, Microsoft 등 수십 개 팀을 조사했습니다. 오픈 소스 코드 리뷰, CI 설정 조사, 인터뷰 등을 포함했죠. 우리는 Storybook을 만드는데, Fortune 50의 절반이 이 도구를 사용합니다. 전 세계적 채택 사례를 통해 실전의 최선과 최악의 사례에 골고루 노출되어 있습니다.
현대 프론트엔드 개발에서는 컴포넌트와 데이터 페칭이 기본입니다. 따라서 프론트엔드 테스트는 다음과 같은 기본 개념으로 나눌 수 있습니다:
각 개념은 서로 다른 유형의 테스트와 연결됩니다. 모든 테스트가 모든 개념을 커버하지 않습니다. 각 테스트 타입마다 고유한 장점이 있습니다. 프론트엔드 전체에 버그가 퍼지는 것을 막으려면, 다양한 테스트를 혼합해야 합니다. 아래의 '프론트엔드 테스트 트로피(Frontend Testing Trophy)'는 본 가이드에서 다루는 테스트 유형을 한눈에 보여줍니다.
프론트엔드 로직 코드는 UI와 독립적인 경우가 많습니다. 순수 함수로 작성되어, 컴포넌트에서 임포트해서 사용하죠. 이 함수들은 입력(데이터)을 받아 출력(데이터)을 내놓으며, 부작용이 없습니다. 물론 여러가지 로직 분기가 있을 때도 있지만, Vitest나 Jest와 같은 도구로 쉽게 테스트할 수 있습니다.
Vitest와 Jest 모두 테스트 러너, 테스트와 어서션을 작성할 수 있는 API, 그리고 함수, 모듈, 타이머 등을 모킹할 수 있는 유틸리티를 제공합니다. 단위 테스트는 Node.js 환경에서 CLI/CI로 실행되기 때문에 실행이 빠르고 작성도 쉽습니다.
그럼에도 프론트엔드 개발에서는 단위 테스트의 활용 빈도가 상대적으로 낮습니다. 대부분의 프론트엔드 코드는 브라우저를 대상으로 하기 때문이죠. 경험칙인 “테스트를 작성하라. 너무 많지 않게. 대부분은 통합 테스트로.”는 여전히 유효합니다.
경우에 따라 다릅니다. 단위 테스트는 작성·유지보수 비용이 적습니다. 그러나 브라우저 의존성이 높은 프론트엔드에서는 백엔드 개발처럼 단위 테스트의 비중이 크지 않습니다. 모든 세부사항까지 커버하려고 과하게 단위 테스트에 집착하는 것은 오히려 역효과일 수 있습니다.
도구: Storybook, Testing Library
컴포넌트 테스트는 단위 테스트와 E2E(엔드 투 엔드) 테스트의 간극을 메워줍니다. 전체 앱 환경 세팅 없이도 독립적으로 컴포넌트를 렌더링하여, 로직, 브라우저 렌더링, 인터랙션 등을 테스트할 수 있습니다.
프론트엔드 개발자는 대부분의 시간을 컴포넌트 개발에 씁니다. 버튼에서 페이지에 이르기까지 모두 컴포넌트죠. 각 컴포넌트는 HTML과 CSS로 렌더링되며, 전달된 props와 state에 따라 다양한 변형을 가질 수 있습니다.
자세히 보면, 컴포넌트도 앞서 설명한 "순수 함수"와 닮았습니다. 데이터(입력)를 받아 UI(출력)를 만듭니다.
과거에는 UI 렌더링 결과를 테스트하는 게 고달픈 작업이었습니다. 대부분의 테스트 도구가 Node.js 환경에서 CLI/CI로 HTML을 문자열로 반환해주지만, 구조를 검증하려면 복잡한 어서션이 필요했습니다. 디버깅이 너무 힘들다 보니 많은 개발자가 프론트엔드 테스트 자체를 포기하곤 했습니다.
컴포넌트 테스트는 이런 한계를 실 브라우저 환경에서 돌파합니다. 이제 실제로 브라우저에서 컴포넌트를 렌더링하고, 시각적으로 출력을 검토하거나, 인터랙션을 조작하여 동작을 검증할 수 있습니다. Storybook처럼, 각 컴포넌트를 설명하는 stories 파일을 만들어 다양한 상태(예: 에러, 빈 상태, 기본 상태 등)를 이야기 형식으로 기록합니다. 각각의 story가 곧 테스트 케이스가 됩니다.
컴포넌트는 동적입니다. 사용자가 UI와 상호 작용하고, 폼 필드를 입력하고, 이벤트를 트리거할 수 있습니다. 대부분의 컴포넌트는 이러한 이벤트에 반응하여 내부 상태나 렌더링을 바꿉니다.
Storybook에서는 클릭, 입력 등 사용자 행동을 시뮬레이션한 뒤, 컴포넌트가 기대한 대로 동작하는지 어서션을 쓸 수 있습니다.
컴포넌트 테스트는 진짜 브라우저 환경에서 실행되므로, 브라우저 개발자 도구를 활용하여 DOM 검사, 스타일 조작, 디버깅 등이 가능합니다.
항상 그렇습니다. 컴포넌트 테스트는 유지보수 비용이 적고, 실제 브라우저에서 실행되며, 다른 스택에 의존하지 않아 불안정성(플레이크)이 없습니다. 단위 테스트만큼 빠르고 구체적이면서, 사용자 관점(E2E 테스트)도 충족합니다.
도구: aXe
사용자는 마우스, 터치스크린, 키보드, 화면낭독기 등 다양한 방식으로 UI를 만집니다. 접근성이란 웹사이트가 모든 사용자에게 사용 가능하도록 만드는 실천법입니다.
접근성 테스트의 가장 정확한 방법은, 브라우저와 기기, 스크린리더 조합별로 수동 점검하는 것이지만, 이는 매우 번거롭고 시간이 많이 듭니다. 그래서 대부분의 팀은 수동 점검과 자동화 테스트를 혼합합니다.
먼저, 기계로 명백한 접근성 위반을 잡아냅니다. aXe 라이브러리를 사용해 렌더링된 DOM을 표준 지침(린터와 유사)에 따라 검사합니다.
그 다음, 컴포넌트 테스트로 실제 사용자처럼 UI를 쿼리합니다. aria-roles로 요소를 찾고, user-event로 사용자 인터랙션을 시뮬레이션합니다.
마지막으로, 다양한 브라우저와 기기, 스크린리더에서 실제로 접근성을 확인합니다.
자동화와 수동의 결합은 커버리지와 효율성의 균형을 잡는 실용적인 방법입니다. 빠른 피드백을 통해 접근성 이슈를 프로덕션 이전에 발견하고 해결할 수 있습니다. 대다수 팀이 aXe로 컴포넌트 자동 점검을 하여, 타겟 테스트와 버그 조기 발견을 실현합니다. 예를 들어:
자주 그렇습니다. aXe를 쓴다고 해서 애플리케이션이 전적으로 접근 가능하지는 않지만, 주요 이슈를 미리 잡아주므로 집중적으로 점검할 대상을 좁힐 수 있습니다. 참고로 2025년부터 접근성 준수는 북미와 유럽의 법적 필수사항이 됩니다.
도구: Chromatic
현대 UI는 셀 수 없이 다양한 변형을 가집니다. 변형이 많을수록, 모든 환경에서 외관이 올바른지 확인하는 게 힘들어집니다.
비주얼 테스트는 프론트엔드의 모든 상태별 외형을 검증합니다. 컴포넌트 테스트, E2E 테스트와 상호보완적입니다.
컴포넌트 테스트에서는 TDD처럼, 렌더링 결과·동작을 코드로 검증합니다. 하지만 디자인 의도를 눈으로 확인하는 것은 결국 사람의 몫입니다. 모든 변형을 커밋마다 확인하는 것은 피로를 야기합니다.
E2E 테스트에서는 전체 앱을 띄워서 UI와 사용자 플로우를 점검하지만, 여전히 각 페이지별로 눈으로 디자인 의도를 맞춰봐야 합니다. 모든 페이지를 일일이 확인하는 것은 매우 번거롭습니다.
비주얼 테스트는 컴포넌트·페이지의 스크린샷을 자동으로 찍어, 마크업, 스타일, 에셋까지 완비된 브라우저 환경에서 보관합니다. 최초 1회 수동으로 UI를 검토해 베이스라인으로 승인하고, 이후 커밋마다 새 스크린샷을 비교하여 변경 여부를 확인합니다.
프론트엔드 외형이 달라지면, 비주얼 테스트가 알림을 주어, 새 베이스라인으로 승인하거나 버그를 고칠 수 있습니다.
항상 그렇습니다. 비주얼 테스트는 프론트엔드 외곽의 품질 저하를 방지합니다. 브라우저·뷰포트별 변형을 일일이 확인할 필요가 없어 엄청난 시간적 이득이 있습니다. 또한, 기존 컴포넌트·E2E 테스트 케이스를 그대로 활용하므로 별도의 비주얼 테스트 파일을 작성·관리할 필요가 없습니다.
도구: Playwright, Cypress
기본적인 작업조차 사용자가 여러 페이지에 걸쳐 순차적으로 진행해야 할 수 있습니다. 엔드 투 엔드(E2E) 테스트는 전체 앱(백엔드, API, 프론트엔드 포함)을 실제 사용자처럼 띄우고, 여러 단계를 시뮬레이션해 결합 오류를 찾아냅니다.
E2E 테스트는 프로덕션 환경에 가장 근접하지만, 대가도 큽니다. 전체 시스템(프론트, 백엔드, 기타 서비스)에 대한 테스트 환경 세팅, 데이터 시드, 클라우드 브라우저 연동까지 모든 인프라스트럭처 업무가 필요합니다. 유지보수 오버헤드가 많죠.
특히 E2E 세팅 자체가 다른 모든 테스트 실행을 합친 것보다 오래 걸릴 수 있습니다.
대다수 인터뷰팀은 E2E 테스트에 과도하게 투자하는 것을 경계했습니다. 대신 실행이 빠르고 유지보수가 적은 컴포넌트 테스트를 우선합니다. 하지만 일부 팀은 그만한 가치가 있다고 판단합니다. 예를 들어 O’Reilly는 Docker로 전체 인프라를 게임처럼 띄우고, Cypress로 사용자 플로우를 검증합니다.
E2E 테스트는 빌드·번들된 앱 코드 위에서 "블랙박스" 방식으로 돌아갑니다. 보통 CI에서 "최종 단계"로, 주요 사용자 플로우가 잘 동작하는지 검증합니다.
적절히 사용하면 그렇습니다. E2E 테스트는 신뢰도는 높지만, 들이는 노력도 많습니다. 그러므로 "회원가입 → 장바구니 담기 → 결제" 등, 꼭 핵심 플로우에만 제한적으로 실시하세요.
정적 분석 도구는 코드가 고정된 규칙이나 베스트 프랙티스에 부합하는지 비교해 이슈를 찾습니다. 테스트 실행 전, 명백한 실수를 피하도록 개발 도우미 역할을 해줍니다. 팀이 어떤 규칙을 체크할지 커스터마이징하면, 정적 분석 도구가 규정 준수를 보장해줍니다.
코드가 브라우저에 도달하기 전에 스캔하여, 프론트엔드 테스트(브라우저에서 실행됨)를 보조합니다. 그래도 꼭 추천하는데, 테스트 코드 자체가 조직 기준에 부합하는지 추가적인 신뢰를 주기 때문입니다.
지금까지 고유한 5가지 프론트엔드 테스트 유형을 다뤘습니다. 모두 한 번에 적용하고 싶겠지만, 개발자는 한 번에 하나의 버그만 고칠 수 있습니다. 테스트 실행 순서가 중요합니다.
개발자의 핵심 임무는 기능 요구사항을 충족하는 것입니다. 단위와 컴포넌트 테스트는 요구사항 충족과 빠른 피드백을 보장합니다. 이 테스트부터 먼저 실행하세요.
이제 화면이 제대로 그려지고, 올바르게 동작하는지 확인한 후, 접근성 작업으로 넘어가세요. 이 과정에서 기능 코드를 교체하거나 동작을 변경하게 됩니다. 이미 단위·컴포넌트 테스트가 든든한 백업 역할을 할 겁니다.
이제 구현에 확신이 생겼으니, 픽셀이 디자인과 일치하는지 확인해야 합니다. 이는 여러 번의 반복 작업이 필요할 수 있습니다. 비주얼 테스트로 앱 다른 부분의 외형이 실수로 손상되지 않도록 보장하세요.
지금까지 해온 모든 일은 앱의 각 부분 단품 및 변형을 점검한 것이었습니다. 이제 전체 앱의 통합을 검증할 차례입니다. 엔드 투 엔드 테스트로 핵심 사용자 플로우가 잘 동작하는지 마지막으로 확인하세요.
테스트는 지속적으로 실행될 때 가장 효과적입니다. 모든 코드 푸시에 CI 파이프라인에서 테스트가 자동으로 작동하도록 연동하세요. 결과는 PR에서 모두가 확인할 수 있습니다. 각 테스트 유형을 Git 제공자의 "필수 체크"로 등록해, 팀 전체의 품질 기준을 보장하세요.
프론트엔드 테스트는 절대 정답이 없기에 이 가이드를 만들었습니다. 자신에게 맞는 전략만이 최고의 답입니다. 아래 표는 각 프론트엔드 테스트 방식의 장단점, 사용 빈도를 요약한 것입니다.