Cursor와 BrowserAct를 사용하여 취약한 셀렉터 없이 동적 페이지를 처리하는 방법
요약
Cursor와 BrowserAct를 활용하여 동적인 웹 페이지 환경에서 취약한 셀렉터 없이 브라우저 자동화를 수행하는 방법을 설명합니다. AI 에이전트가 '검사-실행-재평가' 루프를 통해 변화하는 DOM 구조에 유연하게 대응하도록 하는 워크플로우를 제안합니다.
핵심 포인트
- 현대적 웹의 동적 DOM 업데이트로 인한 기존 셀렉터의 취약성 문제 해결
- Cursor와 BrowserAct를 결합한 '검사-실행-재평가' 루프 구축
- 하드코딩된 셀렉터 대신 실시간 페이지 상태 기반의 동작 결정
- AI 에이전트의 브라우저 조작 신뢰성 및 유지보수성 향상
요약 (TL;DR)
현대적인 웹 애플리케이션은 끊임없이 변화합니다. 컴포넌트는 다시 렌더링되며, 생성된 속성(attributes)은 빌드마다 다를 수 있습니다. UI가 동일해 보일 때조차, 브라우저 자동화(browser automation)는 페이지가 변경되기 전에 캡처된 가설에 의존하기 때문에 실패할 수 있습니다.
이 글에서 저는 Cursor와 BrowserAct CLI를 사용하여 동적인 프로젝트 필터를 테스트했습니다. 신뢰할 수 없는 셀렉터(selectors)에 의존하는 대신, Cursor는 BrowserAct를 사용하여 현재 페이지 상태를 검사(inspect)하고 취약한 셀렉터에 의존하지 않고 작업을 완료했습니다.
목표는 DOM을 제거하거나 Playwright를 대체하는 것이 아니었습니다. 목표는 AI 에이전트에게 현대적이고 동적인 웹사이트에서 작동하는 신뢰할 수 있는 검사(inspect) → 실행(act) → 재평가(reassess) 루프를 제공하는 것이었습니다.
자, 그럼 시작해 봅시다! 🏎️
🖥️ 문제점: 동적 DOM 업데이트가 기존 셀렉터를 깨뜨림
브라우저 테스트는 몇 주 동안 성공적으로 실행되다가, 아무런 해가 없는 프론트엔드 업데이트 이후 갑자기 실패할 수 있습니다.
버튼은 여전히 보입니다. 기능도 여전히 작동합니다. 하지만 테스트는 예상했던 요소가 더 이상 존재하지 않기 때문에 실패합니다.
<!-- 초기 페이지 -->
<div class="toolbar">
<button id="date-filter-btn">Filter by Date</button>
...
하이드레이션(hydration) 이후:
<div class="toolbar toolbar--v2">
<div class="toolbar__indent"></div>
<button id="status-filter-btn" class="btn btn--active">
...
await page.click("#date-filter-btn")
이 코드는 셀렉터가 더 이상 현재 페이지와 일치하지 않기 때문에 실패할 수 있습니다.
👀 하드코딩된 셀렉터가 실패하는 이유
현대적인 브라우저 자동화는 애플리케이션이 이미 알려져 있을 때 가장 잘 작동합니다. 엔지니어들은 페이지 구조를 미리 이해하고 애플리케이션이 진화함에 따라 해당 테스트를 유지 관리할 수 있기 때문에 신뢰할 수 있는 Playwright 테스트를 작성할 수 있습니다.
// Playwright: 당신이 페이지 구조를 알고 있다고 가정함
await page.click('#filter-button'); // 오늘 이 ID가 존재한다면 작동함
await page.waitForTimeout(500); // 이것이 충분히 길기를 희망함
...
AI 에이전트에게는 도전 과제가 다릅니다. Cursor가 익숙하지 않은 웹사이트를 조작할 때, 어떤 요소가 존재하는지 또는 인터페이스가 어떻게 구성되어 있는지 가정할 수 없습니다. 의미 있는 상호작용이 일어날 때마다 페이지가 변경되어 새로운 컨트롤이 도입되거나 기존 컨트롤이 교체될 수 있습니다. 이전에 캡처한 셀렉터 (Selector)에 의존하는 대신, 에이전트는 현재 페이지 상태를 검사하고, 실제로 사용 가능한 것에 기반하여 다음 동작을 선택하며, UI가 업데이트된 후 다시 평가해야 합니다. 이것이 바로 BrowserAct가 해결하고자 설계된 격차입니다.
⚙️ BrowserAct가 Cursor를 어떻게 변화시키는가
Cursor에게 이전에 캡처한 셀렉터를 기억하라고 요청하는 대신, BrowserAct는 에이전트가 다음 동작을 결정하기 전에 현재 브라우저 상태를 반복적으로 검사할 수 있게 해줍니다.
워크플로우는 다음과 같이 변합니다:
- 페이지 열기
- 현재 상태 읽기
- 동작 선택
- 동작 실행
- 안정될 때까지 대기
- 상태 다시 읽기
- 결과 확인
이는 Cursor에게 현재 페이지 상태의 압축된 표현을 제공하여, 에이전트가 페이지를 검사하고, 현재 사용 가능한 것에 따라 행동하며, 의미 있는 UI 변경이 있을 때마다 다시 평가할 수 있도록 합니다. 이전 DOM 스냅샷의 가정에 의존하기보다, Cursor는 현재 존재하는 페이지와 지속적으로 상호작용하므로 동적인 인터페이스에 훨씬 더 탄력적으로 대응할 수 있습니다.
💻 실제 동적 페이지 테스트
말로만 설명하기보다 직접 실행해 보겠습니다. 작동하는 워크플로우를 보여주기 위해, 검색 가능한 프로젝트 목록을 사용했습니다.
설치
시작하기 위해 browser-act를 설치해 보겠습니다.
uv tool install browser-act-cli --python 3.12
다음과 같이 버전을 확인할 수 있습니다:
browser-act --version
저는 다음 버전을 보여주고 있습니다. 사용자의 버전은 더 최신일 수 있지만, 핵심 내용은 동일합니다:
Cursor 앱을 연 상태에서, 우리 앱의 현재 상태를 가져오는 테스트를 진행해 보겠습니다.
첫 번째 테스트 생성하기
이를 위해, 입력창에 다음과 같은 프롬프트 (prompt)를 입력하겠습니다:
Cursor에서 BrowserAct를 사용하여 EmbedCatalog의 검색 기능 (search functionality)을 테스트하세요. 모든 동작 전에 현재 페이지 상태 (page state)를 읽으세요. 페이지가 변경되면 이전 인덱스 (indices)를 재사용하는 대신 페이지 상태를 새로고침하세요. 프로젝트를 검색하고, 상세 페이지를 연 다음, 올바른 프로젝트 정보가 표시되는지 확인하세요.
browser-act --session embedcatalog browser open https://embedcatalog.com
browser-act --session embedcatalog state
그 후 테스트 프로세스가 시작됩니다.
Cursor가 생성 시점에 명령 실행 권한을 요청할 수 있다는 점에 유의하세요. 다음과 같은 모습으로 나타날 것입니다:
실행 (run) 버튼을 클릭하면, 잠시 후 첫 번째 명령이 실행되어 브라우저가 열립니다. 자동화 도구 (automation tools)를 처음 사용하는 경우, 브라우저에서 동작 확인을 요청할 수 있습니다. 단순히 허용 (allow)을 클릭하면 웹사이트가 열립니다:
테스트를 실행하는 동안 자동화된 브라우저 동작을 경험할 수 있습니다. 걱정하지 마세요, 이는 BrowserAct가 작동하고 있는 것입니다. BrowserAct는 우리의 명령을 바탕으로 버튼을 클릭하거나, 스크롤하거나, 현재 페이지 상태를 가져오기 위한 기타 동작들을 수행할 수 있습니다. 이전에 캡처된 셀렉터 (Selector)에 의존하는 대신, BrowserAct는 현재 페이지에서 사용 가능한 상호작용 요소들의 압축된 표현 (Compact representation)을 생성합니다.
실행 중에는 페이지를 닫지 마세요. 그렇지 않으면 오류가 발생할 수 있습니다.
제 Composer 2.5가 응답을 생성한 후, Cursor는 다음과 같은 결과를 보여주었습니다:
우리는 어떠한 셀렉터 (Selector)도 지정하지 않았습니다. Cursor는 BrowserAct의 도움을 받아 필요한 입력창을 자동으로 찾고, 페이지를 검색하며, 스캔했습니다. 우리는 DOM을 전혀 살펴보지 않고 단순히 간단한 프롬프트 (Prompt)를 생성했을 뿐입니다.
테스트 확장하기
이제 더 복잡한 검색 옵션을 시도해 보겠습니다. 다음과 같은 명령어를 나열하고 워크플로 (Workflow)를 간략하게 설명하겠습니다:
browser-act --session embedcatalog click <CURRENT_INDEX>
browser-act --session embedcatalog wait stable
browser-act --session embedcatalog state
...
이 워크플로에서 Cursor는 먼저 검색 인터페이스를 열고 페이지가 안정화될 때까지 기다립니다. 그런 다음 페이지 상태를 새로 고치고, 검색 필드에 "BrowserAct"를 입력한 뒤, 결과가 로드될 때까지 기다립니다. 그리고 올바른 결과를 선택하기 전에 업데이트된 상태를 다시 읽습니다. 마지막으로, 예상했던 프로젝트 페이지가 성공적으로 열렸는지 확인하기 위해 페이지 콘텐츠를 마크다운 (Markdown) 형식으로 가져옵니다.
Cursor에 동일한 내용을 입력하고 저희의 명령어를 추가하자, 잠시 후 다음과 같은 결과를 얻게 됩니다:
테스트가 성공적으로 완료되었습니다. 모든 상호작용 후, Cursor는 현재 페이지 상태를 새로고침한 다음 계속 진행하여 업데이트된 인터페이스에 적응할 수 있게 했습니다.
검증 결과 정확한 프로젝트가 열렸음을 확인했습니다. 프로젝트 이름, 설명, 최종 업데이트 날짜, 별점 개수(star count), 태그, 그리고 프로젝트 URL이 모두 검색 결과와 일치했기 때문에, 하드코딩된 셀렉터에 의존하지 않고도 워크플로우가 PASS 결과로 완료되었습니다.
좀 더 간결한 버전입니다. 핵심 아이디어는 유지하면서 읽기가 훨씬 수월합니다.
👀 BrowserAct가 실제로 해결한 문제점
BrowserAct는 절대 깨지지 않는 셀렉터를 생성하는 것이 아닙니다. 대신, AI 에이전트가 다음에 무엇을 할지 결정하기 전에 현재 페이지 상태를 반복적으로 검사함으로써 UI 변경으로부터 회복할 수 있는 더 나은 방법을 제공합니다.
이전에 캡처된 ID, CSS 셀렉터 또는 XPath에 의존하는 대신, 에이전트는 지금 존재하는 페이지 자체와 함께 작동합니다. 이는 워크플로우를 다음에서:
Remember → Click → Hope
다음으로 전환시킵니다:
Inspect → Act → Wait → Inspect Again
동적인 웹사이트에서 브라우저 자동화(browser automation)를 더욱 탄력적으로 만들기.
🔎 Playwright가 여전히 적합한 경우
이것은 Playwright를 대체하는 것이 아닙니다. Playwright는 결정론적(deterministic) 브라우저 테스트를 위한 훌륭한 선택지로 남아 있으며, 특히 엔지니어가 안정적인 역할 로케이터(role locators), 텍스트 로케이터(text locators) 또는 테스트 ID(test IDs)를 사용할 수 있는 경우에 더욱 그렇습니다.
BrowserAct는 다른 문제를 해결합니다. BrowserAct는 이전에 캡처된 셀렉터(selectors)에 의존하는 대신 현재 페이지 상태(page state)를 바탕으로 의사결정을 내림으로써, AI 에이전트가 익숙하지 않거나 끊임없이 변화하는 웹사이트를 운영할 수 있도록 돕습니다. 이 두 도구는 경쟁 관계가 아닌 상호 보완적인 솔루션입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
