AI 서브루틴: 브라우저 내부에서 자동화 스크립트 실행
이 글은 기존 웹 자동화 에이전트의 경제성과 인증(Auth) 문제를 해결하기 위해, 브라우저 확장 프로그램이 웹페이지 내부에서 직접 네트워크 요청을 녹화하고 재생하는 'AI 서브루틴(AI Subroutines)' 아키텍처를 소개합니다. 복잡한 인증 토큰이나 세션을 외부에서 강제로 재구성할 필요 없이 브라우저의 고유 실행 환경을 그대로 활용하여 안정성을 높이는 것이 핵심입니다. 또한 수많은 노이즈 요청 중 실제 의미 있는 API 호출만 추출하기 위해 요청을 평가하고 필터링하는 정교한 점수 기반 랭킹 시스템을 제공합니다.
AI 서브루틴(AI Subroutines): 페이지 내부에서 실행되는 브라우저 자동화
대부분의 웹 에이전트는 문제의 잘못된 절반만을 해결합니다. LLM(대형 언어 모델)을 이용해 X(트위터)에 게시물을 올리거나, Instagram에서 DM을 보내거나, LinkedIn 연결 요청을 보내는 것은 한 번쯤은 가능합니다. 하지만 이를 1,000번 해야 할 때 경제성은 무너집니다. 호출당 토큰 비용, 호출당 지연 시간, 그리고 호출 시마다 발생하는 비결정성 때문입니다. 아웃리치(영업 및 외부 커뮤니케이션), CRM 업데이트, 대량 게시 작업에서 "이번에 에이전트가 잘못된 버튼을 클릭함"은 단순한 특이치(quirk)가 아닙니다. 그것은 시스템의 치명적인 실패입니다.
가장 명백한 해결책은 UI(사용자 인터페이스)를 건너뛰고 해당 사이트의 내부 API를 직접 호출하는 것입니다. 이 방향은 맞지만, 대부분의 '그냥 API를 호출해'라는 프로젝트가 여기서 좌초합니다. 진짜 어려운 문제는 엔드포인트(API 경로)가 아니라 '인증(Auth)'이기 때문입니다.
인증(Auth)이 진짜 어려운 문제입니다 인증된 웹 요청은 쿠키, 회전하는 CSRF 토큰, 세션 토큰, Bearer 헤더, 재생 방지 논스(nonce), 지문(Fingerprint) 기반 매개변수, 그리고 요청 시점에 사이트 자체의 JS(자바스크립트)에서 계산된 요청 서명 해시 등의 조합을 포함합니다. 일부는 서버에서 설정되고, 일부는 브라우저 내부에서 파생됩니다. 그중 일부는 요청할 때마다 값이 바뀝니다. 프로세스 외부에서 동작하는 스크래퍼(Node 워커, Playwright 워커, 클라우드 함수 등)는 이 모든 것을 외부에서 다시 구축해야만 합니다. 사이트가 헤더를 회전시키거나 새로운 서명 방식을 도입하는 순간 이 방식은 바로 망가집니다. 대부분의 HAR(HTTP Archive) 재생 도구의 수명은 바로 여기서 끝이 납니다.
핵심 트릭: 확장 프로그램에서 녹화하고, 웹페이지 내부에서 재생하기 rtrvr(해당 솔루션)에서는 녹화와 재생 모두 사용자의 브라우저 내부, 즉 웹페이지 자체에서 이루어집니다. 확장 프로그램은 사용자가 작업을 수행하는 동안 브라우저 탭이 만드는 네트워크 요청을 가로챕니다. 이는 두 가지 계층으로 이루어집니다. 첫째, 어떤 페이지 스크립트보다도 먼저 설치되는 메인 월드(Main-world)의 fetch/XHR 패치입니다. 둘째, 페이지 내부 패치가 감지할 수 없는 CORS 및 서비스 워커 경로에 대비하기 위해 Chrome의 webRequest API를 사용한 상관(correlated) 대체 수단입니다. 요청 본문(FormData, Blob, 원시 바이트, 단순 JSON 포함) 역시 캡처됩니다.
이후 스크립트가 실행될 때, 해당 요청들은 페이지 자체의 실행 컨텍스트(동일한 출처, 동일한 쿠키, 동일한 TLS 세션, 서명된 헤더를 계산하는 동일한 JS)에서 전송됩니다. Puppeteer 드라이버도, 헤드리스 워커도, 별도의 TLS 스택도 필요 없습니다. 브라우저는 평소에 하던 대로 쿠키를 첨부하고, 사이트 자체의 JS를 실행하여 헤더를 계산한 다음, 요청을 전송합니다. 인증, CSRF, 서명, 지문(Fingerprinting)이 모두 자연스럽게 전파됩니다. 에이전트는 이러한 복잡한 과정에 전혀 개입하지 않습니다. 키 추출, 세션 재구축, 프록시 회전이 필요 없습니다. 이는 단순한 각주처럼 들릴 수 있지만, 이 솔루션의 전체 아키텍처를 관통하는 핵심 원리입니다.
네트워크 캡처의 순위 매기기 및 필터링(Trimming) "네트워크를 그냥 녹화하라"는 개념 안에는 두 번째 문제가 숨겨져 있습니다. 일반적인 1분간의 브라우징만으로도 탭당 수십에서 수백 개의 요청이 발생합니다. 여기에는 분석 비콘, RUM 핑, 기능 플래그 폴링, 서드파티 픽셀, 사전 가져오기(Prefetch), 미디어 청크, 핫 모듈 리로드(HMR) 요청 등이 포함됩니다. 정작 우리가 신경 쓰는 실제 API 호출은 300개 중 3개뿐일 수 있습니다. 이 모든 걸 LLM에 던져 어떤 것이 필요한 도구인지 파악하게 할 수는 없습니다. 이는 컨텍스트 윈도우(Context Window)에 들어가지도 않으며, 억지로 넣는다 한들 과금이 발생하는 데다 중요한 신호가 노이즈에 묻혀버립니다.
따라서 스크립트 생성기가 데이터를 확인하기 전에, 우리는 캡처된 데이터의 순위를 매기고 필터링합니다. 요청은 소수의 가중치가 적용된 신호를 기반으로 점수를 받습니다.
- 퍼스트파티(First-party) 대 서드파티(Third-party) 출처 (+20 / −15). Sentry, Segment, Hotjar, RUM 등과 같이 알려진 원격 측정(Telemetry) 호스트는 무조건 −80점을 받습니다. 클릭과 얼마나 잘 상관관계가 있는지는 중요하지 않으며, 이는 우리가 원하는 도구가 아닙니다.
- DOM 이벤트와의 시간적 상관관계 (800ms 이내 +28, 2.5초 이내 +16). '전송' 버튼을 클릭한 지 40ms 후에 발생한 POST 요청은 거의 확실히 전송 기능일 것입니다.
- 메서드 및 페이로드 형태 (데이터를 변경하는 POST/PUT/PATCH/DELETE: +35, GET: +5, 요청 본문 포함 시: +8, OPTIONS/HEAD/성능 항목: −40).
- 응답 품질 (2xx: +12, 4xx 이상: −25, 비어있지 않은 본문: +4).
- 휘발성 작업 식별자 (−18). URL이나 본문에 GraphQL의 queryId, doc_id, operationHash 또는 빌드별 해시가 포함된 요청들입니다. 이들은 오늘 당장에는 정상적으로 보이지만, 사이트가 다시 배포(redeploy)되는 순간 바로 망가집니다.
구체적인 예시로, 시스템은 퍼스트파티(First-party)이며 데이터를 변경하는...