블로그
frontend
4遺??뚯슂

끝까지 눌러서 검증하라: 프런트엔드 E2E 테스트 설계

E2E 테스트는 사용자의 핵심 흐름을 브라우저에서 끝까지 재현해, 유닛·통합 테스트가 놓치는 통합 지점을 조기에 잡아낸다.

끝까지 눌러서 검증하라: 프런트엔드 E2E 테스트 설계

한 문장 결론: E2E(End-to-End) 테스트는 사용자의 핵심 흐름을 브라우저에서 끝까지 재현해, 유닛·통합 테스트가 놓치는 연결 지점의 오류를 조기에 잡아낸다.

사용자 경험은 버튼 클릭 -> 페이지 이동 -> 데이터 입력 -> API 응답 -> 화면 갱신처럼 여러 요소가 함께 움직일 때 완성됩니다. 그런데 테스트를 조각 단위로만 쪼개면, 전체 흐름에서 터지는 문제를 놓치기 쉽습니다.

정리하면 포인트는 사용자 관점의 시나리오를 실제 브라우저에서 검증하는 것입니다. E2E 테스트는 이 목적에 가장 잘 맞습니다. ([Playwright Docs](https://playwright.dev/), [Cypress Docs](https://docs.cypress.io/))


배경/문제

프런트엔드 결함은 종종 컴포넌트 자체가 아니라 컴포넌트들 사이의 연결에서 발생합니다.

  • 라우팅이 바뀌며 의도치 않게 리다이렉트된다.
  • API 에러 처리 때문에 버튼이 다시 눌리거나 화면이 멈춘다.
  • 로그인 후 세션/쿠키 상태 때문에 다음 페이지가 빈 화면이 된다.

유닛 테스트는 각 조각이 맞는지 빠르게 확인하지만, 브라우저에서 실제 사용 흐름이 정상인지까지는 보장하지 못합니다.


핵심 개념

E2E 테스트는 “흐름”을 검증한다

E2E 테스트는 애플리케이션을 실제 브라우저에서 실행하고, 사용자의 동작을 그대로 시뮬레이션합니다. 클릭, 입력, 페이지 이동, 네트워크 요청/응답 후 UI 변화까지 포함합니다.

아래 다이어그램은 유닛/통합/E2E가 무엇을 주로 검증하는지 “관심 범위”를 정리한 것입니다.

```mermaid

flowchart TB

U["Unit<br/>함수·컴포넌트 단위"] --> I["Integration<br/>여러 모듈의 연결"]

I --> E["E2E<br/>사용자 흐름 전체"]

U -->|"빠른 피드백"| Goal1["로직 정확성"]

I -->|"경계·계약 확인"| Goal2["연동 안정성"]

E -->|"브라우저에서 재현"| Goal3["사용자 경험 검증"]

```

→ 기대 결과/무엇이 달라졌는지: “어디서 깨지는지”를 범위로 나눠 추적할 수 있어, 테스트 설계가 목적 중심으로 정리됩니다.

왜 유닛 테스트만으로는 부족해질까?

유닛 테스트는 “로그인 함수가 성공을 반환한다”를 확인할 수 있습니다. 하지만 사용자는 “로그인 버튼을 누른 뒤, 페이지가 이동하고, 세션이 유지되며, 화면이 올바르게 렌더링되는지”를 경험합니다.

E2E는 이 연결 구간을 검증해, 배포 후 바로 체감되는 오류를 줄이는 데 유리합니다.


해결 접근

접근 1) E2E는 “핵심 사용자 흐름”에 집중한다

E2E는 비용(실행 시간/환경 의존성)이 있는 테스트라서, 모든 화면을 다 덮기보다 **깨지면 영향이 큰 흐름**에 집중하는 게 효율적입니다.

  • 로그인/로그아웃, 권한이 필요한 페이지 접근
  • 결제/구매/예약 같은 주요 전환 흐름
  • 검색/필터/목록→상세→주요 액션(담기/저장 등)

→ 기대 결과/무엇이 달라졌는지: 테스트 수를 무작정 늘리지 않고도, “치명적인 회귀”를 먼저 막는 구조가 됩니다.

접근 2) Cypress vs Playwright는 “운영 방식”으로 고른다

