브라우저 기반 AI 에이전트 설계 방법 – LangGraph로 웹 자동화 에이전트 만들기

AI 에이전트를 처음 만들어보던 시절이 있었다. 그때 제일 많이 막혔던 지점이 “이 에이전트가 실제로 뭔가를 하게 만들려면 어떻게 해야 하지?”였다. 텍스트 생성은 잘 됐다. 근데 에이전트가 웹사이트에 들어가서 정보를 긁어오고, 양식을 채우고, 버튼을 누르는 것까지 연결하는 건 전혀 다른 문제였다. LLM이 답을 알아도, 그 답을 실행에 옮기는 부분은 개발자가 직접 설계해야 했다.

2026년 현재, 그 구조가 빠르게 정립되고 있다. Google이 Chrome에 Gemini를 넣고 auto browse라는 에이전트 기능을 출시하면서, 브라우저 기반 AI 에이전트가 실제 상용 서비스로 등장했다. Chrome + Gemini가 브라우저를 AI 플랫폼으로 바꾸는 전략의 핵심에 바로 이 에이전트 구조가 있다. Google은 Gemini가 직접 웹페이지를 탐색하고, 클릭하고, 구매까지 처리하는 수직 통합 구조를 만들었다. 이 글에서는 그 구조가 어떻게 작동하는지를 분석하고, 개발자가 직접 LangGraph로 브라우저 기반 에이전트를 설계하는 방법을 실전 아키텍처 중심으로 풀어본다.


브라우저가 AI 에이전트에게 특별한 이유

AI 에이전트가 실제로 유용하려면 도구가 있어야 한다. 텍스트만 생성하는 에이전트는 결국 사람이 그 텍스트를 보고 직접 실행해야 한다. 에이전트가 스스로 실행까지 해야 진짜 자동화가 된다.

에이전트에게 줄 수 있는 도구는 크게 세 가지 환경에 있다. API를 통해 직접 호출하는 방법, OS 레벨에서 GUI를 조작하는 방법, 그리고 브라우저를 통해 웹을 조작하는 방법이다. 이 셋 중에서 브라우저가 가장 강력한 이유는 간단하다. 사람이 하는 업무의 대부분이 이미 웹 안에 있기 때문이다. 이메일, 문서, 쇼핑, 예약, 정보 검색, 폼 제출, 보고서 작성. 이 모든 것이 브라우저를 통해 이루어진다.

API 방식은 서비스가 API를 제공해야만 쓸 수 있다. 하지만 브라우저를 통하면 API가 없는 서비스도 사람처럼 접근할 수 있다. 버튼이 있으면 클릭하고, 입력창이 있으면 타이핑하고, 링크가 있으면 이동한다. 인간이 브라우저에서 하는 모든 상호작용을 에이전트도 동일하게 할 수 있다. 이것이 브라우저 기반 에이전트가 범용적인 이유다.


전통적인 브라우저 자동화의 한계

브라우저 자동화 자체는 새로운 기술이 아니다. Selenium이 나온 게 2004년이고, Puppeteer와 Playwright 같은 도구들도 이미 수년 전부터 쓰여왔다. 그런데 왜 이게 “AI 에이전트”와 연결되면서 새로운 얘기가 되는 걸까.

기존 브라우저 자동화의 핵심 문제는 취약성이다. Playwright나 Puppeteer 기반으로 짠 스크립트는 웹사이트의 DOM 구조에 종속된다. 버튼의 클래스명이 btn-primary에서 button-main으로 바뀌거나, 페이지 구조가 리뉴얼되면 스크립트가 깨진다. 개발자가 직접 들어가서 셀렉터를 고쳐줘야 한다. 유지보수 비용이 끊임없이 든다.

더 근본적인 문제는 의도 이해다. 기존 스크립트는 “3번째 li 요소의 a 태그를 클릭해라”처럼 구체적인 기계어 수준의 명령으로 작동한다. “로그인하고 가장 최근 주문의 배송 상태를 확인해라”라는 인간의 의도를 이해하고 실행하는 능력이 없다. 여기서 LLM이 들어온다. LLM은 페이지를 보고 “이게 로그인 버튼이겠구나”, “이 영역이 주문 내역이겠구나”를 스스로 판단한다. 클래스명이 바뀌어도 시각적으로나 의미적으로 같은 요소라면 인식하고 클릭한다. 브라우저 자동화에 LLM의 추론 능력이 더해지면서 에이전트의 범용성이 완전히 달라진다.


LangGraph가 브라우저 에이전트에 적합한 이유

