Skip to content

AI 에이전트를 위한 브라우저 자동화 컨트롤러

Notifications You must be signed in to change notification settings

urstory/browser-controller

Repository files navigation

browser-controller

AI 에이전트를 위한 브라우저 자동화 컨트롤러

풀스택패밀리 연구소 제작

Playwright 기반의 브라우저 자동화 컨트롤러입니다. CDP(Chrome DevTools Protocol)를 통해 Chrome 브라우저를 HTTP API로 제어할 수 있습니다.


프로젝트 배경

이 프로젝트는 moltbot의 브라우저 제어 모듈(src/browser/)을 분리하여 독립적인 패키지로 재구성한 것입니다.

풀스택패밀리 연구소에서 moltbot의 핵심 브라우저 자동화 기능만 추출하여, 다른 프로젝트에서도 쉽게 사용할 수 있도록 별도 패키징 작업을 수행했습니다.

분리 작업 내용

  • moltbot src/browser/ 디렉토리의 약 52개 TypeScript 파일 추출
  • 내부 의존성(config, infra, logging, media) 간소화 및 독립화
  • 독립 실행 가능한 HTTP API 서버 구성
  • 단위 테스트 및 E2E 테스트 작성

개요

이 프로젝트는 AI 에이전트가 웹 브라우저를 자유롭게 제어할 수 있도록 설계되었습니다. 에이전트는 HTTP API를 통해 브라우저를 시작하고, 페이지를 탐색하며, 요소를 클릭하거나 텍스트를 입력할 수 있습니다.

핵심 기능

  • 브라우저 생명주기 관리: Chrome 시작/중지
  • 탭 관리: 열기, 닫기, 포커스, 목록 조회
  • 페이지 탐색: URL 이동
  • 요소 상호작용: 클릭, 타이핑, 호버, 키 입력
  • 페이지 스냅샷: AI 친화적인 텍스트 형식으로 페이지 구조 파악
  • 스크린샷: PNG/JPEG 형식 지원
  • JavaScript 실행: 페이지 내 스크립트 평가

아키텍처

시스템 개요

browser-controller는 **Chrome DevTools Protocol (CDP)**을 통해 브라우저를 제어하는 HTTP API 서버를 제공합니다. Playwright를 브라우저 인터페이스로 사용하여 안정적인 페이지 조작 기능을 구현합니다.

┌────────────────────────────────────────────────────────────────┐
│                        AI 에이전트                              │
│  (Claude, 사용자 스크립트, 기타 LLM 애플리케이션)               │
└────────────────────┬───────────────────────────────────────────┘
                     │ HTTP API
                     ▼
┌────────────────────────────────────────────────────────────────┐
│               browser-controller 서버                          │
│  - HTTP 엔드포인트 제공 (/snapshot, /act, /tabs, ...)          │
│  - 프로필별 브라우저 컨텍스트 관리                             │
│  - 요청 라우팅 및 디스패칭                                     │
└────────────────────┬───────────────────────────────────────────┘
                     │
         ┌───────────┴───────────┐
         │                       │
         ▼                       ▼
┌──────────────────┐    ┌──────────────────┐
│  Playwright      │    │   Chrome/Chromium │
│  (CDP 클라이언트) │◄──►│    (CDP 서버)     │
│  - 페이지 조작    │    │   포트: 9222     │
│  - 스냅샷 생성    │    └──────────────────┘
│  - 요소 상호작용  │
└──────────────────┘

핵심 설계 원칙

원칙 설명
HTTP API 우선 언어에 독립적인 인터페이스 제공
역할 기반 참조 접근성 트리를 통한 안정적인 요소 식별
상태 비저장 각 요청은 독립적으로 처리 (상태는 브라우저가 관리)
프로필 격리 여러 브라우저 인스턴스 동시 실행 지원

역할 기반 참조 시스템

AI 에이전트가 웹 페이지를 제어할 때 가장 큰 문제는 DOM의 불안정성입니다. CSS 선택자나 XPath는 페이지 구조가 조금만 변경되어도 깨지기 쉽습니다.

이 프로젝트는 **접근성 트리( Accessibility Tree)**를 기반으로 요소를 식별합니다.

┌─────────────────────────────────────────────────────────────┐
│                   페이지 스냅샷 요청                         │
│              GET /snapshot?format=ai                         │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│            Playwright 접근성 트리 추출                      │
│   page.accessibility.snapshot()                             │
│                                                              │
│   AXNode {                                                   │
│     role: "button",                                          │
│     name: "로그인",                                          │
│     children: [...]                                         │
│   }                                                          │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│              역할 기반 스냅샷 변환                           │
│   - 대화형 요소만 필터링                                     │
│   - 계층 구조 유지                                           │
│   - 고유 참조 ID 할당 (e1, e2, e3...)                       │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│                  AI 친화적 출력                              │
│                                                              │
│   - e1: button "로그인"                                      │
│   - e2: textbox "이메일"                                     │
│   - e3: textbox "비밀번호" [password]                        │
│   - e4: link "비밀번호 찾기"                                 │
└─────────────────────────────────────────────────────────────┘

