본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 08. 00:19

Playwright 작업을 자동화하는 Claude 브라우저 에이전트를 만들었습니다 — 스타터 키트를 소개합니다

요약

DOM 구조 변화에 취약한 기존 CSS/XPath 기반 브라우저 자동화의 한계를 극복하기 위해, Claude의 Vision API를 활용한 시각 기반 브라우저 에이전트 스타터 키트를 소개합니다.

핵심 포인트

  • 기존 셀렉터 방식은 DOM 변경 시 유지보수가 매우 어려움
  • 시각 기반 자동화는 구조가 아닌 사용자의 의도와 시각적 요소를 활용
  • Claude Vision API를 통해 스크린샷 기반의 상호작용 구현 가능
  • 리디자인 등 프론트엔드 변화에도 안정적인 자동화 유지

브라우저 자동화(Browser automation)에는 추악한 비밀이 하나 있습니다. 바로 오늘 당신이 작성한 코드는 이미 죽어가고 있다는 사실입니다.

당신은 로그인 양식을 역공학(reverse-engineering)하는 데 두 시간을 소비합니다. 정확한 XPath를 찾아냅니다. //div[@class='auth-container']//input[@data-testid='email-field']라고 작성하면 작동합니다. 코드를 배포하고, 그것을 잊어버립니다.

3주 후, 코드가 깨집니다. 프론트엔드 팀이 A/B 테스트를 진행하며 data-testidid로 교체했거나, 리디자인(redesign)을 적용했거나, 혹은 단순히 클래스 이름(class name)을 변경했기 때문입니다.

이런 일은 끊임없이 일어납니다. 대부분의 브라우저 자동화는 작성하기가 어려운 것이 아니라, 유지보수(maintain)하기가 어려운 것입니다.

셀렉터 문제 (The Selector Problem)

실제 문제는 이렇습니다: CSS 셀렉터(CSS selectors)와 XPath는 의도(intent)가 아니라 구조(structure)를 설명합니다.

당신이 #signup-form > .input-wrapper:nth-child(2) > input라고 작성할 때, 당신은 "이메일 필드를 채워라"라고 말하는 것이 아닙니다. "가입 양식 내부의 wrapper의 두 번째 자식인 input 요소를 찾아라"라고 말하는 것입니다. 기계는 그 input이 무엇을 하는지에 대해서는 전혀 알지 못하며, 오직 DOM 내의 위치만 알 뿐입니다.

DOM이 변경되는 순간 — 그리고 반드시 변경될 것입니다 — 당신의 셀렉터는 무효화됩니다.

동적 ID(Dynamic IDs)는 이 문제를 더욱 악화시킵니다. React, Angular, Vue는 모두 _3xR9scss-1q5f3g와 같은 클래스 이름을 생성합니다. 붙잡을 수 있는 안정적인 핸들(handle)이 없습니다. 결국 다음 배포(deploy)에서 하나라도 살아남기를 바라며 8개의 셀렉터를 체이닝(chaining)하게 됩니다.

다른 접근 방식: 보이는 것을 설명하기

DOM 구조를 설명하는 대신, 당신이 화면에서 보는 것을 설명한다면 어떨까요?

//input[@id='email_input_63h2'] 대신:

"이메일 주소 필드를 채워줘"라고 말하는 것입니다.

button.btn-primary:nth-child(3) 대신:

"양식 하단에 있는 파란색 Submit 버튼을 클릭해줘"라고 말하는 것입니다.

이것이 시각 기반 브라우저 자동화(vision-based browser automation)가 작동하는 방식입니다. 스크린샷을 찍습니다. 그것을 비전 모델(vision model)에 보냅니다. 그리고 평이한 영어(plain English)로 설명한 요소를 찾아 상호작용하도록 요청합니다. 모델은 레이아웃, 라벨, 색상, 문맥 등 인간이 보는 것과 정확히 똑같은 것을 봅니다.

DOM은 변합니다. 하지만 시각적 구조는 거의 변하지 않습니다. 리디자인 이후에도 파란색 Submit 버튼은 여전히 파란색 Submit 버튼입니다.

실제 작동 방식

다음은 Claude의 Vision API를 사용하여 구축된 시각 기반 상호작용 모듈 (vision-based interaction module)의 핵심입니다:

from vision_browser import VisionBrowser
from patchright.async_api import async_playwright

...

셀렉터 (selectors)도, XPath도, DOM 검사 (DOM inspection)도 필요 없습니다. 에이전트는 각 단계에서 스크린샷을 찍어 Claude에게 전송하고, 시각적 응답 (visual response)을 사용하여 어디를 클릭하거나 타이핑할지 결정합니다.

에이전트 레이어 (The Agent Layer)

전체 브라우저 작업을 수행하려면 이를 에이전트 루프 (agent loop)로 감싸야 합니다:

// browser-agent.js — 단순화된 버전

// 시작하기 전에, 지난번에 무엇이 실패했는지 확인합니다
...

핵심 부분은 failureHistory입니다. 각 실행 전에 에이전트는 과거 시도 기록이 담긴 SQLite 데이터베이스를 쿼리하여 무엇이 왜 실패했는지 읽고, 해당 컨텍스트 (context)를 가지고 시작합니다. 실행할 때마다 점점 더 똑똑해집니다.

CAPTCHA 처리

시각 기반 상호작용은 CAPTCHA를 처리하는 방식도 바꿉니다. 전통적인 셀렉터를 사용할 때는 특정 iframe ID나 클래스 (class)를 찾는 것이 탐지 방법이었습니다. 이는 매우 취약합니다. 시각 기반 방식에서는 Claude에게 페이지 상태 (page state)를 설명하도록 요청합니다:

state = await vb.understand_page()

if "captcha" in state.get("obstacles", []):
...

텍스트 CAPTCHA는 별도의 비용이 들지 않습니다. Claude가 직접 읽을 수 있기 때문입니다. 누르고 있기 (Press-and-hold) 방식의 CAPTCHA도 별도의 비용이 들지 않으며, 타이밍 알고리즘 (timing algorithm)으로 해결됩니다. 오직 어려운 것들(Arkose Labs, 일부 이미지 그리드)만이 유료 API를 필요로 합니다.

메모리 레이어 (The Memory Layer)

이 시스템을 프로덕션 수준 (production-ready)으로 만드는 마지막 요소는 지속성 (persistence)입니다. 모든 시도는 로그로 기록됩니다:

mem = BrowserMemory('/path/to/my.db')

# 시도하기 전에
...

에이전트가 동일한 사이트에서 다시 실행될 때, 먼저 이 기록을 읽습니다. 어떤 전략이 효과가 있었는지, 어떤 것이 실패했는지, 그리고 그 이유가 무엇인지 알고 있습니다. 이미 알고 있는 막다른 길을 반복하지 않습니다.

스타터 키트 가져오기

저는 이 모든 것 — vision_browser.py, captcha_brain.py, browser_memory.py, proxy_manager.py, 에이전트 러너 (agent runner), 그리고 바로 실행 가능한 3가지 예제 — 을 스타터 키트 (starter kit)로 패키징했습니다.

만약 여러분이 브라우저 에이전트를 구축하고 싶고, 제가 이미 고생하며 알아낸 부분들을 건너뛰고 싶다면:

Claude 브라우저 에이전트 스타터 키트 받기 →

$27. Python + Node.js. 프로덕션 준비 완료 (Production-ready). XPath 불필요.

질문이나 피드백이 있으신가요? 아래에 댓글을 남겨주세요 — 어떤 부분이든 더 자세히 설명해 드릴 준비가 되어 있습니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0