AI 에이전트 프레임워크는 2025년 기준으로 LangGraph, CrewAI, AutoGen 등 여러 선택지가 있다. 브라우저 에이전트 설계에서 LangGraph가 특히 유리한 건 상태 관리와 조건부 분기 처리 때문이다.

브라우저 에이전트는 단순한 단일 호출이 아니다. “여행 일정을 세워줘”라는 요청 하나에 항공 검색 → 가격 비교 → 호텔 검색 → 일정 최적화 → 캘린더 등록 같은 여러 단계가 이어진다. 각 단계의 결과가 다음 단계의 입력이 되고, 중간에 오류가 나거나 사용자 확인이 필요한 분기점도 생긴다. 이런 복잡한 멀티스텝 워크플로우를 다루는 데 LangGraph의 그래프 기반 구조가 딱 맞다.

LangGraph의 핵심 개념은 세 가지다. 노드(Node)는 특정 작업을 수행하는 단위다. 에지(Edge)는 노드 간의 실행 흐름을 정의한다. 상태(State)는 노드 사이를 오가는 공유 데이터 구조다. 브라우저 에이전트로 치면 노드는 “웹페이지 탐색”, “요소 클릭”, “텍스트 입력”, “결과 분석” 같은 작업들이 된다. 상태는 현재 URL, 페이지 내용, 지금까지 수행한 작업 기록, 최종 목표 같은 정보를 담는다. 에지는 특정 노드 실행 후 다음에 어디로 가야 하는지, 조건에 따라 분기를 정의한다.

LangGraph의 또 다른 강점은 Human-in-the-loop 지원이다. Chrome의 auto browse도 구매 확인이나 민감한 작업 전에 사용자에게 승인을 요청하는 구조를 갖고 있다. LangGraph에서도 특정 노드에서 실행을 일시 중단하고 사용자 확인을 받은 뒤 재개하는 패턴을 기본 기능으로 지원한다. 자동화와 인간 통제를 동시에 유지하는 구조를 쉽게 구현할 수 있다.


브라우저 에이전트 기본 아키텍처 설계

실제로 어떻게 설계하는지 뼈대를 보자. 브라우저 기반 LangGraph 에이전트의 기본 구조는 다음 흐름으로 잡는다.

[사용자 요청 입력]
        ↓
[목표 파싱 노드] → 요청을 세부 태스크로 분해
        ↓
[브라우저 초기화 노드] → Playwright로 헤드리스 브라우저 실행
        ↓
[페이지 탐색 노드] → URL 이동 및 페이지 로드
        ↓
[페이지 분석 노드] → LLM이 현재 페이지 내용 해석
        ↓
[액션 결정 노드] → 다음에 할 행동 결정 (클릭/입력/스크롤/이동)
        ↓
[액션 실행 노드] → Playwright로 실제 DOM 조작
        ↓
[결과 평가 노드] → 목표 달성 여부 판단
        ↓
    목표 달성? → Yes → [결과 반환]
              → No  → [페이지 탐색 노드]로 루프 복귀

State 정의부터 시작하는 게 맞다. TypedDict 기반으로 에이전트가 추적해야 할 정보를 명시적으로 설계한다.

from typing import TypedDict, List, Optional
from langgraph.graph import StateGraph, END

class BrowserAgentState(TypedDict):
    goal: str                    # 최종 목표
    current_url: str             # 현재 페이지 URL
    page_content: str            # 현재 페이지 텍스트 내용
    screenshot_b64: Optional[str] # 현재 페이지 스크린샷 (base64)
    action_history: List[str]    # 지금까지 수행한 액션 목록
    next_action: Optional[dict]  # LLM이 결정한 다음 액션
    result: Optional[str]        # 최종 결과
    is_done: bool                # 완료 여부

상태를 정의한 후, 각 노드를 함수로 구현한다. 핵심 노드는 페이지 분석 노드와 액션 결정 노드다. 페이지 분석 노드에서는 Playwright로 현재 페이지의 텍스트와 스크린샷을 추출해서 상태에 저장한다. 액션 결정 노드에서는 LLM에게 현재 상태와 목표를 주고, 다음에 수행할 액션을 JSON으로 받는다.

from playwright.async_api import async_playwright
from langchain_google_genai import ChatGoogleGenerativeAI

async def analyze_page_node(state: BrowserAgentState) -> BrowserAgentState:
    # Playwright로 현재 페이지 내용 추출
    page_text = await browser_page.inner_text("body")
    screenshot = await browser_page.screenshot()
    screenshot_b64 = base64.b64encode(screenshot).decode()
    
    return {
        **state,
        "page_content": page_text[:3000],  # 토큰 절약을 위해 앞부분만
        "screenshot_b64": screenshot_b64
    }

