Playwright + Cloudflare Pages 조합으로 E2E 및 시각적 회귀 테스트 완전 자동화하기

프로덕션 서비스에서 코드를 수정할 때 가장 두려운 순간은 **“기존 기능이나 UI 레이아웃이 나도 모르게 깨지는 비의도적 회귀(Regression)”**입니다. 특히 다국어 지원 웹 사이트나 모바일 반응형 페이지는 사람이 수동으로 브라우저를 열어 테스트하기에 한계가 있습니다.
Cypress 대비 3배 이상 빠른 실행 속도, 크로스 브라우저(Chromium, WebKit, Firefox) 완벽 지원, 강력한 스냅샷 디버깅(Trace Viewer) 기능을 갖춘 Playwright는 현재 차세대 E2E 테스팅 도구의 대세로 자리 잡았습니다.
이 글에서는 Playwright와 Cloudflare Pages의 Preview Deployment, 그리고 GitHub Actions를 결합하여 PR(Pull Request)이 올려질 때마다 실제 에지(Edge) 환경에 배포된 URL을 대상으로 E2E 및 시각적 회귀(Visual Regression) 테스트를 완전 자동화하는 CI/CD 구축 파이프라인을 다룹니다.
핵심 요약
- Playwright 대세화 이유: Multi-tab, iFrame 지원, Auto-waiting, 브라우저 콘솔 및 네트워크 mock이 기본 탑재되어 Flaky 테스트 발생률이 매우 낮습니다.
- Cloudflare Pages Preview 연동: 로컬 dev 서버가 아닌, Cloudflare Pages 에지에 배포된 PR 전용 고유 Preview URL (
https://<hash>.pages.dev)을 대상으로 실제 사용자와 동일한 네트워크 조건에서 테스트를 검증합니다.- Visual Regression (시각적 회귀):
toHaveScreenshot()을 통해 픽셀 단위 UI 변경 사항을 비교하고, 픽셀 디프(Diff) 발생 시 GitHub Action Artifact로 차이점 보고서를 자동 업로드합니다.- 병렬 실행 및 샤딩 (Sharding): GitHub Actions Matrix 전략을 활용해 E2E 테스트 Suite를 N개의 러너로 병렬 분산하여 10분 넘는 실행 시간을 2분 이내로 단축시킵니다.
1. Cloudflare Pages + Playwright CI/CD 전체 아키텍처
[ Developer PR Push ]
│
▼
[ Step 1: Cloudflare Pages Preview Deploy ] ──► Deploy to https://pr-123.my-app.pages.dev
│
▼ (Wait for Deployment URL)
[ Step 2: GitHub Actions Playwright Runner ]
│ ──► Execute Chromium / WebKit / Firefox Tests against Preview URL
│ ──► Execute toHaveScreenshot() Visual Check
▼
[ Step 3: Test Report & Artifact Upload ] ──► Post PR Comment or Upload Trace File on Failure
2. Playwright 설정 파일 (playwright.config.ts)
Cloudflare Pages Preview URL 환경 변수를 수신하여 테스팅 대상을 동적으로 전환합니다.
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
const BASE_URL = process.env.PREVIEW_URL || 'http://localhost:4321';
export default defineConfig({
testDir: './e2e',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 4 : undefined,
reporter: [
['html', { open: 'never' }],
['github'],
],
use: {
baseURL: BASE_URL,
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'mobile-safari',
use: { ...devices['iPhone 14'] },
},
],
});
3. Visual Regression 테스트 코드 (e2e/visual.spec.ts)
import { test, expect } from '@playwright/test';
test.describe('시각적 회귀 및 주요 랜딩 검증', () => {
test('메인 홈 페이지 스냅샷 비교', async ({ page }) => {
await page.goto('/');
// 폰트 로딩 및 애니메이션 완료 대기
await page.waitForLoadState('networkidle');
// 픽셀 단위 Visual Regression 비교 (최초 실행 시 베이스라인 생성)
await expect(page).toHaveScreenshot('homepage-baseline.png', {
maxDiffPixelRatio: 0.01, // 1% 이하 미세 변경 허용
fullPage: true,
});
});
test('다크모드 스위처 및 검색 모달 E2E 검증', async ({ page }) => {
await page.goto('/');
// 검색 모달 열기
await page.click('button[aria-label="Search"]');
await expect(page.locator('#search-modal')).toBeVisible();
// 키워드 입력 후 결과 노출 확인
await page.fill('#search-input', 'Playwright');
await expect(page.locator('.search-result-item')).toHaveCount(1);
});
});
4. GitHub Actions CI 파이프라인 (.github/workflows/playwright.yml)
Cloudflare Pages deployment 완료 이벤트를 수신하여 Playwright를 돌리는 GitHub Actions 구성입니다.
name: Playwright E2E & Visual Regression Test
on:
deployment_status:
jobs:
e2e-test:
# Cloudflare Pages Preview 배포 성공 시에만 트리거
if: github.event.deployment_status.state == 'success' && github.event.deployment_status.environment == 'Preview'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright Tests against Preview URL
env:
PREVIEW_URL: ${{ github.event.deployment_status.target_url }}
run: npx playwright test
- name: Upload Playwright Report on Failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
retention-days: 14
5. E2E 프레임워크 3종 성능 비교표
| 비교 지표 | Cypress (v13) | Selenium | Playwright (v1.48+) |
|---|---|---|---|
| 테스트 실행 속도 | 보통 | 느림 | 매우 빠름 (WebSockets 프로토콜) |
| Multi-tab & Domain 지원 | 제한적 | 가능 | 완벽 지원 |
| Auto-waiting 및 Flaky 방지 | 보통 | 직접 구현 필요 | 기본 탑재 (자동 대기) |
| Visual Snapshot 비교 | 플러그인 필요 | 플러그인 필요 | toHaveScreenshot() 기본 탑재 |
| Trace Viewer 디버깅 | 없음 | 없음 | 타임라인별 DOM & Network 완전 복원 |
6. 테스트 안정성을 높이는 실전 팁
networkidle상태 조심하기: 외부 애널리틱스 스크립트가 핑을 쏠 경우networkidle대기가 타임아웃을 일으킬 수 있습니다. 특정 주요 UI 요소의toBeVisible()검증을 우선하세요.- Playwright Trace Viewer 활용: CI 테스트가 실패했을 때 GitHub Artifact로 다운로드받은
trace.zip을npx playwright show-trace trace.zip으로 열면, 실패한 정확한 찰나의 DOM과 콘솔 로그를 액션 단위로 감상할 수 있습니다.
Playwright와 Cloudflare Pages Preview 배포를 연동하면 프론트엔드 팀은 QA 공수를 90% 이상 절감하면서 프로덕션 버그 방어막을 구축할 수 있습니다.