• Web Agent๋Š” LLM์ด ์›น ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ž์œจ์ ์œผ๋กœ ์ œ์–ดํ•˜์—ฌ ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๋Š” AI ์—์ด์ „ํŠธ ์‹œ์Šคํ…œ
  • ์‚ฌ์šฉ์ž์˜ ์ž์—ฐ์–ด ์ง€์‹œ๋ฅผ ๋ฐ›์•„ ๊ด€์ฐฐ-์ถ”๋ก -ํ–‰๋™(Observe-Think-Act) ๋ฃจํ”„๋กœ ์›น ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ธŒ๋ผ์šฐ์ € ์ž๋™ํ™” ํŒจ๋Ÿฌ๋‹ค์ž„
  • ๊ธฐ์กด ์Šคํฌ๋ฆฝํŠธ ์ž๋™ํ™”(Selenium, Puppeteer)์™€ ๋‹ฌ๋ฆฌ ์›น์‚ฌ์ดํŠธ ๊ตฌ์กฐ ๋ณ€๊ฒฝ์— ์ ์‘ํ•  ์ˆ˜ ์žˆ๋Š” ์˜๋ฏธ ๊ธฐ๋ฐ˜(semantic) ์ ‘๊ทผ ๋ฐฉ์‹

ํ•ด๋‹น ๊ฐœ๋…์ด ํ•„์š”ํ•œ ์ด์œ 

  • ๊ธฐ์กด ๋ธŒ๋ผ์šฐ์ € ์ž๋™ํ™”๋Š” XPath/CSS ์…€๋ ‰ํ„ฐ์— ์˜์กดํ•˜์—ฌ ์›น์‚ฌ์ดํŠธ ๊ตฌ์กฐ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์ฆ‰์‹œ ๊นจ์ง
  • API๊ฐ€ ์—†๋Š” ์›น ์„œ๋น„์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ฑฐ๋‚˜ ์ž‘์—…์„ ์ž๋™ํ™”ํ•ด์•ผ ํ•˜๋Š” ์ˆ˜์š” ์ฆ๊ฐ€
  • LLM์˜ ์ถ”๋ก  ๋Šฅ๋ ฅ์ด ์›น ํŽ˜์ด์ง€์˜ ๋งฅ๋ฝ์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜์ค€์— ๋„๋‹ฌ (GPT-4o, Claude, Gemini ๋“ฑ)
  • ์‚ฌ์šฉ์ž์˜ ์ธ์ฆ๋œ ์„ธ์…˜(์ฟ ํ‚ค, ๋กœ๊ทธ์ธ)์„ ํ™œ์šฉํ•˜์—ฌ ๊ฐœ์ธํ™”๋œ ์›น ์ž‘์—… ๊ฐ€๋Šฅ

AS-IS: ๊ธฐ์กด ์Šคํฌ๋ฆฝํŠธ ์ž๋™ํ™”

# Selenium โ€” ์…€๋ ‰ํ„ฐ ๊ธฐ๋ฐ˜, ๊ตฌ์กฐ ๋ณ€๊ฒฝ ์‹œ ์‹คํŒจ
driver.find_element(By.XPATH, '//*[@id="search-box"]').send_keys("query")
driver.find_element(By.CSS_SELECTOR, '.btn-submit').click()
# ์›น์‚ฌ์ดํŠธ ๋ฆฌ๋””์ž์ธ โ†’ XPATH ๋ณ€๊ฒฝ โ†’ ์Šคํฌ๋ฆฝํŠธ ์ „์ฒด ์ˆ˜์ • ํ•„์š”

TO-BE: Web Agent (LLM ๊ธฐ๋ฐ˜)

sequenceDiagram
    autonumber
    participant User as ์‚ฌ์šฉ์ž
    participant LLM as LLM (์ถ”๋ก  ์—”์ง„)
    participant Browser as ๋ธŒ๋ผ์šฐ์ €

    User->>LLM: "Google์—์„œ 'AI agent' ๊ฒ€์ƒ‰ํ•ด์ค˜"
    loop Observe-Think-Act
        LLM->>Browser: ํŽ˜์ด์ง€ ์ƒํƒœ ์š”์ฒญ (Accessibility Tree)
        Browser-->>LLM: ํŽ˜์ด์ง€ ๊ตฌ์กฐ + ์š”์†Œ ์ฐธ์กฐ ID
        Note over LLM: ์ถ”๋ก : ๊ฒ€์ƒ‰์ฐฝ์€ ref=e5, ์—ญํ• =textbox
        LLM->>Browser: type_text(ref=e5, "AI agent")
        Browser-->>LLM: ์ž…๋ ฅ ์™„๋ฃŒ, DOM ๋ณ€ํ™” ๊ฐ์ง€
        LLM->>Browser: press_key("Enter")
        Browser-->>LLM: ํŽ˜์ด์ง€ ๋„ค๋น„๊ฒŒ์ด์…˜ ์™„๋ฃŒ
    end
    LLM-->>User: "๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋ฅผ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค: ..."

