튜토리얼

Playwright E2E 테스트 환경 구축: 웹 자동화 실전 가이드

강코의 코딩 일기 2026. 3. 18. 18:03

복잡한 웹 애플리케이션의 E2E 테스트, Playwright로 간편하게 자동화하세요. 환경 설정부터 실제 테스트 코드 작성까지 단계별 가이드를 통해 안정적인 테스트 워크플로우를 구축하는 방법을 알아봅니다.

안녕하세요, 웹 개발의 복잡성 속에서 안정적인 서비스를 유지하기 위해 고군분투하는 모든 개발자분들께 질문 하나 드립니다. 여러분의 웹 애플리케이션은 사용자에게 도달하기 전까지 얼마나 많은 테스트 단계를 거치나요? 혹시 중요한 기능이 배포될 때마다 수동 테스트에 많은 시간을 할애하고 계시지는 않나요? 사용자 경험에 직결되는 엔드-투-엔드(E2E) 테스트는 서비스의 신뢰성을 보장하는 핵심 요소이지만, 구축과 유지보수의 어려움으로 인해 많은 개발팀이 고민하는 지점이기도 합니다.

이 글에서는 이러한 고민을 해결하고, Playwright를 활용하여 E2E 테스트 환경을 효율적으로 구축하고 웹 자동화를 실현하는 실전 가이드를 제시합니다. Playwright는 강력한 기능과 높은 신뢰성으로 빠르게 주목받고 있는 테스트 자동화 프레임워크입니다. 이 가이드를 통해 여러분은 Playwright의 매력을 발견하고, 더 견고하고 안정적인 웹 서비스를 제공하는 첫걸음을 내딛게 될 것입니다.

Playwright를 활용한 E2E 테스트 환경 구축 및 자동화 실전 가이드 - covid, testing, corona test, covid-19, corona, coronavirus, sars-cov-2, concept, quick test, pcr, pcr-test, covid test, covid, covid, covid, covid, covid, corona, corona, covid test, covid test, covid test

Image by analogicus on Pixabay

E2E 테스트, 왜 Playwright인가?

웹 애플리케이션 개발에 있어 E2E 테스트는 실제 사용자의 흐름을 시뮬레이션하여 시스템 전체의 동작을 검증하는 매우 중요한 과정입니다. 하지만 동시에 가장 구축하기 어렵고, 테스트 실패 원인을 파악하기 복잡하며, 유지보수 비용이 높은 테스트 유형으로도 알려져 있습니다. 과거에는 Selenium과 같은 도구들이 주로 사용되었으나, 최근에는 Playwright가 여러 장점을 내세우며 새로운 대안으로 떠오르고 있습니다.

Playwright의 독보적인 강점

Playwright가 E2E 테스트 자동화 시장에서 강력한 존재감을 드러내는 이유는 다음과 같은 핵심적인 장점들 때문입니다.

  • 다양한 브라우저 지원: Chromium (Chrome, Edge), Firefox, WebKit (Safari) 등 모든 주요 브라우저 엔진을 단일 API로 제어할 수 있습니다. 이는 크로스 브라우징 테스트를 훨씬 용이하게 만듭니다.
  • 자동 대기(Auto-waiting): 요소를 찾거나 액션을 수행하기 전에 Playwright가 자동으로 해당 요소가 준비될 때까지 기다립니다. 이로 인해 불안정한 테스트(Flaky Tests)의 발생 가능성이 현저히 줄어듭니다.
  • 병렬 실행: 여러 테스트를 동시에, 심지어 여러 워커 프로세스에서 병렬로 실행할 수 있어 테스트 시간을 대폭 단축시킵니다.
  • 테스트 격리: 각 테스트가 독립적인 브라우저 컨텍스트에서 실행되어, 이전 테스트의 상태가 다음 테스트에 영향을 미치지 않도록 보장합니다.
  • 풍부한 기능: 스크린샷, 비디오 녹화, 네트워크 인터셉션, 파일 업로드/다운로드, 로컬 스토리지/세션 스토리지 제어 등 웹 자동화에 필요한 거의 모든 기능을 제공합니다.
  • 개발자 친화적 도구: Codegen (테스트 코드 자동 생성), Playwright Inspector (테스트 디버깅 UI) 등 개발자의 생산성을 높이는 강력한 도구를 제공합니다.

이러한 장점들은 Playwright를 단순한 테스트 도구를 넘어, 웹 애플리케이션의 품질과 안정성을 혁신하는 강력한 솔루션으로 만듭니다. 이제 Playwright를 직접 경험하며 E2E 테스트 환경을 구축하는 방법을 자세히 살펴보겠습니다.

