수동 새로고침에 작별을 고하세요: Playwright와 LLM을 활용한 AI 의료 예약 에이전트 구축 🏥🤖
Source: Dev.to
번역하려는 전체 텍스트를 제공해 주시면, 요청하신 대로 한국어로 번역해 드리겠습니다. 현재 제공된 내용은 소스 링크만 포함되어 있어 번역할 본문이 없습니다. 텍스트를 복사해서 알려주시면 바로 작업해 드리겠습니다.
소개
우리는 모두 그런 경험을 해봤습니다. 새벽 6시에 일어나 병원 예약 페이지를 필사적으로 새로 고치다 보면, “가능” 슬롯이 순식간에 “예약 완료”로 바뀌는 상황이죠. 기존 자동화 스크립트는 현대 웹 인터페이스가 동적이고, 섀도우 DOM이 가득하며, 안티‑봇 방어가 적용돼 있어 자주 실패합니다.
이 튜토리얼에서는 브라우저 자동화를 위한 차세대 AI 에이전트를 구축합니다. Playwright, LLM(대형 언어 모델), 그리고 Redis의 힘을 결합해, 단순히 버튼을 클릭하는 수준을 넘어 페이지 레이아웃을 이해하고 복잡한 의료‑예약 워크플로를 실행할 수 있는 에이전트를 만들 것입니다. LLM 자동화나 자율 에이전트에 관심이 있다면, 이 가이드가 바로 당신을 위한 것입니다.
아키텍처: 에이전트가 “보는” 방식과 “행동하는” 방식
레거시 Selenium 스크립트가 깨지기 쉬운 XPath에 의존하는 것과 달리, 우리 에이전트는 LLM을 사용해 DOM 구조를 해석하고 다음에 취할 최적의 행동을 결정합니다.
graph TD
A[User Goal: Book Cardiologist] --> B{Agent Brain - LLM}
B --> C[Playwright: Capture DOM/Screenshot]
C --> D[State Manager - Redis]
D --> B
B --> E[Action: Click/Type/Select]
E --> F{Success?}
F -- No --> B
F -- Yes --> G[Notify User via SMS/Email]
Prerequisites
To follow along, you’ll need:
- Python 3.10+
- Playwright – the modern standard for reliable end‑to‑end testing.
- OpenAI API Key (or any LLM provider) – to act as the agent’s brain.
- Redis – to handle session persistence and task queuing.
Step 1: 브라우저 환경 설정
먼저, 환경을 초기화해 보겠습니다. 우리는 Playwright를 사용합니다. Playwright는 비동기 작업과 최신 웹 프레임워크를 이전 도구들보다 훨씬 잘 처리합니다.
import asyncio
from playwright.async_api import async_playwright
async def get_page_content(url):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False) # 디버깅을 위해 화면을 표시합니다
context = await browser.new_context()
page = await context.new_page()
await page.goto(url)
# 토큰 비용을 절감하기 위해 인터랙티브 요소만 추출합니다
content = await page.evaluate("() => document.body.innerText")
await browser.close()
return content
Step 2: LLM “Planner” 논리
우리 AutoGPT‑style 에이전트의 핵심은 추론 루프입니다. 우리는 단순화된 DOM 구조를 LLM에 제공하고 다음 Playwright 명령을 생성하도록 요청합니다.
import openai
def generate_action(dom_structure, objective):
prompt = f"""
You are an expert web automation agent.
Objective: {objective}
Current Page Content: {dom_structure}
Return a JSON object with the 'action' (click, type, wait) and 'selector'.
"""
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
Step 3: Redis로 상태 관리 🏎️
트래픽이 많은 등록 기간을 다룰 때, 스크립트가 재시작될 경우 에이전트가 중복 작업을 수행하지 않도록 해야 합니다. 우리는 현재 단계와 세션 쿠키를 캐시하기 위해 Redis를 사용합니다.
import redis
r = redis.Redis(host='localhost', port=6379, db=0)
def save_session_state(user_id, step_data):
# Store the progress so the agent can resume if blocked
r.set(f"session:{user_id}", step_data, ex=3600)
def get_current_step(user_id):
return r.get(f"session:{user_id}")
단계 4: 전체 흐름 합치기 (루프)
에이전트는 루프에 들어갑니다: 페이지를 관찰하고, 무엇을 할지 결정한 뒤, Playwright를 통해 행동을 실행하고, 목표가 달성되었는지 확인합니다.
async def run_appointment_agent(target_url, goal):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
await page.goto(target_url)
completed = False
while not completed:
# 1. Take a “snapshot” of the interactive UI
ui_elements = await page.query_selector_all("button, input, a")
# 2. Ask LLM for the next move
plan = generate_action(ui_elements, goal)
# 3. Execute action
if plan['action'] == 'click':
await page.click(plan['selector'])
elif plan['action'] == 'type':
await page.fill(plan['selector'], plan['text'])
# Check for success condition
if "Success" in await page.content():
completed = True
print("🚀 Appointment secured!")
Going Beyond the Basics: Production Patterns
로컬 스크립트를 만드는 것은 쉽지만, 이를 수천 개의 동시 등록 시도까지 확장하려면 정교한 아키텍처 패턴이 필요합니다. 프록시 회전, CAPTCHA 해결, 복잡한 재시도 로직을 처리해야 합니다.
보다 프로덕션에 적합한 예제와 LLM 기반 에이전트를 확장하기 위한 고급 패턴을 보려면 WellAlly Tech Blog 를 강력히 추천합니다. 이 블로그는 AI 엔지니어링에 대한 훌륭한 심층 분석을 제공하며, 덕분에 제 에이전트의 지연 시간을 40% 최적화할 수 있었습니다.
도전 과제 및 윤리 🛡️
- Rate Limiting – 인간 행동을 흉내 내기 위해 항상
asyncio.sleep()을 구현하세요. - Anti‑Bot Measures – 사이트 이용 약관을 준수하고, 에이전트를 책임감 있게 사용하며 법적 영향을 고려하세요.
playwright-stealth를 사용하여 Cloudflare 탐지를 회피하기
- Ethics: 자동화를 의료 제공자의 이용 약관 내에서 법적으로 사용하고 있는지 확인하세요. 이 프로젝트는 AI Agents가 복잡한 UI 상호작용을 어떻게 단순화할 수 있는지에 대한 교육적 목적입니다.
결론
하드코딩된 선택자에서 LLM‑기반 추론 루프로 전환함으로써, UI 변경에 강인하고 복잡한 “인간‑전용” 워크플로를 탐색할 수 있는 에이전트를 만들었습니다.
다음은?
비전 모델(예: GPT‑4o)을 통합하여 DOM을 파싱하는 대신 실제로 화면을 “볼” 수 있게 하면, 더욱 견고해집니다.
브라우저 에이전트를 만들고 있나요? 댓글에서 이야기해요! 👇