Web Agent์˜ 3๊ฐ€์ง€ ์ธ์‹ ๋ฐฉ์‹

1. DOM ๊ธฐ๋ฐ˜ ์ธ์‹

HTML Document Object Model์„ ํŒŒ์‹ฑํ•˜์—ฌ ํŽ˜์ด์ง€ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐฉ์‹. ์š”์†Œ์˜ ํƒœ๊ทธ, ์†์„ฑ, ํ…์ŠคํŠธ ์ฝ˜ํ…์ธ ๋ฅผ ์ง์ ‘ ๋ถ„์„ํ•œ๋‹ค.

  • ์žฅ์ : ์ •ํ™•ํ•œ ์š”์†Œ ์‹๋ณ„, ๋น ๋ฅธ ์ฒ˜๋ฆฌ
  • ๋‹จ์ : ์‹œ๊ฐ์  ๋ ˆ์ด์•„์›ƒ ์ •๋ณด ๋ถ€์กฑ, JavaScript ๋ Œ๋”๋ง ํ›„ DOM๊ณผ ์‹ค์ œ ํ™”๋ฉด ๊ดด๋ฆฌ

2. Accessibility Tree ๊ธฐ๋ฐ˜ ์ธ์‹

๋ธŒ๋ผ์šฐ์ €์˜ ์ ‘๊ทผ์„ฑ ํŠธ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์š”์†Œ์˜ ์—ญํ• (role), ์ด๋ฆ„(name), ์ƒํƒœ(state) ๋ฅผ ํŒŒ์•…. ์Šคํฌ๋ฆฐ ๋ฆฌ๋”๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ๊ตฌ์กฐ๋ฅผ ์—์ด์ „ํŠธ๊ฐ€ ํ™œ์šฉํ•œ๋‹ค.

  • ์žฅ์ : ์˜๋ฏธ๋ก ์ (semantic) ์ดํ•ด ๊ฐ€๋Šฅ, CSS/๋ ˆ์ด์•„์›ƒ ๋ณ€๊ฒฝ์— ๊ฐ•๊ฑด
  • ๋‹จ์ : ์ ‘๊ทผ์„ฑ ๋งˆํฌ์—…์ด ๋นˆ์•ฝํ•œ ์‚ฌ์ดํŠธ์—์„œ๋Š” ์ •๋ณด ๋ถ€์กฑ
  • ํ•ต์‹ฌ ์ธ์‚ฌ์ดํŠธ: โ€œ์Šคํฌ๋ฆฐ ๋ฆฌ๋”๊ฐ€ ์‚ฌ์ดํŠธ๋ฅผ ๋ชป ์ฝ์œผ๋ฉด, AI ์—์ด์ „ํŠธ๋„ ๋ชป ์ฝ๋Š”๋‹คโ€

3. Vision(์Šคํฌ๋ฆฐ์ƒท) ๊ธฐ๋ฐ˜ ์ธ์‹

ํŽ˜์ด์ง€ ์Šคํฌ๋ฆฐ์ƒท์„ Computer Vision/๋ฉ€ํ‹ฐ๋ชจ๋‹ฌ LLM์— ์ž…๋ ฅํ•˜์—ฌ ์‹œ๊ฐ์ ์œผ๋กœ ์š”์†Œ๋ฅผ ์ธ์‹ํ•˜๋Š” ๋ฐฉ์‹.

  • ์žฅ์ : DOM ๊ตฌ์กฐ์— ์˜์กดํ•˜์ง€ ์•Š์Œ, ๋ณต์žกํ•œ ์‹œ๊ฐ์  ๋ ˆ์ด์•„์›ƒ ์ดํ•ด ๊ฐ€๋Šฅ
  • ๋‹จ์ : ์ฒ˜๋ฆฌ ์†๋„ ๋А๋ฆผ, ๋น„์šฉ ๋†’์Œ, ์ •๋ฐ€ํ•œ ์š”์†Œ ์ง€์ • ์–ด๋ ค์›€

