IT/개발

파이썬 Playwright 웹 자동화: 흔한 에러와 디버깅 전략

zzun 2026. 4. 26. 01:30
반응형

파이썬 Playwright 웹 자동화: 흔한 에러와 디버깅 전략

웹 자동화는 비즈니스 프로세스를 효율화하고, 테스트 자동화를 통해 소프트웨어 품질을 높이는 데 필수적인 도구입니다. 특히 파이썬 기반의 Playwright는 크로미움, 파이어폭스, 웹킷 등 다양한 브라우저를 지원하며 강력한 자동화 기능을 제공하여 많은 개발자에게 사랑받고 있습니다. 하지만 강력한 기능만큼이나 개발 과정에서는 다양한 오류와 마주치게 되는데, 이러한 문제들을 효과적으로 해결하는 디버깅 노하우는 생산성을 좌우하는 핵심 역량입니다.

이 포스트에서는 Playwright를 활용한 파이썬 웹 자동화 스크립트 개발 시 흔히 겪는 셀렉터 문제, 인코딩 오류, 객체 참조 및 비동기 동작 관련 문제들을 심도 있게 다루고, 실무에 바로 적용할 수 있는 효율적인 디버깅 전략과 해결 노하우를 공유합니다. 이 글을 통해 여러분의 Playwright 자동화 스크립트가 더욱 견고하고 안정적으로 동작하도록 돕는 인사이트를 얻으시길 바랍니다.

1. 셀렉터 문제: 'Elements Not Found' 해결 전략

웹 자동화 개발 시 가장 빈번하게 발생하는 오류는 단연 'Elements Not Found'입니다. 이는 Playwright가 지정된 셀렉터로 웹 페이지에서 요소를 찾지 못했을 때 발생하며, 주로 다음과 같은 원인이 있습니다.

  • 동적 콘텐츠와 ID: 웹 페이지가 로드될 때마다 ID나 클래스 이름이 변경되는 경우가 많습니다.
  • 잘못된 셀렉터 문법: CSS 또는 XPath 셀렉터가 웹 페이지의 DOM 구조와 일치하지 않을 수 있습니다.
  • 요소 로딩 타이밍 문제: 페이지가 완전히 로드되기 전에 스크립트가 요소를 찾으려고 시도할 수 있습니다.
  • Shadow DOM: 일부 웹 컴포넌트는 Shadow DOM 내부에 존재하여 일반적인 셀렉터로는 접근하기 어렵습니다. (Shadow DOM: 웹 컴포넌트의 내부 DOM 구조를 캡슐화하여 외부 DOM과 격리하는 기술)

해결 노하우:

  • Playwright Inspector 활용: Playwright가 제공하는 Inspector는 시각적으로 셀렉터를 디버깅하는 데 매우 유용합니다. 스크립트 내에서 await page.pause()를 호출하거나, 터미널에서 PWDEBUG=1 python your_script.py 명령어로 실행하면 Playwright Inspector가 실행되어 웹 페이지의 요소를 클릭하고 최적의 셀렉터를 자동으로 추천해 줍니다.
  • 견고한 셀렉터 작성:
    • 의미론적 속성 활용: data-testid와 같이 테스트를 위해 명시적으로 추가된 속성이나, button:has-text('Submit')과 같이 텍스트 내용을 포함하는 셀렉터를 우선적으로 사용합니다. 이는 UI 변경에도 비교적 안정적입니다.
    • 태그와 속성 조합: 'input[name='username']'이나 'a[href*='product']'와 같이 특정 태그와 속성을 조합하여 대상을 명확히 합니다.
    • XPath 사용: 복잡한 부모-자식 관계나 텍스트 내용 기반으로 요소를 찾아야 할 때는 XPath가 유용합니다. 예를 들어, '//div[contains(., '원하는 텍스트')]/button'과 같이 사용합니다.
  • 대기 전략 적용:
    • await page.wait_for_selector(selector, state='visible'): 요소가 DOM에 존재하며 화면에 표시될 때까지 기다립니다. state 옵션으로 'attached' (DOM에만 존재), 'hidden' (DOM에 존재하지만 숨김) 등으로도 대기할 수 있습니다.
    • await expect(locator).to_be_visible(): 테스트 코드에서는 Playwright Test의 expect API를 사용하여 요소가 특정 상태가 될 때까지 기다리고 검증할 수 있습니다.
    • ⚠️ 주의: await page.wait_for_timeout(5000)과 같은 고정 시간 대기는 페이지 로딩 속도에 따라 불안정할 수 있으므로, 꼭 필요한 경우가 아니면 피하는 것이 좋습니다.
  • Shadow DOM 접근: Playwright는 기본적으로 Shadow DOM을 자동으로 횡단합니다. 하지만 특정 요소가 Shadow DOM 내부에 있다면 셀렉터 앞에 'css=selector >> shadow=inner_selector'와 같이 명시적으로 지정하여 더 정확하게 접근할 수 있습니다.