async def decide_action_node(state: BrowserAgentState) -> BrowserAgentState:
    llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash")
    
    prompt = f"""
    목표: {state['goal']}
    현재 URL: {state['current_url']}
    페이지 내용: {state['page_content']}
    지금까지 한 작업: {state['action_history']}
    
    다음에 수행할 액션을 JSON으로 반환하세요.
    가능한 액션: click(selector), type(selector, text), navigate(url), done(result)
    """
    
    response = await llm.ainvoke(prompt)
    next_action = json.loads(response.content)
    
    return {**state, "next_action": next_action}

실전 패턴 — 웹 리서치 에이전트와 폼 자동화 에이전트

브라우저 에이전트의 대표적인 두 가지 패턴을 살펴보자.

첫 번째는 웹 리서치 에이전트다. 여러 사이트를 돌아다니며 정보를 수집하고 정리하는 패턴이다. 이 케이스에서는 단일 브라우저 세션이 아니라 여러 탭을 병렬로 열어 정보를 동시에 수집하고 LangGraph의 parallel 노드 실행으로 처리하는 것이 효율적이다. Playwright의 Browser Context를 사용하면 동일한 브라우저 인스턴스에서 메모리 효율적으로 여러 독립 세션을 유지할 수 있다.

두 번째는 폼 자동화 에이전트다. 반복적인 데이터 입력, 신청서 제출, 정기 보고서 업로드 같은 작업이다. 이 패턴에서는 에러 핸들링이 핵심이다. 폼 구조가 예상과 다르거나, CAPTCHA가 나오거나, 로그인 세션이 만료되는 상황을 에이전트가 스스로 감지하고 처리하거나 사용자에게 에스컬레이션하는 로직이 필요하다. LangGraph에서는 이런 예외 상황을 조건부 에지로 처리한다. 에러 감지 노드가 문제를 발견하면 복구 서브그래프로 분기하거나 human-in-the-loop 포인트로 넘기는 구조를 만들 수 있다.


Chrome auto browse 구조와 비교

Google의 auto browse가 내부적으로 어떤 구조인지는 공개되지 않았지만, 외부에서 관찰할 수 있는 동작 방식과 Google의 AI 인프라를 고려하면 대략적인 구조를 추론할 수 있다.

가장 큰 차이는 멀티모달 인식이다. Chrome auto browse는 Gemini 3의 시각 이해 능력을 활용해 페이지를 이미지로 해석한다. 텍스트 기반 DOM 파싱이 아니라 사람이 화면을 보는 것처럼 레이아웃을 이해하고 클릭 대상을 찾는다. 일반 개발자가 Playwright + LLM으로 만드는 에이전트도 스크린샷 기반 접근을 섞으면 비슷한 효과를 낼 수 있지만, 비용과 속도 면에서 차이가 있다.

또 하나는 Chrome DevTools Protocol(CDP)과의 깊은 통합이다. Chrome 브라우저 자체가 에이전트의 실행 환경이기 때문에, auto browse는 브라우저 내부 API를 직접 활용한다. 외부에서 Playwright로 Chrome을 원격 조작하는 것과 달리, 브라우저 안에서 직접 DOM에 접근하는 방식이라 반응 속도와 안정성이 다르다.

그 뒤에서 이 추론을 처리하는 인프라가 어떻게 돌아가는지는 Gemini 실행 인프라 — Google TPU와 Vertex AI 구조에서 자세히 다뤘다. Gemini 3 기반의 클라우드 추론과 Gemini Nano 기반의 온디바이스 추론이 작업의 복잡도에 따라 조합되는 하이브리드 구조가 auto browse 뒤에 깔려 있다.


MCP로 브라우저 에이전트 확장하기

2025년부터 에이전트 생태계에서 빠르게 표준이 되고 있는 게 MCP(Model Context Protocol)다. Anthropic이 공개한 오픈 프로토콜로, AI 에이전트가 외부 도구나 서비스와 표준화된 방식으로 통신하는 인터페이스를 정의한다.

브라우저 자동화 측면에서 주목할 건 Microsoft가 2025년 3월 공개한 Playwright MCP 서버다. 이 MCP 서버를 통하면 LLM이 직접 Playwright 명령을 실행할 수 있다. 스크린샷 대신 접근성 스냅샷(Accessibility Snapshot)을 사용하기 때문에 비전 모델이 아닌 텍스트 모델로도 브라우저 자동화가 가능하고, 속도와 비용이 개선된다. LangGraph와 MCP를 조합하면, LangGraph가 워크플로우 오케스트레이션을 담당하고 MCP가 브라우저 조작의 표준 인터페이스를 제공하는 구조로 설계할 수 있다.

