- Published on
브라우저 & 모바일 E2E 자동화 2026 딥다이브: Playwright, Cypress, Selenium 4, WebDriverIO, Maestro, Detox, Appium 2 완전 비교
- Authors

- Name
- Youngju Kim
- @fjvbn20031
2026년 E2E 자동화 풍경: BiDi가 바꾼 게임의 규칙
2026년 브라우저 자동화는 두 가지 거대한 변화를 맞았다. 첫째, W3C WebDriver BiDi가 2024년 후반부터 모든 주요 브라우저(Chrome, Firefox, Edge, Safari)에서 GA되면서, 15년 묵은 JSON Wire Protocol과 WebDriver Classic을 사실상 대체했다. 둘째, Microsoft Playwright가 GitHub 스타 65k를 돌파하며 Cypress를 다운로드 수에서 처음으로 추월했고, Cypress.io는 Cloud + Component Testing 중심으로 비즈니스 모델을 재편했다. 모바일에서는 Maestro가 Detox/Appium에게 도전장을 내밀었다. 이 글은 12개 도구를 실전 코드와 함께 비교한다.
E2E 테스트가 풀어야 할 진짜 문제
단위 테스트가 함수를 검증하고 통합 테스트가 서비스 경계를 검증한다면, E2E 테스트는 "실제 사용자가 보는 화면"을 검증한다. 문제는 비용이다. 브라우저 부팅, 네트워크 왕복, DOM 렌더링, 애니메이션이 모두 비결정성을 만든다. 2010년대 Selenium의 flakiness는 산업의 트라우마였다. 2020년 이후 Playwright의 auto-waiting, Cypress의 retry-ability, WebDriver BiDi의 양방향 이벤트 스트림이 차례로 문제를 풀어왔다.
WebDriver BiDi: 15년 만의 표준 교체
기존 WebDriver Classic은 HTTP 요청/응답 기반의 단방향 프로토콜이었다. 브라우저 이벤트(console.log, network request)를 받으려면 폴링이 필요했고, 이는 flaky 테스트의 근원이었다. WebDriver BiDi는 WebSocket 기반 양방향 프로토콜로, Chrome DevTools Protocol(CDP)의 강력함과 W3C 표준의 호환성을 결합한다. 2026년 현재 Selenium 4.20+, Puppeteer 22+, Playwright 1.50+가 모두 BiDi를 1급으로 지원한다.
// Selenium 4 + BiDi 이벤트 리스너
import { Builder, By, LogInspector, NetworkInspector } from 'selenium-webdriver'
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(new chrome.Options().enableBidi())
.build()
// BiDi 로그 인스펙터로 console 메시지 실시간 캡처
const logInspector = await LogInspector(driver)
await logInspector.onConsoleEntry((entry) => {
console.log(`[${entry.level}] ${entry.text}`)
})
// BiDi 네트워크 인스펙터로 요청/응답 가로채기
const networkInspector = await NetworkInspector(driver)
await networkInspector.onBeforeRequestSent((req) => {
if (req.request.url.includes('/api/orders')) {
console.log('Order API called:', req.request.method)
}
})
await driver.get('https://example.com/checkout')
await driver.findElement(By.id('pay-button')).click()
await driver.quit()
Playwright: Microsoft가 만든 차세대 표준
Playwright는 2020년 Microsoft가 출시한 후 매년 다운로드 두 배 성장을 이어가, 2026년 1분기 npm 주간 다운로드 1,200만을 돌파했다. 핵심 차별점은 세 가지다. 첫째, Chromium/Firefox/WebKit 모두를 단일 API로 제어한다(WebKit은 Safari 엔진). 둘째, auto-waiting이 기본이라 waitFor 호출이 거의 필요 없다. 셋째, @playwright/test는 병렬화/샤딩/리트라이/스크린샷/비디오/트레이스가 한 패키지에 들어있다.
// tests/checkout.spec.ts — Playwright Test v1.50
import { test, expect } from '@playwright/test'
test.describe('Checkout flow', () => {
test.beforeEach(async ({ page }) => {
// 인증 상태는 storageState로 재사용 (auth.setup.ts에서 생성)
await page.goto('/cart')
})
test('completes order under 5 seconds', async ({ page }) => {
// Locator는 lazy — 호출 시점에 평가되어 retry됨
await page.getByRole('button', { name: 'Checkout' }).click()
await page.getByLabel('Card number').fill('4242424242424242')
await page.getByLabel('Expiry').fill('12/29')
// Network mocking via route handler
await page.route('**/api/payments', async (route) => {
await route.fulfill({ json: { status: 'success', orderId: 9001 } })
})
await page.getByRole('button', { name: 'Pay' }).click()
await expect(page.getByText(/Order #9001 confirmed/)).toBeVisible({ timeout: 5000 })
})
})
Playwright auto-waiting의 비밀
Playwright의 모든 Locator 액션(click, fill, check)은 내부적으로 "actionability checks"를 수행한다. 요소가 attached, visible, stable(애니메이션 종료), receives events(다른 요소가 가리지 않음), enabled 모두를 만족할 때까지 기본 30초 대기한다. 이것이 Cypress의 retry-ability와 비슷하지만 더 강력한 이유는 <button> 같은 단순 요소부터 React Portal 안의 동적 모달까지 동일하게 동작하기 때문이다.
Cypress: 동일 프로세스 아키텍처의 양날
Cypress는 2014년 출시 이후 "테스트가 브라우저 안에서 돈다"는 독특한 아키텍처를 유지해왔다. 이는 디버깅 경험에서 압도적이다 — Chrome DevTools에서 그대로 테스트를 디버그하고, time-travel 디버거로 각 명령의 DOM 스냅샷을 본다. 하지만 같은 origin 제약, multi-tab 미지원, iframe 한계가 따라온다. 2024년 Cypress 13에서 origin 제약이 완화됐고, 2026년 14는 WebDriver BiDi 모드를 실험 지원한다.
// cypress/e2e/checkout.cy.js — Cypress v14
describe('Checkout flow', () => {
beforeEach(() => {
// 세션 캐싱 — Cypress 12+의 cy.session()
cy.session('user-alice', () => {
cy.visit('/login')
cy.get('[data-cy=email]').type('alice@example.com')
cy.get('[data-cy=password]').type('s3cret')
cy.get('[data-cy=submit]').click()
cy.url().should('include', '/dashboard')
})
})
it('completes payment with intercepted API', () => {
cy.intercept('POST', '/api/payments', {
statusCode: 200,
body: { status: 'success', orderId: 9001 },
}).as('payment')
cy.visit('/cart')
cy.get('[data-cy=checkout]').click()
cy.get('[data-cy=card-number]').type('4242424242424242')
cy.get('[data-cy=pay]').click()
cy.wait('@payment').its('response.statusCode').should('eq', 200)
cy.contains('Order #9001 confirmed').should('be.visible')
})
})
Playwright vs Cypress: 아키텍처가 결정한 차이
가장 자주 받는 질문은 "Playwright와 Cypress 중 무엇이냐"다. 핵심은 아키텍처다. Playwright는 out-of-process — 테스트 코드는 Node.js에서 돌고 브라우저는 CDP/BiDi로 원격 제어한다. 멀티 브라우저, 멀티 탭, 멀티 origin, 진짜 병렬화가 가능하다. Cypress는 in-process — 테스트가 브라우저 안에서 돌아서 DevTools 친화적이지만, 병렬화는 같은 머신 안에서 어렵다(Cypress Cloud의 머신별 샤딩으로 우회). 토스(Toss) QA팀은 2024년 SLASH에서 결제 플로우 E2E를 Cypress에서 Playwright로 이전했고, 풀-스위트 실행 시간이 23분에서 6분으로 줄었다고 발표했다.
병렬화 & 샤딩 전략
Playwright는 workers 옵션으로 같은 머신에서 N개 워커를 띄우고, --shard=1/4 같은 CLI로 CI 머신 간 분할한다. Cypress는 머신 안에서는 1워커지만 Cypress Cloud가 테스트 파일 단위로 머신을 자동 분배한다. WebDriverIO는 maxInstances와 maxInstancesPerCapability로 세밀하게 제어한다. 카카오페이는 결제 E2E 1,200개를 GitHub Actions matrix strategy.matrix.shard: [1,2,3,4,5,6,7,8]로 8개 러너에 분할해 평균 7분 안에 완료한다고 2025년 if(kakao)에서 공유했다.
인증 상태 공유: storageState 패턴
E2E 테스트가 매번 로그인 폼을 채우면 5분짜리 스위트가 50분이 된다. Playwright는 storageState로 쿠키/localStorage를 JSON으로 저장하고 모든 테스트에서 재사용한다. Cypress는 cy.session()이 같은 역할을 한다. Selenium은 명시적 코드가 필요하다.
// auth.setup.ts — Playwright의 글로벌 setup
import { test as setup } from '@playwright/test'
setup('authenticate as admin', async ({ page }) => {
await page.goto('/login')
await page.getByLabel('Email').fill('admin@example.com')
await page.getByLabel('Password').fill(process.env.ADMIN_PW || '')
await page.getByRole('button', { name: 'Sign in' }).click()
await page.waitForURL('/dashboard')
await page.context().storageState({ path: 'playwright/.auth/admin.json' })
})
// playwright.config.ts에서 모든 테스트가 storageState를 사용
export default {
projects: [
{ name: 'setup', testMatch: /.*\.setup\.ts/ },
{
name: 'chromium',
use: { storageState: 'playwright/.auth/admin.json' },
dependencies: ['setup'],
},
],
}
Selenium 4: 표준의 부활
2009년 시작된 Selenium은 한때 "느리고 flaky한 도구"의 대명사였다. Selenium 4(2021)와 4.20(2025)이 모든 것을 바꿨다. 첫째, W3C WebDriver 프로토콜과 BiDi 1급 지원. 둘째, Selenium Manager가 브라우저 드라이버 자동 설치(chromedriver 수동 다운로드 시대 종료). 셋째, Selenium Grid 4의 분산 아키텍처와 Kubernetes 네이티브 배포. 엔터프라이즈와 Java 생태계는 여전히 Selenium이 표준이고, 100개 이상의 모바일/임베디드 브라우저를 지원하는 도구는 Selenium이 유일하다.
// Selenium 4 + Java — 브라우저 매니저 자동 + BiDi 사용
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.bidi.log.LogInspector;
ChromeOptions options = new ChromeOptions();
options.setCapability("webSocketUrl", true); // BiDi 활성화
WebDriver driver = new ChromeDriver(options);
try (LogInspector logInspector = new LogInspector(driver)) {
logInspector.onConsoleEntry(entry ->
System.out.printf("[%s] %s%n", entry.getLevel(), entry.getText())
);
driver.get("https://example.com/checkout");
driver.findElement(By.id("pay-button")).click();
} finally {
driver.quit();
}
WebDriverIO: Node 진영의 Selenium 클라이언트
WebDriverIO는 Node.js 기반 Selenium/WebDriver 클라이언트로, BiDi와 Appium을 모두 지원해서 "웹+모바일"을 한 코드베이스로 묶을 수 있다. 2026년 v9는 Vitest 스타일 API와 React Native 헬퍼를 추가했다. Ionic, Cordova, Capacitor 기반 하이브리드 앱 자동화에서는 사실상 표준이다.
// test/specs/checkout.e2e.js — WebDriverIO v9
describe('Checkout E2E', () => {
it('processes payment', async () => {
await browser.url('/cart')
await $('[data-test=checkout]').click()
await $('#card').setValue('4242424242424242')
// 네트워크 모킹 (BiDi 기반)
await browser.mock('**/api/payments', { method: 'POST' }).respond({
status: 'success',
orderId: 9001,
})
await $('button=Pay').click()
await expect($('=Order #9001 confirmed')).toBeDisplayed()
})
})
Puppeteer & Chrome DevTools Protocol
Puppeteer는 Google Chrome 팀이 만든 Node 라이브러리로, Chrome/Edge를 CDP로 제어한다. Playwright의 사실상 조상이다 — Playwright 창립자들이 Google에서 Puppeteer를 만들고 Microsoft로 옮겨 멀티 브라우저로 확장한 것이 Playwright다. 2026년 Puppeteer 23은 BiDi 모드를 GA했고, Firefox 지원이 안정화됐다. 다만 테스트 러너가 없어 Jest/Vitest와 조합해야 하고, "스크래핑 + 자동화"에 더 자주 쓰인다.
TestCafe & Nightwatch.js
TestCafe(DevExpress)는 WebDriver 없이 프록시로 동작하는 독특한 도구로, 모바일 디바이스에서 실제 사파리/파이어폭스를 동작시킬 수 있다. Nightwatch.js는 Selenium 위의 가벼운 래퍼로 BDD/AC와 잘 어울린다. 둘 다 작은 시장 점유율이지만 특정 니즈(레거시 사파리 자동화, BDD 문법)에서 여전히 선택된다. 2026년 시점 npm 다운로드는 Playwright의 1/50 수준이다.
Maestro: 모바일 E2E의 새로운 표준
Maestro(by Mobile.dev, 2022 출시)는 YAML 기반 모바일 E2E 도구로, "한 줄로 끝나는 테스트"를 모토로 한다. iOS Simulator, Android Emulator, 실제 디바이스, React Native, Flutter, 네이티브 앱을 단일 도구로 다룬다. 핵심은 idempotency — 명령이 안정될 때까지 자동 재시도하고, 텍스트/이미지 기반 매처로 변경에 강하다.
# .maestro/login.yaml — Maestro v1.40
appId: com.example.shop
---
- launchApp
- tapOn: 'Sign in'
- tapOn:
id: 'email_field'
- inputText: 'alice@example.com'
- tapOn:
id: 'password_field'
- inputText: 'hunter2'
- tapOn: 'Continue'
- assertVisible: 'Welcome, Alice'
- takeScreenshot: 'after-login'
- runFlow: 'checkout.yaml'
LINE은 2024년 자사 모바일 슈퍼앱 핵심 플로우 80%를 Maestro로 자동화했고, 메르카리(Mercari)도 2025년 iOS/Android 회귀 테스트를 Detox에서 Maestro로 부분 이전했다고 공식 엔지니어링 블로그에 공유한 바 있다.
Detox: React Native 전용 그레이박스 테스트
Detox는 Wix가 만든 React Native 전용 E2E 도구로, "그레이박스" 접근(앱과 동기화 신호를 주고받음)이 특징이다. 즉 애니메이션, fetch 호출, setTimeout이 모두 끝났다는 신호를 받아야 다음 명령을 실행해, RN 특유의 flakiness를 근본적으로 줄인다. 2026년 Detox 21은 New Architecture(Fabric/TurboModules) GA를 지원한다.
// e2e/checkout.test.js — Detox 21
describe('Checkout', () => {
beforeAll(async () => {
await device.launchApp({ newInstance: true })
})
beforeEach(async () => {
await device.reloadReactNative()
})
it('completes payment', async () => {
await element(by.id('cart-button')).tap()
await element(by.id('checkout-button')).tap()
await element(by.id('card-input')).typeText('4242424242424242')
await element(by.text('Pay')).tap()
await expect(element(by.text('Order #9001 confirmed'))).toBeVisible()
})
})
Appium 2: 모바일의 Selenium
Appium은 2012년부터 "모바일의 Selenium"을 목표로 했고, 2022년 출시된 Appium 2가 드라이버 모델을 완전히 재설계했다. 이제 appium driver install xcuitest처럼 드라이버를 npm 모듈처럼 관리한다. iOS는 XCUITest, Android는 UiAutomator2/Espresso, Windows는 WinAppDriver, macOS는 Mac2 드라이버가 표준이다. 2026년 시점 폴리글랏 모바일 자동화에서 여전히 가장 호환성이 넓다.
Appium vs Detox vs Maestro
세 도구의 차이는 명확하다. Appium은 WebDriver 표준 위에서 가장 넓은 디바이스/플랫폼을 커버하지만 setup이 무겁다. Detox는 RN에 특화돼 RN 팀에게는 압도적인 DX를 주지만 RN이 아니면 못 쓴다. Maestro는 YAML로 가장 빠르게 시작할 수 있지만 복잡한 분기/계산이 어렵다. 카카오뱅크는 백오피스 자동화에 Appium, 뱅킹 앱 회귀에 Detox, 마케팅 캠페인 검증에 Maestro를 병행 사용한다고 2025년 컨퍼런스에서 공유했다.
네트워크 모킹 비교: route vs intercept vs mock
E2E 테스트의 80%는 네트워크 응답 제어다. Playwright의 page.route()는 WebSocket까지 가로채고 fulfill/abort/continue가 가능하다. Cypress의 cy.intercept()는 XHR/fetch에 강력하지만 WebSocket은 별도 라이브러리가 필요하다. WebDriverIO/Selenium의 browser.mock()은 BiDi 기반으로 통일된다. MSW(Mock Service Worker)는 E2E와 단위 테스트 핸들러를 공유할 수 있다는 점이 강점이다.
비주얼 회귀: Percy, Chromatic, Applitools
기능 테스트가 통과해도 "버튼이 보라색이 됐다"는 회귀는 잡지 못한다. 비주얼 회귀 도구가 픽셀 diff와 AI 기반 변경 분류로 이 영역을 채운다. Percy(BrowserStack)는 GitHub PR과 자동 통합되고, Chromatic은 Storybook과 1급 통합으로 컴포넌트 단위 비주얼 테스트의 사실상 표준이다. Applitools Eyes는 "Visual AI"로 동적 콘텐츠를 자동 무시하는 알고리즘이 강점이다.
// Playwright + Percy 통합
import { test } from '@playwright/test'
import percySnapshot from '@percy/playwright'
test('homepage visual', async ({ page }) => {
await page.goto('/')
await page.waitForLoadState('networkidle')
await percySnapshot(page, 'Homepage @ 1280', { widths: [375, 768, 1280] })
})
라쿠텐(楽天)은 2024년부터 모든 E-Commerce 프론트엔드에 Percy를 적용해 평균 주당 8개의 회귀를 머지 전에 잡는다고 공식 엔지니어링 블로그에 공유했다.
클라우드 디바이스 팜: BrowserStack, Sauce Labs, LambdaTest
자체 디바이스 랩은 비용이 천문학적이다. BrowserStack은 3,000+ 실제 디바이스를 SaaS로 제공하며 Apple Vision Pro까지 커버한다. Sauce Labs는 엔터프라이즈 보안과 분석에 강점이 있고, LambdaTest는 가격 경쟁력으로 인디 개발자/스타트업에서 점유율을 높이고 있다. 2026년 기준 BrowserStack은 월 $99부터, Sauce Labs는 월 $149부터, LambdaTest는 월 $39부터 시작한다.
AI 코드젠과 자가 치유 테스트
2026년 가장 뜨거운 카테고리다. Playwright Codegen은 사용자의 브라우저 조작을 실시간 코드로 변환하고, Cypress Studio도 동일한 기능을 제공한다. Reflect.ai와 Mabl은 "자가 치유(self-healing)" 알고리즘으로 셀렉터가 깨졌을 때 텍스트/시각/DOM 컨텍스트로 자동 매칭해 테스트를 살린다. Chromatic은 AI Visual Diff로 인텐트 없는 변경(폰트 로딩 차이 등)을 자동 무시한다. Sybozu(사이보즈)는 2024년 Mabl을 도입해 비개발자 QA가 자동화를 작성하기 시작했다고 발표했다.
CI 통합: GitHub Actions 패턴
# .github/workflows/e2e.yml — Playwright 샤딩 패턴
name: E2E Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm exec playwright install --with-deps chromium
- run: pnpm exec playwright test --shard=${{ matrix.shard }}/4
env:
BASE_URL: http://localhost:3000
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report-${{ matrix.shard }}
path: playwright-report/
retention-days: 14
병렬화의 핵심은 idempotent 테스트 데이터다. 각 워커가 자기 사용자/주문을 만들고, 글로벌 setup에서 공유 리소스를 미리 준비한다. 카카오의 결제 팀은 worker별 prefix(worker-${process.env.TEST_WORKER_INDEX}-${uniqueId})를 모든 테스트 데이터에 붙여 충돌을 완전히 제거했다.
Vitest browser mode와 컴포넌트 테스트의 영역
E2E와 단위 테스트 사이에 "컴포넌트 테스트"가 있다. Cypress Component Testing, Playwright Component Testing(experimental), 그리고 2026년 GA된 Vitest 1.x의 browser mode가 이 영역의 강자다. Vitest browser mode는 실제 Chromium/WebKit에서 Vitest 테스트를 돌려, JSDOM의 한계(레이아웃, 픽셀, CSS) 없이 컴포넌트를 검증한다. Storybook과의 통합이 1급이다.
마이그레이션 전략: Cypress → Playwright
대규모 마이그레이션은 빅뱅보다 점진적으로 가야 한다. 토스 QA팀이 공유한 패턴은: (1) 새 테스트는 Playwright로 작성, (2) 기존 Cypress 테스트는 보존, (3) flaky 톱 20개부터 Playwright로 포팅, (4) cypress-to-playwright 변환기로 90% 자동 변환 후 손보기. 다섯째, 같은 CI에서 둘을 병행 실행하고 통계를 비교한다. 6개월에 걸쳐 800개 테스트를 마이그레이션했고, flakiness 비율이 8%에서 1.2%로 떨어졌다.
보안 & 시크릿 관리
E2E 테스트는 결국 운영 환경 비슷한 데이터에 접근한다. 시크릿을 코드에 박아두는 것은 SOC2/ISO27001 감사에서 즉시 실격이다. 패턴은: (1) GitHub Secrets/AWS Secrets Manager에서 동적 로드, (2) 테스트 전용 IDP(test-only tenant), (3) PII는 합성 데이터로 대체, (4) BrowserStack Local로 사내망 접근 시 mTLS. 카카오뱅크는 모든 E2E 테스트 계정을 매 실행마다 IAM 동적 발급으로 만들고 30분 후 자동 폐기한다.
어떤 도구를 골라야 하는가
요약하면: (1) 새 웹 프로젝트, 멀티 브라우저, 멀티 탭, 빠른 CI → Playwright. (2) 기존 Cypress 자산이 많고 DevTools 디버깅 친숙도가 중요 → Cypress 14+. (3) Java 엔터프라이즈, 100+ 브라우저 매트릭스 → Selenium 4. (4) 웹+모바일 통합 자동화 → WebDriverIO. (5) React Native만 → Detox. (6) iOS+Android+RN+Flutter 빠른 시작 → Maestro. (7) 폴리글랏 모바일 → Appium 2. 도구는 손에 익숙한 것을 쓰되, 2026년 신규 프로젝트는 Playwright + Maestro 조합이 가장 균형 잡혀 있다.
References
- Playwright Official Docs — https://playwright.dev/
- Cypress.io Documentation — https://docs.cypress.io/
- Selenium WebDriver — https://www.selenium.dev/documentation/
- WebDriverIO — https://webdriver.io/docs/gettingstarted
- Puppeteer — https://pptr.dev/
- Maestro Mobile UI Testing — https://maestro.mobile.dev/
- Detox: Gray box end-to-end testing — https://wix.github.io/Detox/
- Appium 2.0 — https://appium.io/docs/en/latest/
- W3C WebDriver BiDi Spec — https://www.w3.org/TR/webdriver-bidi/
- Chrome DevTools Protocol — https://chromedevtools.github.io/devtools-protocol/
- Percy Visual Testing — https://percy.io/
- Chromatic — https://www.chromatic.com/
- Applitools Eyes — https://applitools.com/
- BrowserStack — https://www.browserstack.com/
- Sauce Labs — https://saucelabs.com/
- TestCafe — https://testcafe.io/
- Nightwatch.js — https://nightwatchjs.org/
- Vitest Browser Mode — https://vitest.dev/guide/browser/
- ThoughtWorks Technology Radar — https://www.thoughtworks.com/radar
- Mercari Engineering Blog — https://engineering.mercari.com/