2. 인코딩 및 텍스트 처리 문제

웹 페이지에서 텍스트 데이터를 추출하거나 비교할 때, 인코딩 문제로 인해 텍스트가 깨지거나 예상과 다른 결과가 나올 수 있습니다. 한글 웹 페이지에서 특히 빈번하게 발생하며, 주로 다음과 같은 상황에서 나타납니다.

  • 잘못된 문자 인코딩: 웹 서버가 HTTP 헤더에서 charset=UTF-8이라고 선언했지만, 실제 콘텐츠는 EUC-KR 등으로 인코딩된 경우.
  • 특수 문자 처리: HTML 엔티티( )나 유니코드 특수 문자(줄 바꿈 없는 공백 \xa0, Zero Width Space \u200b 등)가 포함된 경우.
  • 텍스트 비교 오류: 눈에는 같아 보여도 실제로는 다른 공백 문자나 숨겨진 문자로 인해 문자열 비교가 실패하는 경우.

해결 노하우:

  • 명시적 인코딩 지정 및 디코딩: page.content()로 HTML을 가져올 경우, 반환되는 바이트 스트림을 올바른 인코딩으로 디코딩해야 합니다. HTTP 응답 헤더의 Content-Type에서 charset 정보를 확인하고, 만약 정보가 없거나 잘못되었다면 'utf-8', 'euc-kr', 'cp949' 등 일반적인 인코딩을 시도해봅니다. 예를 들어, html_content.decode('utf-8', errors='ignore')와 같이 처리할 수 있습니다.
  • 텍스트 정규화: 추출한 텍스트에서 불필요한 공백이나 특수 문자를 제거하여 일관된 형태로 만듭니다. Python의 str.strip(), str.replace() 메서드를 적극 활용합니다. 예를 들어, text.strip().replace('\xa0', ' ').replace('\u200b', '')는 흔히 문제가 되는 공백 문자를 일반 공백으로 치환하고 양쪽 공백을 제거합니다.
  • 정규 표현식(Regex) 활용: 정확한 문자열 일치 대신 유연한 패턴 매칭이 필요할 때 Python의 re 모듈을 사용합니다. 예를 들어, "총 100건"이라는 텍스트에서 숫자만 추출하거나, 공백의 종류에 상관없이 매칭할 때 유용합니다. re.search(r'총\s*(\d+)건', text)와 같이 사용할 수 있습니다.
  • Playwright의 텍스트 추출 메서드 활용: locator.text_content()locator.inner_text()는 Playwright가 내부적으로 브라우저 렌더링을 기반으로 텍스트를 추출하므로, 많은 인코딩 문제를 자동으로 처리해 줍니다. 하지만 여전히 정규화는 필요할 수 있습니다.

3. 객체 참조 및 비동기 동작 문제

Playwright는 비동기(async/await) 방식으로 동작하며, 이는 파이썬 스크립트 개발 시 객체 참조 오류(NoneType 오류)예상치 못한 동작(race condition)으로 이어질 수 있습니다.

  • await 누락: 비동기 함수 호출 시 await 키워드를 빠뜨리면, 코루틴 객체가 반환될 뿐 실제 작업은 수행되지 않아 이후 작업에서 None 값을 참조하게 됩니다.
  • 오래된 ElementHandle 참조: 페이지 이동(page.goto())이나 DOM 변경 후, 이전에 얻어둔 ElementHandle이 더 이상 유효하지 않을 수 있습니다.
  • ElementHandle vs. Locator 혼동: Playwright에서 권장하는 Locator 대신 저수준 API인 ElementHandle을 사용하여 발생하는 문제입니다. (ElementHandle: 특정 시점의 DOM 요소를 직접 참조, Locator: DOM 요소를 찾기 위한 질의 객체)

