
소개
Playwright는 Microsoft에서 개발한 오픈소스 웹 테스트 자동화 도구로, Chromium, Firefox, WebKit 등 주요 브라우저 엔진을 지원하며 신뢰성 높은 엔드투엔드(E2E) 테스트를 제공합니다. Puppeteer의 한계를 보완하며, 크로스 브라우저 지원, 자동 대기, 네트워크 모킹, 스크린샷 및 비디오 캡처 등 강력한 기능을 자랑합니다. Node.js뿐만 아니라 Python, Java, C#도 지원해 다양한 개발 환경에 적합합니다. 빠른 실행 속도와 직관적인 API로 초보자부터 전문가까지 모두에게 매력적인 선택지입니다.
Playwright의 주요 특징
- 크로스 브라우저 지원: Chrome, Firefox, Safari(WebKit)를 단일 API로 테스트 가능.
- 자동 대기: 요소가 로드될 때까지 자동으로 대기해 플레이크 테스트(flaky test) 감소.
- 다양한 언어 지원: JavaScript/TypeScript, Python, Java, C# 지원.
- 강력한 디버깅: 스크린샷, 비디오, 트레이스 뷰어로 문제 원인 파악 용이.
- 네트워크 제어: 요청 가로채기, 모킹, 수정 가능.
- 멀티 탭/프레임/컨텍스트: 복잡한 웹 앱 시나리오 처리 가능.
다른 프레임워크와 비교
| 기능/프레임워크 | Playwright | Puppeteer | Selenium | Cypress |
|---|---|---|---|---|
| 크로스 브라우저 | Chromium, Firefox, WebKit | Chromium만 지원 | 모든 주요 브라우저 | Chromium, Firefox |
| 언어 지원 | JS, Python, Java, C# | JS만 지원 | 다중 언어 | JS/TS만 지원 |
| 자동 대기 | 네이티브 지원 | 제한적 | 수동 설정 필요 | 네이티브 지원 |
| 속도 | 빠름 | 빠름 | 느림 | 빠름 |
| 모바일 에뮬레이션 | 제한적 | 지원) | 지원 | 제한적 |
| 커뮤니티 | 성장 중 | 중간 | 대규모 | 성장 중 |
- Puppeteer: Google이 개발한 도구로 Chromium에 최적화되어 있지만, 다른 브라우저 지원이 없고 Playwright가 이를 보완하며 상위 호환 격.
- Selenium: 오래된 도구로 다양한 브라우저와 언어를 지원하지만, 설정이 복잡하고 플레이크 테스트가 발생하기 쉬움.
- Cypress: 현대적인 UI와 빠른 속도를 제공하나, 크로스 브라우저 지원이 제한적이고 JavaScript 전용.
Playwright 설치 및 기본 예제
설치 (Node.js 기준)
npm init -y
npm install @playwright / test
npx playwright install # 브라우저 설치
예제: Google 검색 테스트 (JavaScript)
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: false }); // 브라우저 실행
const page = await browser.newPage(); // 새 페이지 열기
await page.goto('https://www.google.com'); // Google로 이동
await page.fill('input[name="q"]', 'Playwright'); // 검색어 입력
await page.press('input[name="q"]', 'Enter'); // Enter 키 입력
await page.waitForSelector('h3'); // 결과 로드 대기
const results = await page.$$eval('h3', elements => elements.map(el => el.textContent)); // 결과 텍스트 추출
console.log('검색 결과:', results);
await browser.close(); // 브라우저 닫기
})();
Python 예제: 로그인 테스트
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://example.com/login')
page.fill('input#username', 'testuser')
page.fill('input#password', 'password123')
page.click('button[type="submit"]')
page.wait_for_selector('div.dashboard')
assert 'Welcome' in page.text_content('div.dashboard')
browser.close()
Playwright 활용 팁
- 코드 생성기:
npx playwright codegen으로 인터랙티브하게 테스트 코드 생성. - 트레이스 뷰어:
npx playwright show-trace trace.zip으로 테스트 실패 원인 시각화. - CI/CD 통합: GitHub Actions, Jenkins 등에서 쉽게 실행 가능.
- 병렬 실행:
npx playwright test --workers 4로 테스트 속도 향상.
결론
Playwright는 강력한 기능, 크로스 브라우저 지원, 다양한 언어 호환성으로 현대 웹 테스트의 표준으로 자리 잡았습니다. Puppeteer의 상위 호환으로 시작했지만, 이제는 Selenium이나 Cypress를 대체할 수 있는 강력한 대안입니다. 초보자는 직관적인 API로 빠르게 시작할 수 있고, 전문가는 복잡한 시나리오를 처리할 수 있는 유연성을 누릴 수 있습니다. 웹 테스트 자동화를 고민한다면, Playwright는 반드시 고려해야 할 도구입니다.
이 글이 Playwright의 매력을 전달하는 데 도움이 되길 바랍니다! 추가 요청이 있다면 말씀해주세요.
Playwright로 Python을 활용한 웹 테스트 자동화 예제
Playwright의 Python API는 직관적이고 강력하여 다양한 웹 테스트 시나리오를 쉽게 구현할 수 있습니다. 이전 답변에서 제공한 기본 로그인 테스트 외에, 아래는 Python을 사용한 3가지 다양한 Playwright 예제를 소개합니다. 각 예제는 실용적인 시나리오를 다루며, 스크린샷 저장, 네트워크 요청 모킹, 파일 업로드 등 Playwright의 고급 기능을 활용합니다.
예제 1: 웹 페이지 스크린샷 및 PDF 저장
이 예제는 웹 페이지를 방문해 스크린샷과 PDF를 저장하는 방법을 보여줍니다. 예를 들어, 특정 웹 페이지의 렌더링 상태를 기록하거나 문서화가 필요한 경우 유용합니다.
from playwright.sync_api import sync_playwright
def test_screenshot_and_pdf():
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
# 웹 페이지로 이동
page.goto('https://www.example.com')
# 스크린샷 저장
page.screenshot(path='example_screenshot.png', full_page=True)
# PDF 저장 (Chromium에서만 지원)
page.pdf(path='example_page.pdf', format='A4')
# 페이지 제목 확인
title = page.title()
print(f"페이지 제목: {title}")
browser.close()
if __name__ == "__main__":
test_screenshot_and_pdf()
설명:
page.screenshot: 전체 페이지 스크린샷을 PNG로 저장.page.pdf: 페이지를 PDF로 저장 (Chromium 전용).headless=False로 설정해 브라우저 동작을 시각적으로 확인 가능.
예제 2: 네트워크 요청 모킹
이 예제는 API 요청을 가로채고 모킹하여 테스트 환경을 제어하는 방법을 보여줍니다. 예를 들어, 외부 API 의존성을 제거하고 테스트 데이터를 주입할 때 유용합니다.
from playwright.sync_api import sync_playwright
import json
def test_network_mocking():
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_page()
# 네트워크 요청 가로채기
def handle_route(route, request):
if 'api.example.com/data' in request.url:
# 모킹된 응답
mock_response = {
"id": 1,
"name": "Mocked User",
"email": "mocked@example.com"
}
route.fulfill(
status=200,
content_type='application/json',
body=json.dumps(mock_response)
)
else:
route.continue_()
page.route('**/*', handle_route)
# 테스트 페이지로 이동
page.goto('https://example.com/app')
# API 호출 트리거 (예: 버튼 클릭)
page.click('button#fetch-data')
# 모킹된 데이터가 페이지에 반영되었는지 확인
content = page.text_content('div#user-name')
assert 'Mocked User' in content
print("모킹된 데이터 확인 완료:", content)
browser.close()
if __name__ == "__main__":
test_network_mocking()
설명:
page.route: 특정 URL 패턴의 요청을 가로챔.route.fulfill: 모킹된 JSON 응답을 반환.- 실제 API 호출 없이 테스트 데이터를 주입해 테스트 안정성 향상.
예제 3: 파일 업로드 및 다운로드 테스트
이 예제는 파일 업로드와 다운로드를 테스트하는 방법을 보여줍니다. 예를 들어, 파일 업로드 기능을 테스트하거나 다운로드된 파일의 내용을 확인할 때 유용합니다.
from playwright.sync_api import sync_playwright
import os
def test_file_upload_download():
with sync_playwright() as p:
browser = p.webkit.launch(headless=False) # WebKit으로 테스트
page = browser.new_page()
# 파일 업로드 페이지로 이동
page.goto('https://the-internet.herokuapp.com/upload')
# 파일 업로드
file_path = 'sample.txt' # 테스트용 파일 생성
with open(file_path, 'w') as f:
f.write('Hello, Playwright!')
page.set_input_files('input#file-upload', file_path)
page.click('input[type="submit"]')
# 업로드 성공 확인
success_message = page.text_content('#uploaded-files')
assert 'sample.txt' in success_message
print("파일 업로드 성공:", success_message)
# 다운로드 테스트
page.goto('https://the-internet.herokuapp.com/download')
with page.expect_download() as download_info:
page.click('a[href="download/some-file.txt"]')
download = download_info.value
download_path = 'downloaded_file.txt'
download.save_as(download_path)
# 다운로드된 파일 내용 확인
with open(download_path, 'r') as f:
content = f.read()
print("다운로드된 파일 내용:", content)
browser.close()
os.remove(file_path) # 테스트 파일 정리
os.remove(download_path)
if __name__ == "__main__":
test_file_upload_download()
설명:
page.set_input_files: 파일 업로드를 시뮬레이션.page.expect_download: 다운로드 이벤트를 캡처하고 파일 저장.- 실제 파일 I/O와 함께 테스트하여 현실적인 시나리오 구현.
추가 팁
- 비동기 API: 위 예제는
sync_playwright를 사용했지만, 비동기 작업을 선호한다면async_playwright와async/await를 사용할 수 있습니다. - 테스트 프레임워크 통합:
pytest와pytest-playwright플러그인을 사용해 테스트를 구조화하세요. - 디버깅:
page.pause()로 실행 중지 후 브라우저 상태 확인 가능.
이 예제들은 Playwright의 Python API를 활용한 다양한 시나리오를 다룹니다. 추가로 특정 기능이나 시나리오에 대한 예제가 필요하면 말씀해주세요!
Playwright를 활용한 Python 웹 크롤링 예제
키워드: Playwright, Python, 웹 크롤링, 데이터 추출, 크로스 브라우저, 동적 웹사이트
Playwright는 단순히 테스트 자동화뿐만 아니라 동적 웹사이트 크롤링에도 강력한 도구입니다. JavaScript로 렌더링된 페이지나 복잡한 상호작용이 필요한 사이트에서도 안정적으로 데이터를 추출할 수 있습니다. 아래는 Python과 Playwright를 사용한 웹 크롤링 예제를 추가로 제공하며, 실제 시나리오를 기반으로 다양한 데이터를 수집하는 방법을 보여줍니다.
예제 4: 동적 웹사이트 크롤링 (상품 정보 수집)
이 예제는 전자상거래 사이트(예: 가상의 쇼핑몰)에서 상품 목록을 크롤링하고, 상품 이름, 가격, 리뷰 수를 추출하는 방법을 보여줍니다. 동적 로딩(예: 무한 스크롤)과 페이지 네비게이션을 처리합니다.
from playwright.sync_api import sync_playwright
import json
def crawl_products():
with sync_playwright() as p:
browser = p.chromium.launch(headless=False) # 브라우저 실행 (디버깅 용으로 headless=False)
page = browser.new_page()
# 타겟 웹사이트로 이동 (여기서는 예시로 'the-internet.herokuapp.com' 사용)
page.goto('https://webscraper.io/test-sites/e-commerce/allinone')
# 동적 콘텐츠 로드 대기
page.wait_for_selector('.product-wrapper')
# 상품 데이터 수집
products = []
while True:
# 상품 목록 추출
product_elements = page.query_selector_all('.product-wrapper')
for product in product_elements:
title = product.query_selector('.title').inner_text()
price = product.query_selector('.price').inner_text()
reviews = product.query_selector('.ratings p') # 리뷰 수
review_count = reviews.inner_text() if reviews else '0 reviews'
products.append({
'title': title,
'price': price,
'reviews': review_count
})
# 다음 페이지 버튼 확인
next_button = page.query_selector('a[aria-label="Next"]')
if next_button and 'disabled' not in next_button.get_attribute('class'):
next_button.click()
page.wait_for_timeout(2000) # 페이지 로드 대기
else:
break # 더 이상 페이지가 없으면 종료
# 결과 출력 및 저장
print(f"총 {len(products)}개의 상품 수집 완료")
for product in products:
print(product)
# JSON 파일로 저장
with open('products.json', 'w', encoding='utf-8') as f:
json.dump(products, f, ensure_ascii=False, indent=2)
browser.close()
if __name__ == "__main__":
crawl_products()
설명:
- 동적 콘텐츠 처리:
page.wait_for_selector로 상품 목록이 로드될 때까지 대기. - 데이터 추출: CSS 셀렉터(
query_selector)로 상품 정보(제목, 가격, 리뷰 수)를 추출. - 페이지 네비게이션: 다음 페이지 버튼을 찾아 클릭하며 무한 스크롤 또는 페이지네이션 처리.
- 결과 저장: 수집된 데이터를 JSON 파일로 저장해 후속 분석 가능.
- 사이트 선택: 예제에서는
webscraper.io의 테스트 사이트를 사용했으나, 실제 사이트(예: Amazon, eBay)로 변경하려면 셀렉터와 URL을 조정해야 합니다.
추가 팁
- 헤드리스 모드:
headless=True로 설정해 서버 환경에서 실행 가능. - 에러 처리: 실제 크롤링에서는
try-except를 추가해 네트워크 오류나 셀렉터 누락에 대비하세요. - 속도 최적화:
page.wait_for_timeout대신 특정 요소 로드를 기다리는wait_for_selector를 활용해 효율성을 높이세요. - 법적 주의: 크롤링 시 대상 사이트의 이용 약관(Terms of Service)과 robots.txt를 확인하세요.
실행 전 준비
- Playwright 설치:
pip install playwright playwright install - 테스트 사이트 외의 실제 사이트를 크롤링할 경우, 셀렉터와 페이지 구조를 개발자 도구로 확인하세요.
- 대량 크롤링 시 IP 차단을 피하려면 프록시나 요청 간 딜레이를 추가하세요.
이 예제를 통해 Playwright로 동적 웹사이트 크롤링을 쉽게 시작할 수 있습니다. 추가로 특정 사이트나 데이터(예: 이미지 URL, 상세 페이지 크롤링)를 대상으로 한 예제가 필요하면 말씀해주세요!
'Python을 배워보자' 카테고리의 다른 글
| 박스오피스예매율실시간 크롤링 (0) | 2025.09.23 |
|---|---|
| Playwright를 활용한 네이버 증권 크롤링 예제 (3) | 2025.07.26 |
| 국가별 월별 기온 데이터를 FastAPI로 백엔드 구축 및 Dash로 테이블 출력하기 (3) | 2025.07.24 |
| 영화진흥위원회(KOBIS) 오픈 API를 사용해 일별 박스오피스 데이터를 가져오는 Python 샘플 코드 (4) | 2025.07.22 |
| 파이썬 Trafilatura: 웹 크롤링과 텍스트 추출의 강력한 도구 (0) | 2025.06.22 |