참조 ID의 장점:

  • 안정성: 페이지 구조가 변경되어도 역할(role)과 이름(name)이 유지되면 유효
  • 가독성: e1, e2 같은 짧은 ID로 에이전트가 쉽게 참조
  • 재사용: 같은 탭에서 참조가 캐시되어 여러 액션에 사용 가능

브라우저 제어 흐름

1. 에이전트 요청
   action="snapshot", profile="clawd", targetId="abc123"
         │
2. HTTP 서버 수신
   - 요청 파싱
   - 프로필 확인
   - 라우트 디스패칭
         │
3. Playwright 세션 관리
   - CDP 연결 확보 (캐시됨)
   - 페이지 객체 획득
   - 상태 모니터링 시작
         │
4. 페이지 조작 실행
   - 접근성 트리 추출
   - 역할 기반 참조 생성
   - 로케이터 변환
         │
5. 응답 반환
   {
     snapshot: "...",
     refs: { e1, e2, ... },
     targetId: "abc123"
   }

계층 구조

browser-controller/
├── 서버 계층
│   ├── HTTP 서버 (Express)
│   ├── 요청 라우팅
│   └── 프로필 관리
│
├── 연결 계층
│   ├── Playwright 세션 관리
│   ├── CDP 연결 캐싱
│   └── Chrome 프로세스 제어
│
├── 페이지 조작 계층
│   ├── 스냅샷 생성 (accessibility → role-based)
│   ├── 요소 상호작용 (click, type, hover...)
│   ├── 상태 추출 (쿠키, 스토리지)
│   └── 네비게이션
│
└── 데이터 표현 계층
    ├── 역할 기반 참조 (e1, e2, e3...)
    ├── 스냅샷 포맷 (ai, aria)
    └── 로케이터 매핑

지원 액션

액션 설명 예시
snapshot 페이지 구조 스냅샷 AI 친화적 텍스트 변환
click 요소 클릭 ref="e1"
type 텍스트 입력 ref="e2", text="검색어"
hover 마우스 호버 ref="e3"
scroll 페이지 스크롤 direction="down"
navigate URL 이동 url="https://..."
wait 대기 condition="load"
evaluate JavaScript 실행 code="..."

다중 브라우저 지원

한 서버에서 여러 브라우저 프로필을 동시에 실행할 수 있습니다:

{
  "profiles": {
    "default": { "cdpPort": 9222 },
    "sandbox": { "cdpPort": 9223 },
    "automation": { "cdpPort": 9224 }
  }
}

각 프로필은 독립적인 Chrome 프로세스와 CDP 포트를 가집니다.


설치

npm install

요구사항

  • Node.js >= 18.0.0
  • Chrome 또는 Chromium 설치 필요

빠른 시작

서버 시작

import { startBrowserServer } from "browser-controller";

const server = await startBrowserServer({
  port: 27182,
  cdpPort: 9222,
  headless: false,
});

console.log(`브라우저 제어 서버 실행 중: ${server.baseUrl}`);

브라우저 컨트롤러 사용

const browser = server.createController("clawd");

// 브라우저 시작
await browser.start();

// 탭 열기
const tab = await browser.openTab("https://google.com");

// 페이지 스냅샷 획득
const snapshot = await browser.snapshot({ targetId: tab.targetId });

// 요소 클릭 (ref 기반)
await browser.click("e1", { targetId: tab.targetId });

// 텍스트 입력
await browser.type("e2", "검색어", { targetId: tab.targetId, submit: true });

// 브라우저 종료
await browser.stop();

HTTP API 엔드포인트

메서드 경로 설명
GET / 브라우저 상태 조회
POST /start 브라우저 시작
POST /stop 브라우저 중지
GET /tabs 탭 목록 조회
POST /tabs/open 새 탭 열기
GET /snapshot 페이지 스냅샷
POST /act 페이지 액션 실행

에이전트의 브라우저 제어 방식

스냅샷 기반 요소 참조 시스템

AI 에이전트가 브라우저를 제어할 때 가장 중요한 것은 페이지의 어떤 요소를 조작할지 식별하는 것입니다. 이 프로젝트는 ref 기반 참조 시스템을 사용합니다.

1단계: 스냅샷 획득

curl "http://127.0.0.1:27182/snapshot?profile=clawd&targetId=..."

2단계: 스냅샷 분석

스냅샷은 페이지를 AI가 이해하기 쉬운 텍스트 형식으로 반환합니다:

- search [ref=e31]:
  - combobox "검색" [active] [ref=e42]
  - button "Google 검색" [ref=e69]
  - button "I'm Feeling Lucky" [ref=e70]

각 상호작용 가능한 요소에는 [ref=e42]와 같은 참조 ID가 부여됩니다.

3단계: ref를 사용한 액션 실행

curl -X POST "http://127.0.0.1:27182/act?profile=clawd" \
  -d '{"kind":"type","ref":"e42","text":"검색어","submit":true}'

