Playwright 브라우저 액션이 멈추는 문제 해결하기: CDP 기반의 새로운 evaluate 방식
브라우저 자동화 스크립트를 짜다 보면 가끔 JavaScript 실행이 끝나지 않아 전체 프로세스가 먹통이 되는 경험을 하게 돼요. 특히 Playwright를 쓸 때 page.evaluate 하나가 길어지면, 그 뒤에 오는 클릭이나 타이핑 같은 모든 액션이 줄줄이 대기 상태에 빠지곤 하죠. 탭 하나가 완전히 멈춰버리는 이 상황은 개발자에게 정말 골치 아픈 일이에요.
이런 현상이 발생하는 이유는 Playwright가 페이지당 CDP 커맨드를 순차적으로 처리하기 때문이에요. 앞선 작업이 끝나지 않으면 다음 작업은 시작조차 할 수 없죠. 이 문제를 해결하기 위해 act:evaluate를 Playwright로부터 분리하여 독립적으로 실행하는 리팩토링 계획을 준비했어요.
필요한 것
섹션 제목: “필요한 것”browser.evaluateEnabled설정 활성화- CDP endpoint 접근 권한
빠른 시작
섹션 제목: “빠른 시작”새로운 구조에서는 Playwright의 대기열을 거치지 않고 CDP를 통해 직접 JavaScript를 실행해요. 5분 만에 이해하는 핵심 단계는 다음과 같아요.
- 단일 Budget 관리:
timeoutMs와AbortSignal을 결합한 통합 예산을 사용해요. 모든 작업은 이 시간을 기준으로 움직여요. - 별도의 CDP 세션 연결: Playwright의 큐와 섞이지 않도록 별도의 WebSocket 연결과 CDP 세션을 생성해요.
- Target 연결:
Target.attachToTarget을 사용하여 특정 페이지에 세션을 붙이고Runtime.evaluate를 실행해요. - Element 지정: 요소(Element)를 타겟팅할 때는
backendDOMNodeId를 사용하여 Playwright와 독립적으로 동작하게 만들어요.
구현의 핵심이 되는 createBudget과 데이터 구조는 다음과 같아요.
// 1. 공통 Budget 헬퍼 사용const budget = createBudget({ timeoutMs, signal });
// 2. 확장된 Ref 메타데이터 구조{ role: string; name: string; nth: number; backendDOMNodeId?: number; // CDP 타겟팅을 위한 선택적 ID}문제 해결
섹션 제목: “문제 해결”개발 중에 마주칠 수 있는 문제와 해결 방법이에요.
- Evaluate가 멈춰서 다음 액션이 안 될 때: 새로운 방식에서는 CDP 세션을 직접 끊어버릴 수 있어요. 타임아웃이나 중단(Abort)이 발생하면
Runtime.terminateExecution을 호출하고 소켓을 닫아버려요. 덕분에 다음 클릭이나 타이핑 액션이 방해받지 않아요. - CDP 매핑에 실패할 때: 만약
backendDOMNodeId를 찾지 못하더라도 걱정하지 마세요. 이 경우에는 안전하게 기존의 Playwright 경로로 돌아가서(Fallback) 작업을 수행해요. - 프레임이나 셀렉터 스냅샷 문제: AX tree를 가져올 때 매핑이 모호하다면 ID를 정의하지 않은 상태로 둡니다. 이는 시스템을 멈추게 하지 않고 안전한 대안을 찾도록 설계되었어요.
- 실행 종료 후 부작용:
terminateExecution은 페이지 내 JavaScript 실행을 강제로 종료하므로 약간의 부작용이 있을 수 있어요. 하지만 이는 탭이 영구적으로 멈추는 것보다 훨씬 안전한 선택이에요.
더 궁금한 점이 있거나 도움이 필요하신가요? AI Setup Assistant에서 바로 물어보세요!
다음 단계
섹션 제목: “다음 단계”OpenClaw Expert
아직 막혀 있나요?
이 문서에서 답을 못 찾았다면 OpenClaw Expert에게 바로 물어보세요.