Playwright 환경 구축 시작하기

Playwright를 시작하는 것은 매우 간단합니다. 몇 가지 명령어로 필요한 모든 것을 설치하고, 기본적인 프로젝트 구조를 설정할 수 있습니다. 여기서는 Node.js 환경을 기준으로 설명합니다.

1. Node.js 및 npm/yarn 준비

Playwright는 Node.js 런타임을 기반으로 동작합니다. 아직 설치되어 있지 않다면, 공식 웹사이트에서 Node.js를 설치해 주세요. npm 또는 yarn은 Node.js 설치 시 함께 제공되거나 별도로 설치할 수 있습니다.

# Node.js 버전 확인 (v14 이상 권장)
node -v
npm -v

2. Playwright 설치 및 초기화

새로운 프로젝트 폴더를 만들고, 해당 폴더 내에서 Playwright를 설치합니다. Playwright는 설치 과정에서 필요한 브라우저 바이너리(Chromium, Firefox, WebKit)를 자동으로 다운로드합니다.

# 프로젝트 폴더 생성 및 이동
mkdir playwright-e2e-guide
cd playwright-e2e-guide

# npm을 사용하여 Playwright 설치 및 초기화
npm init playwright@latest .

# 또는 yarn을 사용하는 경우
# yarn create playwright .

초기화 명령을 실행하면 몇 가지 질문이 나옵니다.

  • Do you want to use TypeScript or JavaScript? (TypeScript 사용을 권장합니다.)
  • Where to put your end-to-end tests? (기본값인 tests/를 사용하거나 원하는 경로를 지정합니다.)
  • Add a GitHub Actions workflow? (CI/CD 연동을 위해 Yes를 선택할 수 있습니다. 나중에 직접 설정할 수도 있습니다.)
  • Install Playwright browsers (Chromium, Firefox, WebKit)? (Yes를 선택하여 필요한 브라우저를 다운로드합니다.)

설치가 완료되면, package.json 파일에 Playwright 의존성이 추가되고, playwright.config.ts (또는 .js) 설정 파일과 예시 테스트 파일이 생성됩니다. 프로젝트 구조는 대략 다음과 같을 것입니다.

playwright-e2e-guide/
├── node_modules/
├── tests/
│   └── example.spec.ts  # 예시 테스트 파일
├── playwright.config.ts # Playwright 설정 파일
├── package.json
├── package-lock.json
└── tsconfig.json        # TypeScript를 선택한 경우

핵심 기능으로 Playwright 둘러보기

환경 구축을 마쳤으니, 이제 Playwright의 핵심 기능들을 살펴보며 실제 웹 자동화가 어떻게 이루어지는지 알아보겠습니다. Playwright는 사용자 액션을 모방하고 웹 페이지와 상호작용하는 데 필요한 강력한 API를 제공합니다.

1. Locator를 이용한 요소 찾기

웹 페이지의 특정 요소를 찾아 상호작용하는 것은 E2E 테스트의 기본입니다. Playwright는 다양한 방법으로 요소를 찾을 수 있는 Locator API를 제공하며, 이는 웹 요소의 변경에도 강력한 내구성을 가집니다.

메서드 설명 예시
page.getByText() 텍스트 내용으로 요소 찾기 page.getByText('로그인')
page.getByRole() 접근성 역할을 기반으로 요소 찾기 page.getByRole('button', { name: 'Submit' })
page.getByLabel() <label>의 텍스트로 입력 필드 찾기 page.getByLabel('이메일')
page.getByPlaceholder() 플레이스홀더 텍스트로 입력 필드 찾기 page.getByPlaceholder('비밀번호 입력')
page.locator() CSS 또는 XPath 셀렉터로 요소 찾기 (가장 일반적) page.locator('#username'), page.locator('.submit-button')
// 예시: 사용자 이름 입력 필드에 값 입력하기
await page.getByLabel('사용자 이름').fill('testuser');

// 예시: 로그인 버튼 클릭하기
await page.getByRole('button', { name: '로그인' }).click();

2. 사용자 액션 시뮬레이션

Playwright는 클릭, 입력, 드래그 등 실제 사용자가 수행하는 모든 액션을 모방할 수 있는 직관적인 API를 제공합니다.

  • click(): 요소 클릭
  • fill(value): 입력 필드에 텍스트 입력
  • press(key): 키보드 키 누르기 (예: 'Enter', 'Tab')
  • check()/uncheck(): 체크박스/라디오 버튼 선택/해제
  • selectOption(value): 드롭다운 메뉴에서 옵션 선택
  • hover(): 요소에 마우스 오버
