오늘날 FE 서비스는 단순히 UI 렌더링을 넘어, 인증/권한 처리, API통신, 상태 관리, 라우팅 등의 다양한 책임을 지니게 되었다.
따라서 단위/통합 테스트만으로는 서비스가 완벽하다고 하기 어렵게 되었고, 사용자 관점에서 실제 브라우저를 통해 전체 흐름을 검증하는 E2E 테스트가 필요하게 됨
Playwright는 이러한 테스트 프레임워크의 표준을 제공하고 있다. 기존 시장을 점유하던 Cypress에 비해 압도적인 테스트 속도를 제공하며, 크로스 브라우징, auto-waiting 기능을 제공하고 있다.
Playwright를 이해하기 위해서는 단순한 API 사용법보다 어떤 개념을 전제로 설계되었는지 이해하는것이 중요하다.
Playwright는 브라우저를 세가지 계층구조로 나누어 BrowserContext는 독립된 실행 환경을 의미하며, 각 Context는 완전히 분리된 상태(쿠키, localStorage, 캐시 공유X)를 가진다.
기존에 로그인 상태, 쿠키가 공유되는 문제를 BrowserContext를 통해 없애고, 테스트간 상태가 섞이는 문제를 차단하도록 되어있다.
그리하여 테스트간 의존성이 없고, 병렬 실행이 가능하며, flaky(불안정한) 테스트 발생 가능성을 줄였다.