해결 노하우:

  • 모든 비동기 호출에 await 사용: Playwright의 모든 비동기 함수(page.goto(), locator.click(), page.wait_for_selector() 등)는 반드시 await 키워드와 함께 호출되어야 합니다. 이를 통해 해당 작업이 완료될 때까지 기다리고, 올바른 반환 값을 받을 수 있습니다.
  • Locator 객체 우선 사용: Playwright는 Locator 객체를 사용하는 것을 강력히 권장합니다. locator = page.locator('button.submit')과 같이 Locator를 생성한 후, await locator.click()과 같이 사용하면, Playwright가 각 액션 수행 전에 자동으로 DOM에서 요소를 다시 찾아주므로, 페이지 변경에 더 견고합니다. ElementHandle은 특별한 경우에만 사용합니다.
  • 컨텍스트 관리자(Context Managers) 활용: 이벤트 대기 시 async with page.expect_event('dialog') as dialog_info:와 같은 컨텍스트 관리자를 사용하면, 이벤트 발생을 확실히 기다리면서 관련 정보를 안전하게 얻을 수 있습니다.
  • 체계적인 로깅: Python의 logging 모듈을 사용하여 스크립트의 각 단계별로 객체의 상태, 함수 호출 결과 등을 기록합니다. 특히 비동기 코드의 흐름을 추적하는 데 큰 도움이 됩니다.

4. 효율적인 디버깅 전략

위에서 언급된 개별 문제 해결 노하우와 함께, 전반적인 디버깅 효율성을 높이는 전략을 소개합니다.

  • 작은 단위로 테스트 및 검증: 복잡한 자동화 스크립트를 한 번에 실행하기보다는, 로그인, 특정 페이지 이동, 데이터 추출 등 각 단계를 작은 함수로 분리하고, 각 함수 실행 후 print() 문이나 로거를 활용하여 중간 결과값을 검증합니다.
  • 스크린샷 및 비디오 레코딩:
    • 오류 발생 시 스크린샷: try-except 블록에서 예외 발생 시 await page.screenshot(path='error.png')를 호출하여 오류 발생 시점의 화면을 캡처합니다. 이는 문제 상황을 파악하는 데 결정적인 단서가 됩니다.
    • 전체 과정 비디오 레코딩: browser = await playwright.chromium.launch() 대신 browser = await playwright.chromium.launch()browser_context = await browser.new_context(record_video_dir='videos/') 옵션을 추가하여 전체 자동화 과정을 비디오로 녹화합니다. 특히 간헐적으로 발생하는 버그(intermittent bugs)를 재현하고 분석하는 데 매우 효과적입니다.
  • Playwright Debugger (PWDEBUG=1)의 적극 활용: 앞서 언급했듯이, PWDEBUG=1 python your_script.py 명령어를 통해 Playwright Inspector를 실행하여 시각적으로 스크립트 실행을 단계별로 제어하고 DOM 탐색, 셀렉터 테스트 등을 수행합니다.
  • Playwright Trace Viewer: browser_context = await browser.new_context(trace='on') 옵션으로 스크립트를 실행하면, Playwright는 모든 브라우저 상호작용, 네트워크 요청, DOM 변경 사항 등을 기록한 추적 파일(.zip)을 생성합니다. 스크립트 실행 후 playwright show-trace trace.zip 명령어로 이 파일을 열면 타임라인 형태로 스크립트의 모든 동작을 상세하게 분석할 수 있어, 문제의 원인을 심층적으로 파악하는 데 매우 강력한 도구입니다.

결론

파이썬 Playwright를 이용한 웹 자동화는 강력하지만, 개발 과정에서 마주치는 다양한 디버깅 과제는 개발자의 인내심을 시험하기도 합니다. 견고한 셀렉터 작성, 인코딩 문제에 대한 이해, 비동기 프로그래밍 패러다임의 숙달, 그리고 Playwright가 제공하는 Inspector, Trace Viewer, 비디오 레코딩과 같은 강력한 디버깅 도구들을 적극적으로 활용하는 것이 중요합니다.

이 글에서 제시된 노하우와 전략들을 여러분의 Playwright 웹 자동화 프로젝트에 적용하여, 더욱 안정적이고 효율적인 스크립트를 개발하고 생산성을 한 단계 더 높이시길 바랍니다. 꾸준한 학습과 실습을 통해 Playwright 마스터가 되십시오!

반응형