์‹ค๋ฌด์—์„œ๋Š” Accessibility Tree + Vision ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๋ฐฉ์‹์ด ๊ฐ€์žฅ ๋ณดํŽธ์ ์ด๋‹ค.

Observe-Think-Act ๋ฃจํ”„

Web Agent์˜ ์‹คํ–‰ ํ•ต์‹ฌ ํŒจํ„ด. ๋ชจ๋“  ์›น ์ž‘์—…์€ ์ด ๋ฃจํ”„์˜ ๋ฐ˜๋ณต์œผ๋กœ ์ˆ˜ํ–‰๋œ๋‹ค.

sequenceDiagram
    autonumber
    participant Agent as Agent (LLM)
    participant Env as Browser Environment

    loop ๋ชฉํ‘œ ๋‹ฌ์„ฑ๊นŒ์ง€ ๋ฐ˜๋ณต
        Agent->>Env: Observe โ€” ํ˜„์žฌ ํŽ˜์ด์ง€ ์ƒํƒœ ์ˆ˜์ง‘
        Note over Env: DOM / Accessibility Tree / Screenshot
        Env-->>Agent: ํŽ˜์ด์ง€ ๊ตฌ์กฐ + ์š”์†Œ ์ฐธ์กฐ ๋ฐ˜ํ™˜
        Note over Agent: Think โ€” ๋ชฉํ‘œ ๋Œ€๋น„ ํ˜„์žฌ ์ƒํƒœ ๋ถ„์„, ๋‹ค์Œ ํ–‰๋™ ๊ฒฐ์ •
        Agent->>Env: Act โ€” ํ–‰๋™ ์‹คํ–‰ (click, type, scroll, navigate...)
        Env-->>Agent: ํ–‰๋™ ๊ฒฐ๊ณผ + ํŽ˜์ด์ง€ ๋ณ€ํ™” ํ”ผ๋“œ๋ฐฑ
    end
๋‹จ๊ณ„์„ค๋ช…์˜ˆ์‹œ
Observeํ˜„์žฌ ํŽ˜์ด์ง€ ์ƒํƒœ๋ฅผ ์ˆ˜์ง‘Accessibility Tree ์ถ”์ถœ, ์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜
ThinkLLM์ด ๋ชฉํ‘œ ๋Œ€๋น„ ์ƒํƒœ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ๋‹ค์Œ ํ–‰๋™์„ ๊ณ„ํšโ€๊ฒ€์ƒ‰์ฐฝ์„ ์ฐพ์•˜์œผ๋‹ˆ ํ…์ŠคํŠธ๋ฅผ ์ž…๋ ฅํ•ด์•ผ ํ•œ๋‹คโ€
Act๋ธŒ๋ผ์šฐ์ €์— ๊ตฌ์ฒด์  ํ–‰๋™์„ ์‹คํ–‰click(ref=e14), type_text(ref=e5, "query")

Action Space (ํ–‰๋™ ๊ณต๊ฐ„)

Web Agent๊ฐ€ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์›์ž์  ํ–‰๋™(primitive) ๋ชฉ๋ก:

Action์„ค๋ช…
navigate(url)ํŠน์ • URL๋กœ ์ด๋™
click(element)์š”์†Œ ํด๋ฆญ (๋ฒ„ํŠผ, ๋งํฌ, ์ฒดํฌ๋ฐ•์Šค ๋“ฑ)
type_text(element, value)์ž…๋ ฅ ํ•„๋“œ์— ํ…์ŠคํŠธ ์ž…๋ ฅ
scroll(direction)ํŽ˜์ด์ง€ ๋˜๋Š” ์š”์†Œ ์Šคํฌ๋กค
press_key(key)ํ‚ค๋ณด๋“œ ํ‚ค ์ž…๋ ฅ (Enter, Escape, Tab ๋“ฑ)
extract_page()ํŽ˜์ด์ง€ ์ฝ˜ํ…์ธ  ์ถ”์ถœ
screenshot()ํ˜„์žฌ ํ™”๋ฉด ์บก์ฒ˜
done()์ž‘์—… ์™„๋ฃŒ ์„ ์–ธ ๋ฐ ์„ธ์…˜ ์ •๋ฆฌ

Playwright โ€” Web Agent์˜ ๊ธฐ๋ฐ˜ ๊ธฐ์ˆ 

