반복되는 회귀 테스트에 지치셨다면 Playwright가 답이 될 수 있습니다.
설치부터 로그인 자동화, pytest 리포트 생성까지 직접 따라할 수 있게 정리했습니다.
매번 같은 화면을 클릭하고 있다면, 이미 자동화가 필요한 시점입니다
QA 업무를 하다 보면 새로운 기능을 테스트하는 시간보다, 이미 확인했던 기능을 "혹시 망가지지 않았는지" 다시 확인하는 회귀 테스트에 더 많은 시간을 쓰게 되는 경우가 많습니다.
로그인, 장바구니, 결제처럼 매 배포마다 반복적으로 클릭해야 하는 시나리오가 있다면, 그 영역은 자동화로 넘기는 게 합리적입니다.
다만 자동화라는 단어가 부담스럽게 느껴지는 이유는, 보통 "프로그래밍을 잘해야 한다"는 인식 때문입니다.
하지만 Playwright는 시작 단계에서는 복잡한 프로그래밍 지식보다 "브라우저에서 무엇을 클릭하고, 무엇을 입력하는지"를 코드로 옮기는 작업에 더 가깝습니다.
여기서는 Python과 Playwright를 활용해 실제 로그인 자동화까지 직접 따라가 보겠습니다.
자동화를 시작하기 전에, Manual 테스트와 무엇이 다른지 먼저 정리합니다
자동화를 도입할 때 가장 먼저 부딫히는 질문은 "이걸 자동화할 가치가 있는가"입니다.
모든 테스트를 자동화하는 것이 목표가 아니라, 반복 빈도가 높고 절차가 안정적인 시나리오부터 자동화 대상으로 선정하는 것이 일반적인 접근입니다.
Playwright가 다른 도구들과 비교해 자주 언급되는 특징은 몇 가지가 있습니다.
먼저 Auto-Wait 기능은 요소가 화면에 나타나고 클릭 가능한 상태가 될 때까지 자동으로 대기해주기 때문에, 기존에 자동화 도구를 다뤄본 분들이라면 익숙한 "타이밍 이슈로 인한 테스트 실패"를 상당 부분 줄여줍니다.
또한 Chromium, Firefox, WebKit 등 여러 브라우저를 동일한 코드로 테스트할 수 있는 Multi-Browser 지원, 그리고 브라우저에서의 동작을 그대로 코드로 변환해주는 Codegen 기능도 입문자에게는 큰 진입장벽을 낮춰주는 요소입니다.
추가로 Selenium에서 Playwright로 무게중심이 옮겨가는 이유와 각각의 장단점을 정리하면 다음과 같습니다.
Playwright가 부상한 핵심 이유
1. Auto-Wait (자동 대기)
Selenium은 요소가 화면에 나타났는지, 클릭 가능한 상태인지를 개발자가 직접 WebDriverWait, expected_conditions 등으로 명시적으로 기다려줘야 합니다.
이걸 생략하면 ElementNotInteractableException 같은 에러가 빈번하게 발생하고, 이로 인한 "Flaky Test"(가끔 실패하는 테스트)가 자동화의 가장 큰 골칫거리였습니다.
Playwright는 클릭이나 입력 같은 액션을 수행하기 전, 해당 요소가 화면에 보이고 활성화되어 있으며 안정된(움직이지 않는) 상태인지를 자동으로 기다려줍니다.
이 한 가지 차이만으로도 테스트 코드의 안정성과 가독성이 크게 달라집니다.
2. 설치와 환경 구성의 간편함
Selenium은 브라우저 버전에 맞는 드라이버(ChromeDriver, GeckoDriver 등)를 별도로 다운로드하고 PATH에 등록해야 했습니다.
브라우저가 업데이트되면 드라이버 버전 불일치로 테스트가 깨지는 경우가 흔했습니다.
Playwright는 playwright install 한 줄로 Chromium, Firefox, WebKit 실행 파일을 자체적으로 관리하기 때문에, 드라이버 버전 문제에서 거의 자유롭습니다.
3. Codegen, Trace Viewer 같은 개발 경험(DX)
Playwright는 브라우저 동작을 코드로 자동 생성해주는 Codegen, 테스트 실행 과정을 타임라인과 스크린샷으로 재생해주는 Trace Viewer, 실패 시점의 스크린샷/비디오를 자동 저장하는 기능을 기본으로 제공합니다.
Selenium은 이런 기능들을 직접 구축하거나 별도 라이브러리(Allure 등)를 조합해야 합니다.
4. 네트워크 제어와 멀티 탭/iframe 처리
Playwright는 API 요청을 가로채거나(intercept), 응답을 mocking하는 기능이 내장되어 있어 "특정 API가 실패했을 때 화면이 어떻게 동작하는가" 같은 테스트가 비교적 쉽습니다.
또한 여러 탭이나 iframe을 다루는 Context/Frame 개념이 Selenium보다 직관적입니다.
5. 비동기/병렬 처리
Playwright는 처음부터 비동기(async) 구조를 염두에 두고 설계되어, 여러 브라우저 컨텍스트를 병렬로 띄워 테스트 시간을 줄이는 작업이 비교적 자연스럽습니다.
| 비교 항목 | Selenium | Playwright |
| 설치/환경 구성 | 드라이버 별도 관리 필요, 초기 세팅·유지보수 부담 큼 | 자체 브라우저 바이너리 관리로 세팅 단순 |
| 대기 처리 | 명시적 대기(Explicit Wait) 직접 작성 필요 | Auto-Wait 기본 동작, 관련 코드 감소 |
| 브라우저 지원 | 크롬·엣지·사파리 등 실제 브라우저 폭넓게 지원 | Chromium·Firefox·WebKit 엔진 기반 (대부분의 웹 테스트에 충분) |
| 생태계/자료 | 오래된 만큼 자료·연동 사례 풍부, 거의 모든 언어 지원(Java/C#/Python/Ruby 등) | 자료量은 적지만 빠르게 증가, 공식 문서 품질 우수 |
| 디버깅 | 별도 로깅/리포팅 도구 조합 필요 | Trace Viewer로 실행 전체 시각적 재생, 분석 시간 단축 |
| 성능 | 상대적으로 느림 | WebSocket 기반 CDP 통신으로 일반적으로 더 빠름 |
설치 및 환경 구성 측면에서는 Selenium은 드라이버를 별도로 관리해야 해서 초기 세팅과 유지보수에 손이 더 가는 반면, Playwright는 자체 브라우저 바이너리를 관리해 세팅이 단순합니다.
대기 처리 측면에서는 Selenium이 명시적 대기를 직접 코드로 작성해야 하는 반면, Playwright는 Auto-Wait가 기본 동작이라 관련 코드가 줄어듭니다.
브라우저 지원 측면에서는 Selenium이 실제 브라우저(크롬, 엣지, 사파리 포함 거의 모든 브라우저)를 폭넓게 지원하는 반면, Playwright는 Chromium, Firefox, WebKit 엔진 기반으로 지원하며 실제 사파리/엣지 브랜드 자체보다는 엔진 단위 지원이라는 차이가 있습니다.
다만 대부분의 웹 테스트 목적으로는 Playwright의 지원 범위로 충분합니다.
생태계와 자료 측면에서는 Selenium이 훨씬 오래된 만큼 커뮤니티 자료, 기존 프레임워크와의 연동 사례, 레거시 프로젝트와의 호환성에서 강점이 있습니다.
Java, C#, Python, Ruby 등 거의 모든 언어를 지원하는 점도 Selenium의 장점입니다.
Playwright는 비교적 최근 도구라 자료의 절대량은 적지만, 빠르게 늘어나고 있고 공식 문서의 품질이 좋은 편입니다.
디버깅 측면에서는 Selenium이 실패 원인을 추적하기 위해 별도 로깅/리포팅 도구를 조합해야 하는 반면, Playwright는 Trace Viewer 하나로 실행 전체를 시각적으로 재생해볼 수 있어 결함 분석 시간이 단축됩니다.
성능 측면에서는 Playwright가 브라우저와 더 낮은 레벨에서 통신하는 구조(WebSocket 기반 CDP 등)를 사용해, 일반적으로 Selenium보다 실행 속도가 빠르다는 평가가 많습니다.
언제 Selenium을 선택하는 게 합리적인가
기존에 Selenium 기반으로 구축된 대규모 테스트 자산이 이미 있고, 이를 전부 마이그레이션하는 비용이 더 크다면 Selenium을 유지하는 것이 합리적입니다.
또한 실제 사파리 브라우저나 특정 레거시 브라우저(IE 등)에서의 동작을 반드시 검증해야 하는 환경이라면 Selenium(WebDriver 표준 기반)이 더 적합할 수 있습니다.
조직 내에 Java나 C# 기반 Selenium 숙련자가 많은 경우도 고려 대상입니다.
언제 Playwright가 더 적합한가
새로 자동화를 시작하는 경우, 특히 QA 인력이 자동화에 익숙하지 않아 "Flaky Test"로 인한 신뢰도 저하를 최소화하고 싶은 경우에는 Playwright가 학습 곡선과 유지보수 비용 면에서 유리합니다.
API mocking, 네트워크 검증을 함께 활용하고 싶은 경우, 또는 결함 발생 시 Trace Viewer로 빠르게 원인을 파악하고 싶은 경우에도 Playwright가 더 적합합니다.
요약하면, Selenium은 "범용성과 생태계"에서 강점이 있고, Playwright는 "안정성, 개발 경험, 디버깅 효율"에서 강점이 있어 최근 신규 프로젝트에서 선호도가 높아지는 추세입니다.
설치 환경 준비하기
실습을 따라가기 위해서는 먼저 컴퓨터에 Python이 설치되어 있어야 합니다.
Python 공식 홈페이지에서 설치 파일을 받아 설치한 뒤, 터미널(또는 명령 프롬프트)에서 아래 명령어로 Playwright를 설치합니다.
pip install pytest-playwright
playwright install
두 번째 명령어인 playwright install은 Chromium, Firefox, WebKit 같은 실제 브라우저 실행 파일을 다운로드하는 과정입니다.
이 과정이 끝나면 별도의 브라우저 설치 없이도 Playwright가 자체적으로 브라우저를 실행할 수 있는 상태가 됩니다.
# mac
최신 macOS Python 환경 보호 정책 때문에 에러가 발생합니다. 가상환경(venv)을 만들어서 그 안에 설치하는 방법을 추천합니다.
cd ~
python3 -m venv playwright-env
source playwright-env/bin/activate
pip install pytest-playwright
playwright install
순서대로 설명하면, 첫 번째 줄은 홈 디렉토리로 이동, 두 번째 줄은 playwright-env라는 이름의 가상환경을 생성, 세 번째 줄은 그 가상환경을 활성화하는 명령입니다.
활성화되면 터미널 프롬프트 앞에 (playwright-env)가 표시됩니다.

이 상태에서 pip install을 실행하면 시스템 환경을 건드리지 않고 이 가상환경 안에만 패키지가 설치됩니다.
이후 작업할 때마다
터미널을 새로 열면 가상환경이 비활성화된 상태이므로, 작업 전에 다시 활성화해야 합니다.
cd ~
source playwright-env/bin/activate
활성화된 상태에서 python3 test_login.py 같은 명령을 실행하면 됩니다.
참고: 빠르게 끝내고 싶다면
가상환경 없이 그냥 진행하고 싶다면 아래처럼 --break-system-packages를 붙여도 됩니다. 다만 시스템 Python 환경에 영향을 줄 수 있어, 학습/실습용이라면 위 venv 방식을 권장합니다.
pip3 install pytest-playwright --break-system-packages
playwright install
빠져나오고 싶다면 deactivate 명령어
deactivate
첫 번째 코드, 로그인 화면을 자동으로 열고 입력해보기
실습용 사이트로는 자동화 학습 목적으로 만들어진 saucedemo.com을 활용하겠습니다. 이 사이트는 로그인 화면과 장바구니 기능을 갖추고 있어, 자동화 입문 실습에 자주 쓰입니다.
먼저 test_login.py라는 파일을 만들고 아래와 같이 작성합니다.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
page.goto("https://www.saucedemo.com")
page.fill("#user-name", "standard_user")
page.fill("#password", "secret_sauce")
page.click("#login-button")
page.screenshot(path="login_result.png")
browser.close()
이 코드는 차례대로 보면 어렵지 않습니다.
page.goto는 브라우저에서 해당 주소로 이동하는 동작, page.fill은 입력창에 값을 채워 넣는 동작, page.click은 버튼을 클릭하는 동작입니다.
마지막으로 page.screenshot은 현재 화면을 캡처해서 파일로 저장합니다.
터미널에서 다음 명령어로 실행합니다.
python test_login.py
headless=False로 설정해두었기 때문에, 실제로 크롬 브라우저 창이 열리면서 아이디와 비밀번호가 자동으로 입력되고 로그인 버튼이 클릭되는 과정을 눈으로 확인할 수 있습니다.
로그인 다음 단계, 장바구니에 상품 담기까지 이어가기
로그인까지 성공했다면, 이어서 상품을 장바구니에 담는 동작까지 자동화 코드에 추가해볼 수 있습니다.
saucedemo.com의 상품 목록 화면에서는 각 상품마다 "Add to cart" 버튼이 있는데, 이 버튼의 위치를 식별하는 방법으로 Playwright는 여러 가지 Locator 전략을 제공합니다.
page.click("text=Add to cart")
page.screenshot(path="cart_result.png")
위 코드에서 text=Add to cart는 화면에 보이는 텍스트를 기준으로 요소를 찾는 방식입니다.
직관적이라는 장점이 있지만, 같은 텍스트를 가진 요소가 여러 개 있을 경우에는 더 정밀한 식별 방법이 필요해집니다.
이때 활용하는 것이 XPath입니다.

XPath, 반복되는 HTML 구조에서 원하는 요소만 골라내는 방법
상품 목록처럼 동일한 구조가 여러 번 반복되는 화면에서는, 단순히 텍스트나 ID만으로 요소를 특정하기 어려운 경우가 생깁니다.
이럴 때 XPath를 활용하면 HTML 구조상의 위치를 기준으로 요소를 정확하게 짚어낼 수 있습니다.
예를 들어 첫 번째 상품의 "Add to cart" 버튼만 클릭하고 싶다면, 개발자 도구의 Elements 탭에서 해당 버튼을 검사한 뒤, 우클릭으로 "Copy → Copy XPath"를 선택하면 해당 요소의 경로를 그대로 복사할 수 있습니다.
복사한 XPath는 아래와 같은 형태로 코드에 적용할 수 있습니다.
page.click("xpath=//div[@class='inventory_item'][1]//button")
처음에는 XPath 문법이 복잡하게 느껴질 수 있지만, 핵심은 "이 요소가 어떤 부모 요소 안에, 몇 번째 자식으로 위치해 있는지"를 경로로 표현한다는 점입니다.
반복되는 카드형 UI에서 특정 위치의 요소만 골라낼 때 특히 유용합니다.
단순 스크립트를 pytest 구조로 바꾸면 생기는 변화
지금까지 작성한 코드는 위에서부터 아래로 한 번 실행되고 끝나는 스크립트 형태입니다.
하지만 실제 테스트 업무에서는 "이 테스트가 성공했는지 실패했는지"를 명확히 판정하고, 결과를 리포트 형태로 남기는 과정이 필요합니다. 이때 활용하는 것이 pytest입니다.
먼저 아래와 같이 test_login.py를 pytest 구조로 바꿔봅니다.
import pytest
from playwright.sync_api import sync_playwright
def test_login_success():
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://www.saucedemo.com")
page.fill("#user-name", "standard_user")
page.fill("#password", "secret_sauce")
page.click("#login-button")
assert page.url == "https://www.saucedemo.com/inventory.html"
browser.close()
def test_login_failure():
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://www.saucedemo.com")
page.fill("#user-name", "standard_user")
page.fill("#password", "wrong_password")
page.click("#login-button")
error_message = page.text_content(".error-message-container")
assert "Epic sadface" in error_message
browser.close()
여기서 핵심은 assert 문입니다.
첫 번째 테스트인 test_login_success는 로그인 성공 후 페이지 주소가 상품 목록 화면(inventory.html)으로 바뀌었는지를 확인합니다.
두 번째 테스트인 test_login_failure는 일부러 잘못된 비밀번호를 입력한 뒤, 에러 메시지가 정상적으로 표시되는지를 확인합니다.
이렇게 작성하면 사람이 결과를 눈으로 보고 판단하는 대신, 코드가 스스로 "이 조건이 맞으면 PASS, 아니면 FAIL"을 판정해줍니다.
HTML 리포트로 결과를 한눈에 정리하기
pytest로 작성한 테스트는 pytest-html 플러그인을 설치하면 결과를 보기 좋은 HTML 파일로 받아볼 수 있습니다.
pip install pytest-html
pytest --html=report.html
명령어를 실행하면 같은 폴더에 report.html 파일이 생성되고, 이 파일을 브라우저로 열면 어떤 테스트가 통과했고 어떤 테스트가 실패했는지, 각 테스트가 실행되는 데 걸린 시간까지 표 형태로 정리된 화면을 볼 수 있습니다.

Codegen, 코드를 직접 짜기 어렵다면 브라우저 동작을 코드로 받아내는 방법
만약 Locator를 직접 찾고 코드를 작성하는 과정이 아직 부담스럽다면, Playwright의 Codegen 기능을 활용하는 것도 좋은 시작점입니다.
터미널에 아래 명령어를 입력하면 브라우저가 열리면서 동시에 코드 생성 창이 함께 뜹니다.
playwright codegen https://www.saucedemo.com
이 상태에서 브라우저 화면을 직접 클릭하고 입력하면, 그 동작이 실시간으로 Python 코드로 변환되어 옆 창에 기록됩니다.

처음 자동화를 시작할 때는 이렇게 생성된 코드를 기반으로, 필요한 부분만 수정하고 assert 문을 추가해 나가는 방식이 훨씬 접근하기 쉽습니다.
여기까지 왔다면, 다음으로 살펴볼 만한 것들
로그인과 장바구니 자동화, 그리고 pytest를 활용한 결과 판정과 HTML 리포트까지 직접 따라와 봤다면, 이미 회귀 테스트의 핵심 흐름은 한 번 경험한 셈입니다.
다음 단계로는 여러 페이지에서 반복되는 Locator를 클래스로 묶어 관리하는 POM(Page Object Model) 패턴이 있는데, 이는 테스트 코드가 많아질수록 유지보수를 쉽게 만들어주는 구조입니다.
최근에는 LLM과 Playwright를 결합한 자동화 방식도 함께 언급되는데, 이 부분은 다음 글에서 좀 더 자세히 다뤄보겠습니다.
'11. 자료실·기타 > 테스트 관련 강좌' 카테고리의 다른 글
| 코드 한 줄 없이 "장바구니에 담아줘"라고 말하면 끝나는 시대, LLM과 Playwright 결합 자동화 들여다보기 (0) | 2026.06.13 |
|---|---|
| 테스트 케이스만 따라가다 보면 놓치는 결함들, 탐색적 테스트가 필요한 이유 (0) | 2026.06.13 |
| 회원가입 화면 하나만 열어도 보이는 것들, QA가 DevTools(개발자도구)로 증거 기반 리포트를 쓰는 법 (0) | 2026.06.13 |
| 테스트만 하는 QA는 끝났다" 토스증권 채용 공고에서 읽은 AI 시대 품질 엔지니어의 변신 (0) | 2026.05.26 |
| "집에 돌아오기 전에 꺼두는 그것처럼" QA도 이제 자동화로 혼자 일한다 (0) | 2026.05.23 |