실제 사용 예시: 구글 검색

다음은 에이전트가 구글에서 "바이브 코딩"을 검색하고 결과를 파싱하는 과정입니다.

1. 브라우저 시작

curl -X POST "http://127.0.0.1:27182/start?profile=clawd"
# 응답: {"ok":true,"profile":"clawd"}

2. 구글 탭 열기

curl -X POST "http://127.0.0.1:27182/tabs/open?profile=clawd" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.google.com"}'

# 응답: {"targetId":"8B2E87A6...","title":"","url":"https://www.google.com/"}

3. 페이지 스냅샷으로 검색창 찾기

curl "http://127.0.0.1:27182/snapshot?profile=clawd&targetId=8B2E87A6..."

스냅샷 결과에서 검색창을 찾습니다:

- search [ref=e31]:
  - combobox "검색" [active] [ref=e42]   ← 이것이 검색 입력란!
  - button "Google 검색" [ref=e69]

4. 검색어 입력 및 검색 실행

curl -X POST "http://127.0.0.1:27182/act?profile=clawd" \
  -H "Content-Type: application/json" \
  -d '{
    "targetId": "8B2E87A6...",
    "kind": "type",
    "ref": "e42",
    "text": "바이브 코딩",
    "submit": true
  }'

# 응답: {"ok":true,"targetId":"8B2E87A6..."}

5. 검색 결과 스냅샷 파싱

검색 결과 페이지의 스냅샷을 분석하여 링크를 추출합니다:

- link "바이브 코딩 나무위키 https://namu.wiki › 바이브 코딩" [ref=e353]:
  - /url: https://namu.wiki/w/바이브%20코딩

- link "2년간의 'vibecoding'을 끝내고..." [ref=e381]:
  - /url: https://news.hada.io/topic?id=26148

- link "바이브 코딩 설명: 도구 및 가이드" [ref=e414]:
  - /url: https://cloud.google.com/discover/what-is-vibe-coding?hl=ko

6. 결과 추출

스냅샷에서 /url: 패턴을 파싱하여 검색 결과 URL을 추출합니다:

# 사이트 URL
1 나무위키 https://namu.wiki/w/바이브%20코딩
2 GeekNews https://news.hada.io/topic?id=26148
3 Google Cloud https://cloud.google.com/discover/what-is-vibe-coding?hl=ko
4 브런치 https://brunch.co.kr/@hsy110405/33
5 위키백과 https://ko.wikipedia.org/wiki/바이브_코딩

7. 브라우저 종료

curl -X POST "http://127.0.0.1:27182/stop?profile=clawd"
# 응답: {"ok":true,"stopped":true,"profile":"clawd"}

에이전트 통합 가이드

에이전트가 브라우저를 제어하는 패턴

1. 스냅샷 획득 → 페이지 구조 파악
2. ref 식별 → 조작할 요소 찾기
3. 액션 실행 → click, type, navigate 등
4. 결과 확인 → 새 스냅샷으로 상태 확인
5. 반복 → 목표 달성까지 1-4 반복

스냅샷 파싱 팁

  • link 요소: /url: 속성에서 URL 추출
  • button 요소: 클릭 가능한 버튼
  • combobox/textbox: 텍스트 입력 가능
  • [active]: 현재 포커스된 요소
  • [ref=eN]: 액션에 사용할 참조 ID

예시: 특정 링크 클릭

# 스냅샷에서 원하는 링크의 ref 확인
# - link "자세히 보기" [ref=e15]

# 해당 ref로 클릭 실행
curl -X POST "http://127.0.0.1:27182/act?profile=clawd" \
  -d '{"kind":"click","ref":"e15","targetId":"..."}'

설정

환경 변수

변수 설명 기본값
BROWSER_CDP_PORT CDP 포트 9222
BROWSER_HEADLESS 헤드리스 모드 false
BROWSER_EXECUTABLE_PATH Chrome 실행 파일 경로 자동 감지
BROWSER_SERVER_PORT HTTP 서버 포트 27182
BROWSER_BIND_ADDRESS 바인드 주소 127.0.0.1

설정 파일

프로젝트 루트에 browser-controller.json 생성:

{
  "cdpPort": 9222,
  "headless": false,
  "serverPort": 27182,
  "bindAddress": "127.0.0.1"
}

테스트

# 단위 테스트
npm test

# E2E 테스트 (Chrome 필요)
npm run test:e2e

보안 주의사항

  • CDP 포트는 기본적으로 localhost에만 바인딩됩니다
  • CDP 포트를 외부에 노출하면 브라우저를 완전히 제어할 수 있으므로 주의하세요
  • 프로덕션 환경에서는 attachOnly: true 옵션을 권장합니다

버전 호환성

  • playwright-core 버전은 1.58.0으로 고정되어 있습니다
  • 다른 버전 사용 시 CDP 프로토콜 호환성 문제가 발생할 수 있습니다

라이선스

MIT


풀스택패밀리 연구소 | 2026

About

AI 에이전트를 위한 브라우저 자동화 컨트롤러

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors