1. 강의 목표: 왜 2026년에도 Playwright인가?
2026년 현재, 웹 기술은 더욱 복잡해졌습니다. 대부분의 기업용 대시보드와 커머스 사이트는 React, Vue, Next.js와 같은 프레임워크를 기반으로 실시간 데이터 바인딩을 수행합니다. 과거의 BeautifulSoup이나 단순한 Selenium만으로는 자바스크립트가 실행된 후의 데이터를 가져오는 데 한계가 있습니다. 본 강의에서는 마이크로소프트에서 개발한 강력한 브라우저 자동화 라이브러리인 Playwright와 Python을 결합하여, 속도와 안정성을 모두 잡은 동적 웹페이지 크롤링 기술을 습득합니다. 비동기 처리(Asyncio)를 통해 수백 개의 페이지를 단 몇 초 만에 처리하는 실무 최적화 기법을 배우게 될 것입니다.
2. 사전 준비 사항
실습을 시작하기 전에 아래 환경이 구축되어 있어야 합니다. 2026년 표준 환경에 맞춰 설정되었습니다.
- 운영체제(OS): Windows 11 이상, macOS Sequoia 이상, 또는 Ubuntu 24.04 LTS
- 편집기: VS Code (Visual Studio Code) 최신 버전 추천
- 파이썬 버전: Python 3.14 이상 (최신 비동기 문법 최적화 활용)
- 필수 라이브러리 설치: 터미널(CMD/Terminal)에서 아래 명령어를 실행하세요.
# 라이브러리 설치
pip install playwright
# 브라우저 바이너리 설치 (Chromium, Firefox, WebKit)
playwright install
3. 단계별 실습 과정
단계 1: 프로젝트 초기화 및 기본 구조 설계
Playwright는 동기(Sync)와 비동기(Async) 방식을 모두 지원하지만, 실무에서는 대량의 데이터를 빠르게 처리하기 위해 비동기 방식을 주로 사용합니다. 먼저 main.py 파일을 생성하고 기본 골격을 작성합니다.
import asyncio
from playwright.async_api import async_playwright
async def run():
async with async_playwright() as p:
# 브라우저 실행 (headless=False로 설정하면 작동 과정을 눈으로 볼 수 있음)
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
# 대상 URL 접속
await page.goto('https://example.com/dynamic-data')
print("페이지 접속 완료")
await browser.close()
if __name__ == "__main__":
asyncio.run(run())
단계 2: 동적 요소 대기 및 데이터 추출
동적 웹페이지의 가장 큰 특징은 페이지 로드 후 자바스크립트가 데이터를 불러온다는 점입니다. 이를 위해 특정 요소가 나타날 때까지 기다리는 wait_for_selector 기능이 필수적입니다.
async def extract_data(page):
# 특정 데이터 리스트가 로드될 때까지 최대 10초 대기
selector = '.product-list-item'
await page.wait_for_selector(selector, timeout=10000)
# 모든 아이템 요소 가져오기
items = await page.query_selector_all(selector)
results = []
for item in items:
# 제목과 가격 추출
title_el = await item.query_selector('.title')
price_el = await item.query_selector('.price')
title = await title_el.inner_text() if title_el else "N/A"
price = await price_el.inner_text() if price_el else "0"
results.append({"title": title, "price": price})
return results
단계 3: 무한 스크롤 처리 및 네트워크 가로채기
많은 현대적 웹사이트는 스크롤을 내릴 때마다 데이터를 추가로 불러옵니다. Playwright의 mouse.wheel 기능을 사용하여 이를 자동화할 수 있습니다. 또한, API 응답을 직접 가로채어(Intercept) 파싱 속도를 극대화하는 기법도 포함합니다.
async def scroll_to_bottom(page):
# 화면 끝까지 스크롤 반복
prev_height = 0
while True:
await page.mouse.wheel(0, 1000)
await page.wait_for_timeout(1000) # 로딩 대기
curr_height = await page.evaluate("document.body.scrollHeight")
if curr_height == prev_height:
break
prev_height = curr_height
print("스크롤 완료")
단계 4: 안티 크롤링 우회 및 컨텍스트 관리
2026년의 웹사이트들은 더욱 강력한 봇 탐지 시스템을 갖추고 있습니다. User-Agent 설정과 Viewport 조정을 통해 일반 사용자로 위장하는 과정이 필요합니다.
async def secure_run():
async with async_playwright() as p:
# 브라우저 컨텍스트 설정 (모바일 기기 환경 모방 가능)
browser = await p.chromium.launch(headless=True)
context = await browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
viewport={'width': 1920, 'height': 1080}
)
page = await context.new_page()
# 실제 작업 수행...
await page.goto('https://target-site.com')
# ... 생략 ...
await browser.close()
4. 결과 확인 및 데이터 저장
추출된 데이터를 CSV 또는 JSON 파일로 저장하여 실무에서 즉시 활용 가능한 결과물을 만듭니다. Python의 내장 json 모듈이나 pandas 라이브러리를 활용하면 효율적입니다.
import json
def save_results(data):
with open('output_2026.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
print(f"총 {len(data)}건의 데이터 저장 완료.")
# 전체 프로세스 실행 예시
# data = await extract_data(page)
# save_results(data)
5. 실무 핵심 요약
본 강의를 통해 여러분은 다음과 같은 핵심 역량을 확보했습니다.
- 비동기 처리:
asyncio를 활용한 고성능 크롤링 구조 설계 - 동적 제어: 자바스크립트 렌더링 완료 시점을 정확히 포착하는 대기 전략
- 유연성: Chromium뿐만 아니라 Firefox, WebKit 등 다양한 브라우저 엔진 대응
- 안정성: 브라우저 컨텍스트 격리를 통한 세션 및 쿠키 관리
이제 여러분은 2026년의 복잡한 웹 환경에서도 막힘없이 데이터를 수집할 수 있는 실무 기술을 갖추게 되었습니다. 위 코드를 기반으로 대상 사이트의 구조에 맞춰 셀렉터를 수정하며 실습을 반복해 보시기 바랍니다.