Playwright๋Š” Microsoft๊ฐ€ ๊ฐœ๋ฐœํ•œ ์˜คํ”ˆ์†Œ์Šค ๋ธŒ๋ผ์šฐ์ € ์ž๋™ํ™” ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, ์›๋ž˜๋Š” E2E ํ…Œ์ŠคํŠธ ๋„๊ตฌ๋กœ ์„ค๊ณ„๋˜์—ˆ์œผ๋‚˜ ํ˜„์žฌ Web Agent์˜ ํ•ต์‹ฌ ์ธํ”„๋ผ๋กœ ์ง„ํ™”ํ•˜๊ณ  ์žˆ๋‹ค.

Playwright ํ•ต์‹ฌ ๊ตฌ์กฐ

sequenceDiagram
    autonumber
    participant Code as Playwright API
    participant BT as BrowserType
    participant B as Browser (Chromium/Firefox/WebKit)
    participant BC as BrowserContext (๊ฒฉ๋ฆฌ๋œ ์„ธ์…˜)
    participant P as Page (ํƒญ)

    Code->>BT: chromium.launch()
    BT->>B: ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœ์„ธ์Šค ์ƒ์„ฑ
    B->>BC: browser.newContext()
    Note over BC: ๋…๋ฆฝ๋œ ์ฟ ํ‚ค, ์Šคํ† ๋ฆฌ์ง€, ์„ธ์…˜
    BC->>P: context.newPage()
    P->>P: page.goto(), page.click(), page.fill()...
๊ณ„์ธต์—ญํ• 
BrowserTypeChromium, Firefox, WebKit ์ค‘ ๋ธŒ๋ผ์šฐ์ € ์—”์ง„ ์„ ํƒ ๋ฐ ์‹คํ–‰
Browser์‹คํ–‰ ์ค‘์ธ ๋ธŒ๋ผ์šฐ์ € ์ธ์Šคํ„ด์Šค
BrowserContext๊ฒฉ๋ฆฌ๋œ ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœํ•„ (์ฟ ํ‚ค, ์„ธ์…˜ ๋…๋ฆฝ). ํ•˜๋‚˜์˜ Browser์—์„œ ์—ฌ๋Ÿฌ Context ์ƒ์„ฑ ๊ฐ€๋Šฅ
Pageํ•˜๋‚˜์˜ ํƒญ. DOM ์กฐ์ž‘, ๋„ค๋น„๊ฒŒ์ด์…˜, ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ์˜ ์‹ค์ œ ๋‹จ์œ„

Playwright์˜ ๊ฐ•์ 

  • Auto-waiting: ์š”์†Œ๊ฐ€ ์กฐ์ž‘ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ์ž๋™ ๋Œ€๊ธฐ (์ธ์œ„์  sleep ๋ถˆํ•„์š”)
  • Trusted Events: ์‹ค์ œ ์‚ฌ์šฉ์ž ์ž…๋ ฅ๊ณผ ๊ตฌ๋ถ„ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋ธŒ๋ผ์šฐ์ € ๋„ค์ดํ‹ฐ๋ธŒ ์ด๋ฒคํŠธ ์ƒ์„ฑ
  • Cross-browser: Chromium, Firefox, WebKit์„ ๋‹จ์ผ API๋กœ ์ œ์–ด
  • ๊ฒฉ๋ฆฌ(Isolation): BrowserContext ๋‹จ์œ„๋กœ ์„ธ์…˜ ์™„์ „ ๊ฒฉ๋ฆฌ, ๋ฐ€๋ฆฌ์ดˆ ๋‹จ์œ„ ์ƒ์„ฑ
  • Shadow DOM ๊ด€ํ†ต: Shadow DOM, iframe์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ†ต๊ณผํ•˜๋Š” ์…€๋ ‰ํ„ฐ

Playwright โ†’ Web Agent๋กœ์˜ ์ง„ํ™”: Playwright MCP

Playwright ์ž์ฒด๋Š” ์ฝ”๋“œ๋กœ ์ž‘์„ฑ๋œ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋„๊ตฌ์ด๋‹ค. ์—ฌ๊ธฐ์— MCP(Model Context Protocol)๋ฅผ ๊ฒฐํ•ฉํ•˜๋ฉด, LLM์ด Playwright์˜ ๋ธŒ๋ผ์šฐ์ € ์ œ์–ด ๋Šฅ๋ ฅ์„ ๋„๊ตฌ(tool)๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