Playwright는 단순히 querySelector기반 접근이 아닌 Locator 객체를 중심으로 테스트를 작성하며, Locator는 DOM 요소를 즉시 찾지 않고, 동작이 실행되는 시점에 요소를 평가한다.
Locator를 통해 수행되는 대부분의 동작은 "요소가 나타날 때까지, 클릭 가능해질 때까지, 네트워크 요청이 안정될 때까지"인데,
Auto-waiting 기능이 있기 때문에 개발자가 직접 wait, sleep 구문을 넣지 않아도 적절한 테스트 시점을 판단한다.
기존 테스트 프레임워크는 "렌더링 타이밍 차이, 네트워크 지연, 비동기 상태 변경" 등이 flaky 테스트의 주 원인이었는데, Playwright는 Locator와 Auto-waiting으로 이를 안정화 시켰다.
E2E 테스트에 최적화된 자체 Test Runner를 제공한다. 아래와 같은 구조를 통해 BrowserContext 기반 구조와 결합하여 테스트 독립성을 유지, 코드 중복을 줄일 수 있다.
또한 Playwright는 테스트 병렬 수행을 Default로 가져가기에 테스트 실행을 크게 단축시킬 수 있다.
Playwright는 대부분의 설정을 playwright.config.ts 파일 하나로 관리하도록 설계가 되어있어서, "테스트 디렉토리, 타임아웃, 브라우저 종류, 리포터, 병렬 실행 옵션" 등의 환경별 성정 관리가 용이하다.
옵션 예시는 아래와 같다.
Playwright는 이렇게 단순히 브라우저를 조작한다는 개념보다는
Playwright는 다음과 같은 테스트 운영과 디버깅을 고려한 기능을 제공한다
Chromium, Firefox, Webkit 세가지 브라우저 엔진을 공식 지원하며 하나의 테스트 코드와 하나의 API로 실행할 수 있다는 장점을 가지고 있다.
보통 모든 테스트를 모든 브라우저에서 돌리는것은 실무에서 비용이 크게 발생하기 때문에, 핵심 사용자의 시나리오만 멀티 브라우저로 수행하고 그 외 나머지 테스트는 Chromium 위주로 실행한다고 한다.
CI 환경에서는 브라우저 별 프로젝트를 병렬 실행.
테스트를 아래 두가지 방식으로 실행이 가능하다.
실패 분석을 위한 도구를 제공한다.
Trace를 통해 테스트 실행 전체를 기록한 타임라인 데이터를 저장하고 불러올 수 있다.(config에 trace: 'on' 사용 시 zip파일로 자동 저장, show-trace로 불러오기 가능)
Trace Viewer(--ui)를 통해 어느 시점에 화면의 상태와 실패 지점을 시간순으로 확인할 수 있다. (DOM 스냅샷, 네트워크 요청, 콘솔 로그, 스크린샷, 영상 등..)
Playwright는 실제 API 호출과 API mocking 두가지를 테스트 상황에 맞게 혼합하여 사용할 수 있다.
실제 API 호출 - 로그인/인증 토큰 발급/핵심 사용자의 Flow 시작 지점 (실제 서비스와 동일한 흐름을 보장해야 함)
Mock 처리 - 목록 조회 API, 외부 API, 부수 데이터 (테스트 안정성, 속도 확보)
E2E테스트는 "동작하는 코드"보다 "계속 유지할 수 있는 코드"를 만드는것이 중요하다고 하며, 그러기 위해서는 테스트를 작성하기 위해 아래와 같이 몇가지 흐름을 준수해주는것이 좋을것으로 보인다.
흐름은 위와같이 가져가고 실무에 적용할 때에는 테스트를 많이 만드는것보다 무엇을 테스트하며 CI에서 어떻게 운영할지가 중요하다!
아래와 같이 실제 브라우저 상 화면 전환, 사용자 행동이 일어나는 구간에서 주로 사용한다
E2E 테스트에서 버튼 하나, 조건 분기 하나까지 검증하는 용도로 쓰면 테스트 유지 비용이 급격하게 증가한다.
따라서 실제로 테스트가 깨지면 사용자가 불편해하는 범위까지를 테스트의 적용 기준으로 보는것이 좋다.
Playwright는 CI환경에서 실행되는것을 전제로 설계되었기에 CI 파이프라인에 비교적 쉽게 통합할 수 있다. (브라우저 설치 자동화, headless실행 기본값, 실패 로그/trace/스크린샷/비디오 자동 생성을 제공)
또한 병렬실행을 사용할 수 있기에 테스트 수가 늘어도 전체 실행 시간을 통제하는것이 가능하다.
일반 적인 테스트 흐름은 "코드 체크아웃 → 의존성 설치 → playwright 실행 → 실패 시 결과물 업로드"이다.
테스트를 작성할 때에는 playwright에서 제공하는 codegen 기능을 사용하면 복잡한 폼 입력 과정을 일일이 타이핑할 필요 없이, 브라우저에서 실제 서비스를 이용하듯 클릭하고 입력하며 코드가 실시간으로 완성된다.
그리고 id나 class처럼 깨지기 쉬운 선택자 대신 getByRole, locator등 사용자 중심의 로케이터를 우선적으로 찾아준다. 또한 사용자 행위 뿐만아니라 "assert visibility / text / value / snapshot"으로 검증에 대한 작성도 가능하다.
이렇게 로컬환경에서 브라우저를 띄운 후 codegen을 통해 테스트 코드 작성에 익숙해지도록 도움을 주며, 나아가 테스트의 일관성과 개발 속도를 향상시킬 수 있다.(pnpm exec playwright codegen http://localhost:3001/)
코드와 구조를 간략하게 정리하면 아래와 같이 표시할 수 있다.
BrowserContext로 독립성이 보장되는 시점은 test.describe와 test.beforeEach()로 공통 로직을 사용한 뒤의 test() 부터 각각 의 BrowserContext를 생성하여 테스트의 독립성을 보장한다.
독립성 보장으로는 "쿠키/로컬, 세션 스토리지/캐시/권한" 등이 있다.
테스트 구조 예시
tests/
└── login.spec.ts # 로그인 E2E 테스트 파일
│
├── test.describe('로그인 E2E 테스트') # 관련 테스트 그룹화
│ │
│ ├── test.beforeEach() # Hook: 매 테스트 전 공통 로직
│ │ └── page.goto('/login') # 로그인 페이지 이동
│ │
│ ├── test('로그인 페이지 렌더링') # 개별 테스트 케이스
│ │ └── expect().toBeVisible() # 검증: 요소 표시 확인
│ │
│ ├── test('유효한 자격증명 로그인 성공')
│ │ └── expect(page).toHaveURL() # 검증: URL 리다이렉트 확인
│ │
│ ├── test('빈 폼 제출 시 오류 표시')
│ │ └── expect().toHaveCount(3) # 검증: 에러 메시지 개수
│ │
│ ├── test('필수 필드 누락 시 오류')
│ ├── test('잘못된 자격증명 로그인 실패')
│ ├── test('로그인 중 버튼 비활성화')
│ ├── test('인증 필요 페이지 접근')
│ └── test('Enter 키 폼 제출')
│
└── test.describe('인증 상태 유지') # 별도 테스트 그룹
└── test('새로고침 시 인증 유지')
테스트 수행 예시(Headed)
pnpm exec playwright test
pnpm exec playwright show-report

Jenkins + webhook을 통한 테스트 방법은 아래와 같다.
pipeline {
agent {
docker {
image 'mcr.microsoft.com/playwright:v1.49.0-noble'
args '-u root' // 권한 문제 방지
} ...
}
}
// 위와 같이 작성하면 아무 설정 없는 노드 (Mater 또는 기본 Agent가 응답, 기본노드에 Docker가 설치되어있지 않다면 빌드는 즉시 Error 발생)

Bitbucket 설정(언제 신호를 보낼지 설정)
Code Push시 실행으로 설정
Bitbucket 코드 푸시 → Webhook 발생 → Jenkins가 가용한 서버(Master 등) 선택 → Playwright 도커 기동 → 테스트 후 종료