React/Next.js 애플리케이션을 위한 Playwright E2E 테스트 실전: 안정적인 UI 보장하기
프론트엔드 개발자가 React/Next.js 프로젝트를 위한 Playwright E2E 테스트 실전 경험을 공유합니다. 크로스 브라우저 테스트, 자동화, 코드 예제, 비교 테이블, 핵심 정리 및 체크리스트를 포함하여 안정적인 UI 보장 방법을 알아봅니다.
프론트엔드 개발자의 Playwright E2E 테스트 실전 가이드
1. "이거 되던데요?" - QA와 개발자 간의 끝없는 줄다리기
"분명히 제 로컬에서는 잘 돌아갔는데요?" QA 팀으로부터 버그 리포트를 받을 때마다 개발자들은 이 말을 입에 달고 삽니다. 운영 환경이나 특정 브라우저, 혹은 복잡한 사용자 시나리오 하에서는 예상치 못한 문제가 발생하는 경우가 허다하죠. 특히 React나 Next.js 같은 SPA(Single Page Application) 프레임워크를 사용하면, 클라이언트 측에서 동적으로 UI가 변경되고 상태 관리가 복잡해지면서 이러한 문제는 더욱 빈번하게 발생합니다. 수동 테스트는 시간과 비용이 많이 들 뿐만 아니라, 개발자의 숙련도나 컨디션에 따라 결과가 달라질 수도 있습니다. 그렇다면 어떻게 하면 이러한 비효율적인 반복 작업에서 벗어나, 안정적이고 예측 가능한 UI를 보장할 수 있을까요? 바로 E2E(End-to-End) 테스트 자동화입니다. 그리고 그 중심에 강력한 도구인 Playwright가 있습니다.
2. Playwright, 왜 써야 할까? (feat. React/Next.js)
Playwright는 Microsoft에서 개발한 Node.js 라이브러리로, Chromium(Chrome, Edge), Firefox, WebKit(Safari) 등 주요 브라우저에서 웹 애플리케이션을 자동화하고 테스트할 수 있게 해줍니다. 특히 React/Next.js와 같은 최신 프론트엔드 기술 스택과 훌륭한 궁합을 자랑합니다.
2.1. Playwright의 강력한 기능들
- 크로스 브라우저 테스트: 단 한 번의 코드로 여러 브라우저에서 동일한 테스트를 실행할 수 있습니다. 더 이상 브라우저별 테스트를 위한 별도의 환경 구축이 필요 없습니다.
- 실행 자동화 및 재현성: JavaScript/TypeScript 코드로 테스트 시나리오를 작성하므로, 사람이 직접 조작하는 것보다 훨씬 빠르고 일관된 결과를 얻을 수 있습니다. 또한, 비디오 녹화, 스크린샷, 실행 로그 등을 통해 실패 원인을 명확하게 파악하고 재현하기 용이합니다.
- 강력한 선택자(Selector) 지원: CSS 선택자뿐만 아니라 텍스트 내용,
aria-label등 다양한 방법으로 DOM 요소를 정확하게 선택할 수 있어, 변경에 강한 테스트 코드를 작성할 수 있습니다. - 비동기 작업 처리: Playwright는 비동기 작업을 자동으로 기다려주므로,
setTimeout과 같은 꼼수를 사용하지 않고도 안정적인 테스트가 가능합니다. - Context Isolation: 각 테스트는 독립적인 브라우저 컨텍스트에서 실행되어, 테스트 간의 의존성을 최소화하고 격리성을 보장합니다.
2.2. Playwright vs Cypress vs Selenium (간단 비교)
| 특징 | Playwright | Cypress | Selenium |
|---|---|---|---|
| 브라우저 지원 | Chromium, Firefox, WebKit (모두) | Chromium 계열 (Chrome, Edge, Electron) | Chromium, Firefox, Safari, Edge 등 (별도 설치) |
| 아키텍처 | 브라우저 네이티브 프로토콜 사용 (DevTools) | 브라우저 내부에서 실행 (In-browser) | WebDriver 프로토콜 사용 |
| 실행 속도 | 빠름 | 매우 빠름 (상대적으로) | 느림 |
| 비동기 처리 | 자동 대기, 강력한 API | 자동 대기 | 별도 처리 필요 (explicit waits) |
| 크로스 브라우저 | 네이티브 지원 | 제한적 (Safari 지원 예정) | 설정 복잡 |
| 설치/설정 | 간편 | 간편 | 복잡 (WebDriver, 브라우저 드라이버) |
| 주요 언어 | JS/TS, Python, Java, .NET | JS/TS | Java, Python, C#, Ruby 등 |
2.3. React/Next.js 프로젝트에 Playwright 적용하기
1. 설치:
1npm init playwright@latest my-e2e-tests -- --quickstart 2# 또는 3yarn create playwright my-e2e-tests -- --quickstart
--quickstart 옵션은 기본적인 설정 파일을 생성해줍니다. package.json에 test 스크립트가 추가되고, playwright.config.ts와 tests 폴더가 생성됩니다.
2. 기본 테스트 코드 작성 (예: 로그인 기능):
tests/auth.spec.ts 파일을 생성하고 다음 코드를 작성합니다.
1import { test, expect } from '@playwright/test'; 2 3test.describe('Authentication', () => { 4 test('should allow a user to log in', async ({ page }) => { 5 // 1. 로그인 페이지로 이동 6 await page.goto('/login'); 7 8 // 2. 이메일과 비밀번호 입력 9 await page.fill('input[name="email"]', 'test@example.com'); 10 await page.fill('input[name="password"]', 'password123'); 11 12 // 3. 로그인 버튼 클릭 13 await page.click('button[type="submit"]'); 14 15 // 4. 로그인 성공 후 대시보드 페이지 확인 16 // URL이 변경되었는지 확인하거나, 특정 요소가 보이는지 확인할 수 있습니다. 17 await expect(page).toHaveURL('/dashboard'); 18 await expect(page.locator('h1')).toContainText('Welcome'); 19 }); 20 21 test('should show an error message for invalid credentials', async ({ page }) => { 22 await page.goto('/login'); 23 await page.fill('input[name="email"]', 'wrong@example.com'); 24 await page.fill('input[name="password"]', 'wrongpassword'); 25 await page.click('button[type="submit"]'); 26 27 // 오류 메시지가 표시되는지 확인 28 await expect(page.locator('.error-message')).toBeVisible(); 29 await expect(page.locator('.error-message')).toHaveText('Invalid email or password.'); 30 }); 31});
3. Playwright 설정 (playwright.config.ts):
Next.js 프로젝트의 경우, baseURL을 설정하여 매번 /login과 같이 상대 경로를 입력하는 번거로움을 줄일 수 있습니다.
1import { defineConfig, devices } from '@playwright/test'; 2 3export default defineConfig({ 4 testDir: './tests', 5 /* Base URL to use in actions like `await page.goto('/')`. */ 6 // Next.js 개발 서버 주소 또는 운영 환경 주소 7 baseURL: 'http://localhost:3000', 8 9 /* Run tests in parallel */ 10 // fullyParallel: true, 11 12 /* Reporter to use. See https://playwright.dev/docs/test-reporters */ 13 reporter: 'html', 14 /* Shared settings for all the projects below. See https://playwright.dev/docs/api-configuration. */ 15 use: { 16 /* Base URL to use in actions like `await page.goto('/')`. */ 17 // baseURL: 'http://localhost:3000', 18 19 /* Collect trace when an action or an assertion fails. */ 20 trace: 'on-first-retry', 21 }, 22 23 /* Configure projects for major browsers */ 24 projects: [ 25 { 26 name: 'chromium', 27 use: { ...devices['Desktop Chrome'] }, 28 }, 29 30 { 31 name: 'firefox', 32 use: { ...devices['Desktop Firefox'] }, 33 }, 34 35 { 36 name: 'webkit', 37 use: { ...devices['Desktop Safari'] }, 38 }, 39 40 /* Test against mobile viewports. */ 41 // { 42 // name: 'Mobile Chrome', 43 // use: { ...devices['Pixel 5'] }, 44 // }, 45 // { 46 // name: 'Mobile Safari', 47 // use: { ...devices['iPhone 12'] }, 48 // }, 49 50 /* Test against branded browsers. */ 51 // { 52 // name: 'Microsoft Edge', 53 // use: { ...devices['Desktop Edge'] }, 54 // }, 55 // { 56 // name: 'Google Chrome', 57 // use: { ...devices['Desktop Chrome'] }, 58 // }, 59 ], 60 61 /* Run your local dev server before starting the tests */ 62 // webServer: { 63 // command: 'npm run start', 64 // url: 'http://127.0.0.1:3000', 65 // reuseExistingServer: !process.env.CI, 66 // }, 67}); 68
4. 테스트 실행:
1npm test 2# 또는 3yarn test
5. Playwright Inspector 활용:
테스트 디버깅 시 Playwright Inspector를 사용하면 코드 실행 과정을 시각적으로 추적하고, 요소를 쉽게 선택하며, 코드를 생성하는 등 매우 유용합니다.
1npx playwright test --ui
2.4. 동적 UI 및 비동기 처리 테스트 예제
React에서 흔히 볼 수 있는 동적 렌더링이나 API 호출 후 UI 업데이트 로직을 테스트하는 방법입니다.
1// tests/dynamic-ui.spec.ts 2import { test, expect } from '@playwright/test'; 3 4test.describe('Dynamic Content Loading', () => { 5 test('should display fetched data after button click', async ({ page }) => { 6 await page.goto('/'); // 메인 페이지 7 8 // 'Load Data' 버튼이 보이고 클릭 가능할 때까지 기다립니다. 9 const loadButton = page.getByRole('button', { name: 'Load Data' }); 10 await expect(loadButton).toBeVisible(); 11 await loadButton.click(); 12 13 // 데이터 로딩 인디케이터가 사라질 때까지 기다립니다. 14 await expect(page.locator('.loading-spinner')).not.toBeVisible(); 15 16 // 데이터가 성공적으로 표시되는지 확인합니다. 17 // 'data-testid' 속성을 사용하는 것이 CSS 클래스 변경에 덜 민감합니다. 18 const dataElement = page.locator('[data-testid="user-list"]'); 19 await expect(dataElement).toBeVisible(); 20 await expect(dataElement).toContainText('John Doe'); // 특정 텍스트 포함 여부 확인 21 }); 22 23 test('should show error message when data fetch fails', async ({ page }) => { 24 // API 호출을 Mocking하여 실패 시나리오를 테스트할 수도 있습니다. 25 // (실제 API 호출을 막고 응답을 제어) 26 await page.route('**/api/users', route => 27 route.fulfill({ status: 500, contentType: 'application/json', body: JSON.stringify({ message: 'Server Error' }) }) 28 ); 29 30 await page.goto('/'); 31 await page.getByRole('button', { name: 'Load Data' }).click(); 32 33 // 오류 메시지가 표시되는지 확인 34 await expect(page.locator('.error-message')).toBeVisible(); 35 await expect(page.locator('.error-message')).toHaveText('Failed to load data. Please try again.'); 36 }); 37});
핵심: Playwright의 page.waitForSelector(), page.waitForNavigation(), page.route() 등의 API를 활용하면 동적인 UI 변화와 비동기 작업 완료를 안정적으로 감지하고 테스트할 수 있습니다. 특히 getByRole, getByLabelText, data-testid와 같은 접근성 및 테스트 용이성을 고려한 선택자를 사용하는 것이 좋습니다.
3. 실전 E2E 테스트 구축을 위한 핵심 정리 및 체크리스트
Playwright를 활용한 E2E 테스트는 단순히 버그를 잡는 것을 넘어, 개발 프로세스의 안정성을 높이고 팀 전체의 자신감을 향상시키는 강력한 도구입니다. 특히 React/Next.js와 같이 빠르게 변화하는 프론트엔드 환경에서는 필수적입니다.
핵심 요약:
- E2E 테스트는 사용자 시나리오 전반을 검증하여 실제 운영 환경에서의 문제를 최소화합니다.
- Playwright는 크로스 브라우저 지원, 빠른 실행 속도, 강력한 API를 바탕으로 효율적인 E2E 테스트 환경을 제공합니다.
- React/Next.js 프로젝트에 Playwright를 통합하면 개발 생산성과 애플리케이션 품질을 동시에 높일 수 있습니다.
page.goto(),fill(),click(),expect()와 같은 기본 API와waitForSelector(),route()등을 활용하여 복잡한 UI 흐름과 비동기 작업을 테스트합니다.- 테스트 안정성을 위해
data-testid나 접근성 속성을 활용한 선택자 사용을 권장합니다.
E2E 테스트 구축 체크리스트:
- Playwright 기본 설치 및 설정 완료 (
playwright.config.ts) -
baseURL설정으로 개발/운영 환경 테스트 경로 통일 - 주요 사용자 흐름 (회원가입, 로그인, 상품 구매 등)에 대한 E2E 테스트 케이스 작성
- API 호출 Mocking/Stubbing을 통한 엣지 케이스 및 오류 시나리오 테스트
- 동적 UI 업데이트 및 비동기 작업 완료 대기 로직 포함
- 브라우저별 테스트 실행 및 결과 확인
- CI/CD 파이프라인에 E2E 테스트 자동 통합
- 정기적인 테스트 코드 리뷰 및 유지보수
Playwright와 함께라면 "이거 되던데요?"라는 말 대신 "모든 브라우저에서 완벽하게 작동합니다!"라고 자신 있게 말할 수 있을 것입니다. 지금 바로 여러분의 프로젝트에 Playwright E2E 테스트를 도입해보세요.