// 예시: 검색창에 'Playwright' 입력 후 엔터 키 누르기
await page.locator('#search-input').fill('Playwright');
await page.locator('#search-input').press('Enter');

// 예시: 약관 동의 체크박스 선택하기
await page.locator('#terms-checkbox').check();

3. Assertions (검증)

테스트의 핵심은 특정 액션 후 예상하는 결과가 나타났는지 검증하는 것입니다. Playwright는 expect API를 통해 다양한 어설션을 제공합니다.

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

test('로그인 성공 후 대시보드 페이지로 이동해야 한다', async ({ page }) => {
    await page.goto('http://localhost:3000/login');
    await page.getByLabel('사용자 이름').fill('validuser');
    await page.getByLabel('비밀번호').fill('password123');
    await page.getByRole('button', { name: '로그인' }).click();

    // URL이 변경되었는지 검증
    await expect(page).toHaveURL('http://localhost:3000/dashboard');
    // 특정 텍스트가 페이지에 나타났는지 검증
    await expect(page.getByText('환영합니다, validuser님!')).toBeVisible();
});

주요 expect 메서드:

  • toBeVisible(): 요소가 보이는지
  • toHaveText(text): 요소의 텍스트가 일치하는지
  • toHaveValue(value): 입력 필드의 값이 일치하는지
  • toHaveURL(url): 현재 URL이 일치하는지
  • toHaveCount(count): 요소의 개수가 일치하는지
  • toBeChecked(): 체크박스/라디오 버튼이 선택되었는지
Playwright를 활용한 E2E 테스트 환경 구축 및 자동화 실전 가이드 - test, virus, coronavirus, self-test, covid-19, infection, lock down, hygiene, transmission, shutdown, pandemic, test, test, test, test, test, virus, virus, virus, virus, coronavirus, coronavirus, coronavirus, coronavirus, covid-19, covid-19, covid-19, covid-19, pandemic, pandemic

Image by Alexandra_Koch on Pixabay

실전! Playwright 테스트 코드 작성

이제 기본적인 Playwright API를 이해했으니, 실제 웹 애플리케이션의 E2E 테스트 시나리오를 코드로 구현해 보겠습니다. 여기서는 간단한 로그인 및 게시글 작성 시나리오를 예시로 들어 설명합니다.

먼저, tests/ 폴더 내에 auth.spec.ts 파일을 생성합니다.

// tests/auth.spec.ts
import { test, expect } from '@playwright/test';

test.describe('인증 기능 테스트', () => {
    const BASE_URL = 'http://localhost:3000'; // 테스트할 애플리케이션의 기본 URL

    test('성공적인 로그인 후 대시보드로 이동해야 한다', async ({ page }) => {
        await page.goto(`${BASE_URL}/login`);

        // 사용자 이름과 비밀번호 입력
        await page.getByLabel('사용자 이름').fill('testuser');
        await page.getByLabel('비밀번호').fill('password123');

        // 로그인 버튼 클릭
        await page.getByRole('button', { name: '로그인' }).click();

        // 대시보드 페이지로 이동했는지 확인
        await expect(page).toHaveURL(`${BASE_URL}/dashboard`);
        // 환영 메시지가 보이는지 확인
        await expect(page.getByText('환영합니다, testuser님!')).toBeVisible();
    });

    test('잘못된 비밀번호로 로그인 시도 시 에러 메시지가 표시되어야 한다', async ({ page }) => {
        await page.goto(`${BASE_URL}/login`);

        // 잘못된 비밀번호 입력
        await page.getByLabel('사용자 이름').fill('testuser');
        await page.getByLabel('비밀번호').fill('wrongpassword');

        // 로그인 버튼 클릭
        await page.getByRole('button', { name: '로그인' }).click();

        // 에러 메시지가 보이는지 확인
        await expect(page.getByText('잘못된 사용자 이름 또는 비밀번호입니다.')).toBeVisible();
        // URL이 변경되지 않았는지 확인 (여전히 로그인 페이지)
        await expect(page).toHaveURL(`${BASE_URL}/login`);
    });

    test('로그아웃 기능이 정상적으로 동작해야 한다', async ({ page }) => {
        // 먼저 로그인 수행 (setup 단계에서 처리할 수도 있습니다)
        await page.goto(`${BASE_URL}/login`);
        await page.getByLabel('사용자 이름').fill('testuser');
        await page.getByLabel('비밀번호').fill('password123');
        await page.getByRole('button', { name: '로그인' }).click();
        await expect(page).toHaveURL(`${BASE_URL}/dashboard`);

        // 로그아웃 버튼 클릭
        await page.getByRole('button', { name: '로그아웃' }).click();

        // 로그인 페이지로 돌아왔는지 확인
        await expect(page).toHaveURL(`${BASE_URL}/login`);
        // 로그인 폼이 다시 보이는지 확인
        await expect(page.getByText('로그인')).toBeVisible();
    });
});