원문에서 언급한 대표 도구는 Cypress와 Playwright입니다.

  • Cypress: 브라우저에서 테스트를 관찰/디버깅하기 쉬운 워크플로를 제공합니다. ([Cypress E2E Docs](https://docs.cypress.io/app/end-to-end-testing/writing-your-first-end-to-end-test))
  • Playwright: 여러 브라우저 자동화와 테스트 러너 중심의 구성을 제공합니다. Next.js와 함께 쓰는 공식 가이드도 있습니다. ([Next.js + Playwright](https://nextjs.org/docs/pages/guides/testing/playwright))

→ 기대 결과/무엇이 달라졌는지: 도구 선택을 “유행”이 아니라, 팀의 디버깅·CI·브라우저 요구사항에 맞춰 결정할 수 있습니다.


구현(코드)

아래 예시는 **Next.js에서 E2E 테스트를 재현 가능한 형태로 구성**하는 흐름입니다. (공식 가이드 기준: [Next.js + Playwright](https://nextjs.org/docs/pages/guides/testing/playwright))

1) Playwright 설정(Next.js 서버를 띄우고 테스트 실행)

```ts

// playwright.config.ts

import { defineConfig } from "@playwright/test";

export default defineConfig({

use: {

baseURL: "http://localhost:3000",

},

webServer: {

command: "npm run dev",

url: "http://localhost:3000",

reuseExistingServer: !process.env.CI,

},

});

```

→ 기대 결과/무엇이 달라졌는지: 테스트 실행 시 서버 준비/대기까지 자동화되어, 로컬/CI에서 실행 방식이 일관됩니다.

2) “사용자 동작” 중심의 시나리오 작성

```ts

// tests/navigation.spec.ts

import { test, expect } from "@playwright/test";

test("페이지 이동이 정상 동작한다", async ({ page }) => {

await page.goto("/");

await page.getByRole("link", { name: "About" }).click();

await expect(page).toHaveURL(/\/about$/);

await expect(page.locator("h1")).toContainText("About");

});

```

→ 기대 결과/무엇이 달라졌는지: “클릭 → 이동 → 화면 확인”처럼 사용자가 체감하는 흐름을 그대로 검증합니다.


검증 방법(체크리스트)

핵심 흐름(로그인/전환/주요 액션)이 최소 1개 이상 E2E로 커버된다.
테스트는 서로의 실행 결과에 의존하지 않고 독립적으로 통과한다. ([Cypress Best Practices](https://docs.cypress.io/app/core-concepts/best-practices))
클릭/입력 후에는 “시간 대기” 대신 “조건(요소/URL/응답)”을 기준으로 검증한다.
CI에서 실패했을 때 원인을 추적할 수 있도록 리포트/스크린샷/트레이스를 남긴다. ([Playwright Docs](https://playwright.dev/))

흔한 실수/FAQ

Q1. 유닛 테스트로도 충분히 안정성을 높일 수 있지 않나요?

유닛 테스트는 “조각”의 정확성을 빠르게 보장합니다. 하지만 사용자 경험은 여러 조각이 연결된 결과입니다.

E2E는 이 연결 흐름을 검증해, 배포 후 사용자에게 바로 보이는 오류를 줄이는 데 유리합니다.

Q2. E2E가 자주 깨지는(Flaky) 이유는 뭔가요?

일반적으로 “상태 공유”, “시간 기반 대기”, “환경 의존성(데이터/네트워크)” 때문에 흔들립니다.

테스트 독립성/조건 기반 검증 같은 기본 원칙이 큰 도움을 줍니다. ([Cypress Best Practices](https://docs.cypress.io/app/core-concepts/best-practices))

Q3. 중요한 페이지에만 적용하면 되나요?

네. E2E는 핵심 흐름에 집중할수록 효과가 큽니다.

나머지는 유닛/통합 테스트로 커버해 균형을 맞추는 전략이 일반적입니다.


요약(3~5줄)

E2E 테스트는 브라우저에서 사용자 행동을 그대로 재현해 “흐름”을 검증합니다.

유닛 테스트가 놓치기 쉬운 라우팅/세션/연동 구간의 오류를 조기에 발견하는 데 유리합니다.

Cypress와 Playwright는 팀의 디버깅·CI·브라우저 요구사항에 맞춰 선택하는 편이 안정적입니다.


결론

E2E의 목적은 테스트를 많이 만드는 게 아니라, **깨지면 영향이 큰 사용자 흐름을 끝까지 보호하는 것**입니다.

핵심 흐름부터 작게 시작하고, 실패 원인을 추적 가능한 형태로 운영 기준을 함께 정리하면 유지보수가 쉬워집니다.


참고(공식 문서 링크)

  • [Next.js + Playwright](https://nextjs.org/docs/pages/guides/testing/playwright)
  • [Playwright Docs](https://playwright.dev/)
  • [Cypress E2E Docs](https://docs.cypress.io/app/end-to-end-testing/writing-your-first-end-to-end-test)
  • [Cypress Best Practices](https://docs.cypress.io/app/core-concepts/best-practices)

관련 게시물