sequenceDiagram
    autonumber
    participant LLM as LLM Agent
    participant MCP as MCP Server (Playwright)
    participant PW as Playwright Engine
    participant Browser as Browser

    LLM->>MCP: tool_call: navigate("https://example.com")
    MCP->>PW: page.goto("https://example.com")
    PW->>CDP: CDP ๋ช…๋ น ์ „์†ก
    CDP->>Browser: ๋ธŒ๋ผ์šฐ์ € ๋‚ด๋ถ€ ์‹คํ–‰
    Browser-->>CDP: ํŽ˜์ด์ง€ ๋กœ๋“œ ์™„๋ฃŒ
    CDP-->>PW: ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
    PW-->>MCP: Accessibility Snapshot ๋ฐ˜ํ™˜
    MCP-->>LLM: ํŽ˜์ด์ง€ ๊ตฌ์กฐ (์—ญํ• , ์ด๋ฆ„, ์ฐธ์กฐ ID)
    Note over LLM: ์ถ”๋ก  ํ›„ ๋‹ค์Œ ํ–‰๋™ ๊ฒฐ์ •
๋น„๊ตPlaywright ๋‹จ๋…Playwright MCP (Web Agent)
์ง€์‹œ ๋ฐฉ์‹์ฝ”๋“œ (page.click('#btn'))์ž์—ฐ์–ด (โ€œ๊ฒ€์ƒ‰ ๋ฒ„ํŠผ ํด๋ฆญํ•ด์ค˜โ€)
์ ์‘๋ ฅ์…€๋ ‰ํ„ฐ ๋ณ€๊ฒฝ ์‹œ ์ฝ”๋“œ ์ˆ˜์ • ํ•„์š”LLM์ด ์˜๋ฏธ๋กœ ์š”์†Œ๋ฅผ ์ฐพ์•„ ์ ์‘
์ธ์‹ ๋ฐฉ์‹๊ฐœ๋ฐœ์ž๊ฐ€ ์…€๋ ‰ํ„ฐ ์ง€์ •Accessibility Snapshot ์ž๋™ ๋ถ„์„
์‚ฌ์šฉ ์ฃผ์ฒด๊ฐœ๋ฐœ์ž/QA ์—”์ง€๋‹ˆ์–ดAI ์—์ด์ „ํŠธ (๋น„๊ฐœ๋ฐœ์ž๋„ ํ™œ์šฉ ๊ฐ€๋Šฅ)

Playwright MCP๋Š” ์Šคํฌ๋ฆฐ์ƒท ๋Œ€์‹  Accessibility Snapshot์„ ์‚ฌ์šฉํ•˜์—ฌ ๋น„์ „ ๋ชจ๋ธ ์—†์ด๋„ ๋น ๋ฅด๊ณ  ์ •ํ™•ํ•œ ํŽ˜์ด์ง€ ์ธ์‹์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

ํ†ต์‹  ์•„ํ‚คํ…์ฒ˜

Web Agent๊ฐ€ ์‹ค์ œ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•œ ํ†ต์‹  ๋ฐฉ์‹์€ ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€๋กœ ๋‚˜๋‰œ๋‹ค.

๋ฐฉ์‹ 1: Chrome Extension + Native Messaging

๋ฐ์Šคํฌํ†ฑ ์•ฑ์ด ์‚ฌ์šฉ์ž์˜ ๊ธฐ์กด Chrome ์„ธ์…˜(๋กœ๊ทธ์ธ, ์ฟ ํ‚ค)์„ ๊ทธ๋Œ€๋กœ ํ™œ์šฉํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

sequenceDiagram
    autonumber
    participant App as Host Application
    participant NMH as Native Messaging Host
    participant Ext as Chrome Extension
    participant CS as Content Script
    participant Tab as Web Page

    App->>NMH: IPC/Socket ๋ช…๋ น ์ „์†ก
    NMH->>Ext: stdin โ†’ JSON ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ
    Ext->>CS: Content Script ์ฃผ์ž…
    CS->>Tab: DOM ์กฐ์ž‘ (ํด๋ฆญ, ์ž…๋ ฅ, ์ถ”์ถœ)
    Tab-->>CS: ์‹คํ–‰ ๊ฒฐ๊ณผ
    CS-->>Ext: ๊ฒฐ๊ณผ JSON
    Ext-->>NMH: stdout โ† JSON ์‘๋‹ต
    NMH-->>App: ์‘๋‹ต ์ „๋‹ฌ

Native Messaging์ด๋ž€?

Chrome์ด ์ œ๊ณตํ•˜๋Š” API๋กœ, ๋ธŒ๋ผ์šฐ์ € ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์ด ์‚ฌ์šฉ์ž ์ปดํ“จํ„ฐ์— ์„ค์น˜๋œ ๋กœ์ปฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค.

์™œ ํ•„์š”ํ•œ๊ฐ€?

  • Chrome Extension์€ ๋ณด์•ˆ ์ƒŒ๋“œ๋ฐ•์Šค ์•ˆ์—์„œ ๋™์ž‘ํ•˜์—ฌ ๋กœ์ปฌ ํŒŒ์ผ, ํ”„๋กœ์„ธ์Šค์— ์ง์ ‘ ์ ‘๊ทผ ๋ถˆ๊ฐ€
  • Web Agent์˜ ํ˜ธ์ŠคํŠธ ์•ฑ(๋ฐฑ์—”๋“œ ์„œ๋ฒ„)์€ ๋กœ์ปฌ์—์„œ ์‹คํ–‰๋จ
  • ์ด ๋‘˜์„ ์—ฐ๊ฒฐํ•˜๋Š” ๊ณต์‹์ ์ด๊ณ  ์•ˆ์ „ํ•œ ๋ธŒ๋ฆฟ์ง€๊ฐ€ Native Messaging

๋™์ž‘ ์›๋ฆฌ:

  1. Host Manifest ๋“ฑ๋ก: ๋กœ์ปฌ ์•ฑ์ด JSON ๋งค๋‹ˆํŽ˜์ŠคํŠธ ํŒŒ์ผ์„ OS ์ง€์ • ๊ฒฝ๋กœ์— ๋“ฑ๋ก
    {
      "name": "com.example.webagent",
      "description": "Web Agent Native Host",
      "path": "/usr/local/bin/web-agent-host",
      "type": "stdio",
      "allowed_origins": ["chrome-extension://abcdef12345/"]
    }
  2. ์—ฐ๊ฒฐ ์ˆ˜๋ฆฝ: Extension์ด chrome.runtime.connectNative("com.example.webagent") ํ˜ธ์ถœ
  3. ๋ฉ”์‹œ์ง€ ๊ตํ™˜: stdin/stdout์„ ํ†ตํ•œ JSON ํ†ต์‹  (32-bit ๊ธธ์ด ํ”„๋ฆฌํ”ฝ์Šค + UTF-8 JSON)
  4. ๋ณด์•ˆ: allowed_origins์— ๋ช…์‹œ๋œ Extension ID๋งŒ ์—ฐ๊ฒฐ ํ—ˆ์šฉ (์™€์ผ๋“œ์นด๋“œ ๋ถˆ๊ฐ€)
์†์„ฑ๊ฐ’
์ธ๋ฐ”์šด๋“œ ๋ฉ”์‹œ์ง€ ์ตœ๋Œ€ ํฌ๊ธฐ1 MB
์•„์›ƒ๋ฐ”์šด๋“œ ๋ฉ”์‹œ์ง€ ์ตœ๋Œ€ ํฌ๊ธฐ64 MB
์—ฐ๊ฒฐ ๋ฐฉ์‹์˜๊ตฌ ์—ฐ๊ฒฐ(connectNative) ๋˜๋Š” ๋‹จ๋ฐœ์„ฑ(sendNativeMessage)
Content Script์—์„œ ์ง์ ‘ ์‚ฌ์šฉ๋ถˆ๊ฐ€ โ€” Service Worker๋ฅผ ํ†ตํ•ด ์ค‘๊ณ„ ํ•„์š”

Host Manifest ๋“ฑ๋ก ๊ฒฝ๋กœ:

OS๊ฒฝ๋กœ
macOS~/Library/Application Support/Google/Chrome/NativeMessagingHosts/
Linux~/.config/google-chrome/NativeMessagingHosts/
Windows๋ ˆ์ง€์ŠคํŠธ๋ฆฌ HKCU\Software\Google\Chrome\NativeMessagingHosts\

๋ฐฉ์‹ 2: Playwright (CDP ์ง์ ‘ ์ œ์–ด)

Playwright MCP ๋“ฑ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹. ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœ์„ธ์Šค๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•˜๊ณ  ์ œ์–ดํ•œ๋‹ค.

sequenceDiagram
    autonumber
    participant Agent as Agent / MCP Server
    participant PW as Playwright Engine
    participant CDP as Chrome DevTools Protocol
    participant Browser as Browser Process

    Agent->>PW: API ํ˜ธ์ถœ (navigate, click, extract...)
    PW->>CDP: WebSocket CDP ๋ช…๋ น
    CDP->>Browser: ๋ธŒ๋ผ์šฐ์ € ๋‚ด๋ถ€ ์‹คํ–‰
    Browser-->>CDP: ์‹คํ–‰ ๊ฒฐ๊ณผ
    CDP-->>PW: ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
    PW-->>Agent: ๊ตฌ์กฐํ™”๋œ ์‘๋‹ต

๋‘ ๋ฐฉ์‹ ๋น„๊ต

๋น„๊ต ํ•ญ๋ชฉExtension + Native MessagingPlaywright (CDP)
์‚ฌ์šฉ์ž ์„ธ์…˜๊ธฐ์กด ๋กœ๊ทธ์ธ/์ฟ ํ‚ค ํ™œ์šฉ ๊ฐ€๋Šฅ์ƒˆ ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœํ•„ (๊ธฐ๋ณธ๊ฐ’)
โ€œDebuggerโ€ ๊ฒฝ๊ณ ์—†์Œโ€Chrome is being controlled by automated test softwareโ€ ํ‘œ์‹œ
์„ค์น˜ ๋ณต์žก๋„Extension + Native Host ์„ค์น˜ ํ•„์š”npm install playwright
๋ธŒ๋ผ์šฐ์ € ํ˜ธํ™˜Chrome ์ „์šฉChromium, Firefox, WebKit
์ ํ•ฉํ•œ ์‚ฌ์šฉ์ฒ˜์ธ์ฆ๋œ ์ธํŠธ๋ผ๋„ท, ๊ฐœ์ธํ™”๋œ ์›น ์ž‘์—…๊ณต๊ฐœ ์›น์‚ฌ์ดํŠธ, ํ…Œ์ŠคํŠธ, ์Šคํฌ๋ž˜ํ•‘

์•ˆ์ „์žฅ์น˜ (Guard Mechanisms)

Web Agent๋Š” ์ž์œจ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋ฏ€๋กœ ๋ฐ˜๋“œ์‹œ ์•ˆ์ „์žฅ์น˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค:

์œ„ํ—˜์•ˆ์ „์žฅ์น˜์„ค๋ช…
๋ฌดํ•œ ๋ฃจํ”„๋ฐ˜๋ณต ํ–‰๋™ ๊ฐ์ง€๋™์ผ ํ–‰๋™ NํšŒ ๋ฐ˜๋ณต ์‹œ ์ž๋™ ์ฐจ๋‹จ
์ •์ฒด(Stale) ์ƒํƒœํŽ˜์ด์ง€ ๋ณ€ํ™” ๋ชจ๋‹ˆํ„ฐ๋ง์—ฌ๋Ÿฌ ํ–‰๋™ ํ›„ ํŽ˜์ด์ง€ ๋ณ€ํ™” ์—†์œผ๋ฉด ๊ฒฝ๊ณ 
Prompt Injection์ž…๋ ฅ ๊ฒ€์ฆ์›น ํŽ˜์ด์ง€ ์ฝ˜ํ…์ธ ๊ฐ€ ์—์ด์ „ํŠธ ์ง€์‹œ๋ฅผ ์˜ค์—ผ์‹œํ‚ค๋Š” ๊ณต๊ฒฉ ๋ฐฉ์–ด
์„ธ์…˜ ํญ์ฃผTTL ๋ฐ ์ตœ๋Œ€ ์„ธ์…˜ ์ˆ˜์œ ํœด ์„ธ์…˜ ์ž๋™ ์ •๋ฆฌ, ๋ฆฌ์†Œ์Šค ๋ณดํ˜ธ
๋ฏผ๊ฐ ์ž‘์—…์‚ฌ์šฉ์ž ํ™•์ธ๊ฒฐ์ œ, ์‚ญ์ œ ๋“ฑ ๋˜๋Œ๋ฆฌ๊ธฐ ์–ด๋ ค์šด ์ž‘์—… ์ „ ํ™•์ธ ์š”์ฒญ

์ฃผ์š” ๋„์ „ ๊ณผ์ œ

  • ์‹ ๋ขฐ์„ฑ: LLM์˜ ์ถ”๋ก  ์˜ค๋ฅ˜(hallucination)๋กœ ์ž˜๋ชป๋œ ์š”์†Œ๋ฅผ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ์—‰๋šฑํ•œ ์ž‘์—… ์ˆ˜ํ–‰ ๊ฐ€๋Šฅ. WebVoyager ๋ฒค์น˜๋งˆํฌ ๊ธฐ์ค€ ์ตœ๊ณ  ์„ฑ๊ณต๋ฅ ์€ ์•ฝ 89%
  • ๋ณด์•ˆ: ์›น ํŽ˜์ด์ง€์— ์ˆจ๊ฒจ์ง„ ์•…์˜์  ์ง€์‹œ(Prompt Injection)๊ฐ€ ์—์ด์ „ํŠธ๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์Œ. Anthropic ์—ฐ๊ตฌ์—์„œ ๊ณต๊ฒฉ ์„ฑ๊ณต๋ฅ ์„ 23.6% โ†’ 11.2%๋กœ ๋‚ฎ์ท„์œผ๋‚˜ ์™„์ „ ํ•ด๊ฒฐ์€ ๋ฏธ์™„
  • ๋น„์šฉ ๋ฐ ์ง€์—ฐ: ๋งค ํ–‰๋™๋งˆ๋‹ค LLM API ํ˜ธ์ถœ โ†’ ๋น„์šฉ๊ณผ ์‘๋‹ต ์‹œ๊ฐ„์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„
  • ๋™์  ์ฝ˜ํ…์ธ : SPA, ๋ฌดํ•œ ์Šคํฌ๋กค, CAPTCHA, ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง ๋“ฑ์€ ์—ฌ์ „ํžˆ ๋‚œ์ œ
  • ๋ฒ•์  ์ด์Šˆ: ์—์ด์ „ํŠธ์˜ ์ž๋™ํ™”๋œ ์›น ์ ‘๊ทผ์ด ์„œ๋น„์Šค ์•ฝ๊ด€(ToS)์„ ์œ„๋ฐ˜ํ•  ์ˆ˜ ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ๋ฒ•์  ๋…ผ์Ÿ ์ง„ํ–‰ ์ค‘ (Amazon vs. Perplexity ์†Œ์†ก, 2025)

์ฃผ์š” ํ”„๋ ˆ์ž„์›Œํฌ ๋ฐ ๋„๊ตฌ (2025-2026)

ํ”„๋ ˆ์ž„์›Œํฌ์œ ํ˜•ํŠน์ง•
browser-use์˜คํ”ˆ์†Œ์ŠคPython/TS SDK, WebVoyager 89.1% ๋‹ฌ์„ฑ
Playwright MCP์˜คํ”ˆ์†Œ์ŠคAccessibility Snapshot ๊ธฐ๋ฐ˜, MCP ํ‘œ์ค€
Stagehand์˜คํ”ˆ์†Œ์Šค์ž์—ฐ์–ด ๋ช…๋ น, ์ž๊ฐ€ ๋ณต๊ตฌ(self-healing)
Skyvern์ƒ์šฉCV + LLM ํ•˜์ด๋ธŒ๋ฆฌ๋“œ, ์ฝ”๋“œ ๋ถˆํ•„์š”
Perplexity Comet์†Œ๋น„์ž์šฉChromium ๊ธฐ๋ฐ˜ AI ๋ธŒ๋ผ์šฐ์ €
ChatGPT Atlas์†Œ๋น„์ž์šฉํƒญ๋ณ„ ์—์ด์ „ํŠธ ๋ชจ๋“œ

๋ฏธ๋ž˜ ๋ฐฉํ–ฅ: WebMCP

2026๋…„ 2์›” Google์ด Chrome Canary์— WebMCP ํ”„๋ฆฌ๋ทฐ๋ฅผ ํƒ‘์žฌ. ์›น์‚ฌ์ดํŠธ๊ฐ€ AI ์—์ด์ „ํŠธ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์›ํ•˜๋Š” ํ‘œ์ค€์„ ์ œ์•ˆ:

  • Declarative API: HTML ํผ์˜ ๊ตฌ์กฐํ™”๋œ ์„ค๋ช… ์ œ๊ณต
  • Imperative API: ๋™์  ์ƒํ˜ธ์ž‘์šฉ์„ ์œ„ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ธํ„ฐํŽ˜์ด์Šค
  • W3C๋ฅผ ํ†ตํ•ด Google + Microsoft ๊ณต๋™ ํ‘œ์ค€ํ™” ์ถ”์ง„

์—์ด์ „ํŠธ๊ฐ€ ์›น์‚ฌ์ดํŠธ๋ฅผ โ€œ์Šคํฌ๋ž˜ํ•‘โ€ํ•˜๋Š” ์‹œ๋Œ€์—์„œ, ์›น์‚ฌ์ดํŠธ๊ฐ€ ์—์ด์ „ํŠธ๋ฅผ โ€œ์ดˆ๋Œ€โ€ํ•˜๋Š” ์‹œ๋Œ€๋กœ์˜ ์ „ํ™˜

์ฐธ๊ณ  ๋ฌธ์„œ