이 코드는 test.describe를 사용하여 관련된 테스트들을 그룹화하고, 각 테스트는 독립적인 page 객체를 통해 브라우저와 상호작용합니다. BASE_URL을 변수로 관리하여 유지보수성을 높였습니다.

테스트를 실행하려면 터미널에서 다음 명령어를 입력합니다.

npx playwright test

이 명령어는 기본적으로 모든 브라우저(Chromium, Firefox, WebKit)에서 테스트를 병렬로 실행합니다. 특정 브라우저에서만 실행하고 싶다면 --project 옵션을 사용합니다.

# Chromium에서만 실행
npx playwright test --project=chromium

# 테스트 디버깅 UI (Playwright Inspector) 열기
npx playwright test --ui

--ui 옵션은 Playwright Inspector를 실행하여 각 테스트의 단계별 실행을 시각적으로 확인하고 디버깅할 수 있게 해주는 강력한 도구입니다. 테스트 실패 시 원인을 파악하는 데 매우 유용합니다.

테스트 워크플로우 효율화 전략

단순히 테스트 코드를 작성하는 것을 넘어, E2E 테스트 워크플로우를 효율적으로 관리하는 것은 장기적인 관점에서 매우 중요합니다. Playwright는 이러한 효율성을 위한 다양한 기능을 제공합니다.

1. 테스트 환경 설정 (playwright.config.ts)

playwright.config.ts 파일은 Playwright 테스트 실행 방식에 대한 모든 설정을 담고 있습니다. 여기에서 병렬 실행, 브라우저 설정, 기본 URL 등을 구성할 수 있습니다.

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
    testDir: './tests', // 테스트 파일이 위치한 디렉토리
    fullyParallel: true, // 모든 테스트를 병렬로 실행
    forbidOnly: !!process.env.CI, // CI 환경에서 .only 테스트 금지
    retries: process.env.CI ? 2 : 0, // CI 환경에서 실패한 테스트 2번 재시도
    workers: process.env.CI ? 1 : undefined, // CI 환경에서 워커 수 제한 (리소스 절약)
    reporter: 'html', // HTML 레포터 사용

    use: {
        baseURL: 'http://localhost:3000', // 테스트할 애플리케이션의 기본 URL
        trace: 'on-first-retry', // 첫 번째 재시도 실패 시 트레이스 기록
    },

    projects: [
        {
            name: 'chromium',
            use: { ...devices['Desktop Chrome'] },
        },
        {
            name: 'firefox',
            use: { ...devices['Desktop Firefox'] },
        },
        {
            name: 'webkit',
            use: { ...devices['Desktop Safari'] },
        },
        // 모바일 환경 테스트 추가
        {
            name: 'Mobile Chrome',
            use: { ...devices['Pixel 5'] },
        },
        {
            name: 'Mobile Safari',
            use: { ...devices['iPhone 12'] },
        },
    ],
    webServer: {
        command: 'npm run start', // 테스트 전에 웹 서버 실행 (Next.js, React 앱 등)
        url: 'http://localhost:3000',
        reuseExistingServer: !process.env.CI, // CI가 아니면 기존 서버 재사용
    },
});

위 설정은 병렬 실행을 통해 테스트 시간을 단축하고, HTML 레포터를 통해 가독성 높은 테스트 결과를 제공하며, CI 환경에서의 재시도 정책을 정의하여 테스트 안정성을 높이는 방법을 보여줍니다. 또한, webServer 설정을 통해 테스트 전에 프론트엔드 개발 서버를 자동으로 실행하도록 구성할 수 있어 매우 편리합니다.

2. 테스트 결과 보고서 (HTML Reporter)

Playwright는 기본적으로 CLI에 테스트 결과를 출력하지만, reporter: 'html' 설정을 사용하면 시각적으로 풍부한 HTML 보고서를 생성합니다. 테스트 실행 후 다음 명령어로 보고서를 열 수 있습니다.

npx playwright show-report

이 보고서는 각 테스트의 성공/실패 여부, 실행 시간, 스크린샷, 비디오, 트레이스 파일 등을 포함하여 실패 원인을 빠르게 분석하는 데 큰 도움을 줍니다.

Playwright를 활용한 E2E 테스트 환경 구축 및 자동화 실전 가이드 - coronavirus, mass testing, covid-19, slovakia, swab test, swab testing, pandemic, new normal, antigen test, man, testing, coronavirus test, medical worker, healthcare professional, healthcare worker, face masks, žilina, slovakia, slovakia, slovakia, swab test, swab test, swab test, swab test, swab test, pandemic, antigen test, antigen test, antigen test, testing, testing, coronavirus test, coronavirus test, medical worker, healthcare professional, healthcare worker, healthcare worker

Image by lukasmilan on Pixabay

CI/CD 파이프라인 연동

E2E 테스트CI/CD(지속적 통합/지속적 배포) 파이프라인의 필수적인 부분입니다. 코드가 변경될 때마다 자동으로 테스트를 실행하여 버그를 조기에 발견하고, 안정적인 배포를 보장합니다. Playwright는 GitHub Actions와 같은 CI/CD 도구와 쉽게 연동됩니다.

GitHub Actions 예시

프로젝트 루트에 .github/workflows/playwright.yml 파일을 생성하고 다음 내용을 추가합니다.

# .github/workflows/playwright.yml
name: Playwright E2E Tests

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-node@v4
      with:
        node-version: 18

    - name: Install dependencies
      run: npm ci

    - name: Install Playwright browsers
      run: npx playwright install --with-deps

    - name: Start web server (if applicable)
      run: npm run start & # 백그라운드에서 웹 서버 실행 (예: 'npm run start' 스크립트가 앱을 띄운다고 가정)
      env:
        PORT: 3000 # 웹 서버가 사용할 포트
      continue-on-error: true # 서버 시작 실패 시 테스트는 계속 진행하지 않도록 주의

    - name: Run Playwright tests
      run: npx playwright test

    - uses: actions/upload-artifact@v4
      if: always()
      with:
        name: playwright-report
        path: playwright-report/
        retention-days: 30

이 워크플로우는 main 또는 develop 브랜치에 코드가 푸시되거나 풀 리퀘스트가 발생할 때마다 자동으로 실행됩니다. Playwright 브라우저를 설치하고, 웹 서버를 백그라운드에서 실행한 다음, Playwright 테스트를 수행합니다. 마지막으로, 테스트 보고서를 아티팩트로 업로드하여 GitHub Actions 인터페이스에서 결과를 확인할 수 있도록 합니다.

이러한 CI/CD 연동을 통해 개발팀은 코드 변경이 서비스에 미치는 영향을 즉각적으로 파악하고, 안정적인 배포 주기를 유지할 수 있습니다.

마무리: 견고한 웹 서비스의 시작

지금까지 Playwright를 활용하여 E2E 테스트 환경을 구축하고 웹 자동화를 실현하는 방법에 대해 자세히 살펴보았습니다. 환경 설정부터 실제 테스트 코드 작성, 그리고 효율적인 워크플로우 관리와 CI/CD 연동까지, Playwright가 제공하는 강력한 기능들을 통해 웹 애플리케이션의 품질과 안정성을 어떻게 향상시킬 수 있는지를 알아보았습니다.

E2E 테스트는 개발 초기에는 다소 번거롭게 느껴질 수 있지만, 장기적으로는 버그 발견율을 낮추고, 개발 생산성을 높이며, 궁극적으로 사용자에게 더 나은 경험을 제공하는 데 결정적인 역할을 합니다. Playwright는 이러한 목표를 달성하기 위한 가장 효율적이고 강력한 도구 중 하나입니다.

이 가이드가 여러분의 웹 개발 여정에 큰 도움이 되기를 바랍니다. Playwright를 통해 여러분의 웹 서비스가 더욱 견고하고 신뢰할 수 있게 되기를 기대합니다. 혹시 Playwright를 사용하면서 겪었던 특별한 경험이나, 더 효율적인 팁이 있다면 댓글로 공유해 주세요! 함께 성장하는 개발 커뮤니티를 만들어가요.

📌 함께 읽으면 좋은 글

  • [생산성 자동화] Makefiles 활용 개발 프로젝트 자동화: 빌드, 테스트, 배포 효율 극대화 전략
  • [보안] OAuth 2.0과 OpenID Connect: 안전한 사용자 인증 및 인가 시스템 구축 실전 가이드
  • [개발 도구] VS Code 필수 확장 프로그램: 개발 생산성을 극대화하는 실용 가이드

이 글이 도움이 되셨다면 공감(♥)댓글로 응원해 주세요!
궁금한 점이나 다루었으면 하는 주제가 있다면 댓글로 남겨주세요.