MCP 생태계가 확산되면서 주요 AI 어시스턴트들(ChatGPT, Claude, Gemini)이 모두 MCP를 지원하게 됐다. 브라우저 에이전트를 MCP 서버로 구현해두면, 어떤 AI 프론트엔드에서도 동일한 브라우저 자동화 기능을 사용할 수 있는 플랫폼 독립적인 구조가 된다.


운영 환경에서 고려할 것들

설계는 됐는데 운영에서 문제가 터진다. 브라우저 에이전트를 실제 프로덕션에 배포할 때 반드시 챙겨야 할 부분들이 있다.

첫째는 세션 관리다. 에이전트가 로그인이 필요한 서비스를 다루는 경우, 쿠키와 세션 정보를 유지하면서 작업을 이어가야 한다. Playwright의 Browser Context는 쿠키와 로컬 스토리지를 직렬화해서 저장하고 복원하는 기능을 제공한다. 이 상태를 LangGraph의 checkpointer 기능과 결합하면, 에이전트 작업이 중단됐다가 재개될 때 브라우저 세션도 함께 복원할 수 있다.

둘째는 봇 감지 우회다. 많은 서비스가 자동화 트래픽을 감지하고 차단하는 시스템을 운영한다. Playwright의 기본 설정으로는 감지될 수 있어서, 사람처럼 보이는 마우스 움직임 패턴, 랜덤한 딜레이 삽입, 브라우저 핑거프린트 조작 같은 처리가 필요하다. Browserbase 같은 클라우드 브라우저 인프라 서비스는 이런 스텔스 기능을 내장해서 제공한다. 2025년 기준 Browserbase는 1,000개 이상의 고객사를 확보하며 연간 5,000만 건 이상의 세션을 처리했다.

셋째는 비용 관리다. LLM 호출은 매 페이지 분석과 액션 결정마다 발생한다. 복잡한 웹 태스크 하나에 수십 번의 LLM 호출이 이루어질 수 있고, 스크린샷을 넣으면 토큰 비용이 급격히 올라간다. 접근성 트리나 DOM 텍스트만으로 처리할 수 있는 단계에서는 이미지 없이 텍스트만 LLM에 넣는 것이 비용 절감에 효과적이다. 시각적 판단이 반드시 필요한 단계에서만 스크린샷을 사용하는 선택적 멀티모달 전략이 필요하다.


마무리 : 에이전트가 웹을 다루는 시대의 설계 원칙

AI 에이전트가 웹을 직접 다루는 건 이제 개념 증명 수준이 아니다. Google이 Chrome에 auto browse를 탑재하고, Amazon이 Nova Act를 출시하고, Anthropic이 Computer Use API를 내놓으면서, 브라우저 기반 에이전트는 실제 사용자들이 쓰는 기능이 됐다. 2025년 어도비 분석에 따르면 AI 에이전트에서 미국 리테일 사이트로의 트래픽이 전년 대비 4,700% 증가했다. 에이전트가 웹에서 하는 행동이 이미 측정 가능한 규모로 실재하고 있다는 뜻이다.

LangGraph로 브라우저 에이전트를 설계할 때의 핵심 원칙을 정리하면 이렇다. 상태를 명시적으로 설계하라. 에이전트가 현재 어디에 있고 무엇을 알고 있는지가 타입 정의된 상태 객체에 항상 담겨 있어야 한다. 루프를 두려워하지 마라. 브라우저 에이전트는 목표 달성까지 반복하는 구조가 기본이다. LangGraph의 사이클 지원이 이걸 가능하게 해준다. 그리고 Human-in-the-loop를 설계에 포함하라. 에이전트가 완전 자율로 모든 것을 처리하는 것보다, 중요한 결정 포인트에서 사람이 개입할 수 있는 구조가 실제로 더 신뢰받는다.

브라우저가 AI 플랫폼이 되는 변화의 핵심은 결국 에이전트다. 에이전트가 사람 대신 웹을 탐색하고, 정보를 수집하고, 작업을 처리하는 시대가 열렸다. 그 구조를 이해하고 직접 설계할 수 있는 개발자와 그렇지 않은 개발자 사이의 거리가 이제부터 빠르게 벌어진다.

Leave a Comment