블로그로 돌아가기

AI Agent 웹 작업이 불안정해지는 네 가지 원인과 엔지니어링 방법

Agent가 웹 작업을 수행할 때 실패는 주로 요소 탐색, 대기와 타임아웃, 상태 저장, 환경 측 차단의 네 영역에서 발생합니다. 각 단계를 멱등하게 만들고, 복구 가능한 실패를 재시도하며, 상태를 영속화하고, 작업별로 환경을 격리하면 성공률을 훨씬 안정적으로 유지할 수 있습니다.

웹 자동화를 처음 시작하면 접근 방식은 대개 단순해 보입니다. 흐름을 만들고 스크립트를 실행하면 된다고 생각하기 쉽습니다. 로직에는 문제가 없어 보이는데도 작업은 간헐적으로 실패하고 계정 상태도 가끔 비정상적으로 변합니다. 처음에는 코드를 의심하지만 자세히 조사해 보면 문제는 대체로 네 영역에 집중됩니다.

AI Agent 网页任务不稳定的四类来源与工程做法的关键步骤与判断维度示意图

페이지가 바뀌면 요소 탐색이 깨진다

대부분의 스크립트는 selector로 요소를 찾습니다. selector를 고정해 두면 페이지의 거의 모든 변경이 이를 무효화할 수 있습니다. 버튼의 class 이름이 바뀌거나, 문구의 한 단어가 변경되거나, 특정 영역이 서버 렌더링에서 비동기 로딩으로 바뀌거나, 요소가 새 container 안에 들어갈 수 있습니다. A/B 테스트에서는 같은 페이지라도 계정에 따라 구조가 달라질 수도 있습니다.

일반적인 증상은 요소를 찾지 못하거나, 클릭이 엉뚱한 곳에 들어가거나, 이름은 같지만 다른 위치에 있는 컨트롤을 누르는 것입니다. 이런 실패는 네트워크 변동 때문이 아니므로 몇 번 재시도해도 해결되지 않습니다.

실용적인 방법은 절대 경로에 대한 의존을 줄이는 것입니다. 접근성 속성, 안정적인 비즈니스 ID, 요소 간 상대적 관계를 우선 사용하고, 같은 유형의 페이지에는 대체 selector를 준비해 기본 selector가 실패할 때 자동으로 fallback하도록 합니다. 페이지에 iframe이나 Shadow DOM이 있다면 먼저 올바른 context로 전환해야 하며, 그렇지 않으면 탐색은 실패합니다.

대기와 타임아웃 범위가 잘못 설정되어 있다

대기 시간이 너무 짧으면 요소 렌더링이 끝나기 전에 실패로 판단되어 스크립트 버그처럼 보일 수 있습니다. 너무 길면 한 작업의 실행 시간이 불필요하게 늘고 throughput이 떨어지며, 긴 타임아웃이 실제 오류를 가릴 수도 있습니다.

고정 sleep보다 명시적 대기가 더 신뢰할 만합니다. 대상 요소가 나타나거나, 요청에 응답이 오거나, 로딩 애니메이션이 사라지는 등 구체적인 조건을 기다립니다. 타임아웃 예산은 한 단계, 한 페이지, 전체 작업에 각각 별도로 두고, 모든 곳에서 같은 값을 쓰는 대신 단계적으로 범위를 좁혀야 합니다.

또한 페이지가 사용 가능한 상태가 되는 것과 비즈니스 결과가 생성되는 것을 구분해 기다려야 합니다. 전자는 DOM이 준비될 때까지 기다리면 충분한 경우가 많지만, 후자는 API callback이나 페이지의 상태 문구 변화를 기다려야 할 수 있습니다. 잘못된 신호를 기다리면 작업은 성공한 것처럼 보여도 실제 데이터는 기록되지 않을 수 있습니다.

여러 단계의 작업이 중간에 멈추면 진행 상황이 사라진다

가입, 주문, 게시 같은 작업은 쉽게 열 단계 이상이 됩니다. 타임아웃으로 인한 종료, 브라우저 충돌, 호스트 재시작 등으로 프로세스가 중간에 끝났는데 상태가 메모리에만 있다면 다음 실행은 처음부터 다시 시작하거나 이전 단계를 다시 제출해야 합니다.

중복 실행의 결과는 단순 실패보다 더 찾기 어렵습니다. 같은 작업이 두 번 수행되어 상위 시스템에 추가 레코드가 생기고, 그 출처도 추적하기 어려워집니다.

해결책은 각 단계에 영속화 지점을 두는 것입니다. 단계가 하나 끝날 때마다 작업의 고유 식별자와 함께 진행 상황을 영구 저장 위치에 기록하고, 재시작 후에는 마지막 성공 지점부터 이어 갑니다. 복잡한 framework는 필요하지 않으며 파일 하나나 상태 레코드 하나면 충분합니다.

환경 측 차단은 코드 오류처럼 보인다

앞의 세 문제는 작업 내부에서 발생하지만, 또 다른 유형은 환경에서 옵니다. 사이트는 브라우저 특성, 접근 행동, 네트워크 출처를 종합해 트래픽의 출처를 판단할 수 있습니다. 의심스럽다고 판단하면 검증 페이지, 빈 콘텐츠 또는 단순 타임아웃을 반환할 수 있습니다. 작업 로그에서는 실행 오류와 거의 구분되지 않습니다.

자주 나타나는 원인은 다음과 같습니다.

  • 출구 IP의 지역, 시간대, 언어가 서로 맞지 않음
  • 모든 작업이 동일한 브라우저 환경에서 요청을 보내 단위 시간당 요청 밀도가 실제 사용자보다 확연히 높음
  • 환경이 자주 바뀌거나 계정이 반복해서 다시 로그인함

성공률을 높이는 네 가지 방법

  1. 모든 단계를 멱등하게 만든다. 실행 전에 선행 조건이 이미 충족되었는지 확인해 같은 동작을 반복해도 추가 부작용이 생기지 않게 합니다. 조회 작업은 본래 멱등적이지만, 쓰기 작업은 고유 식별자나 중복 제거 키로 보호해야 합니다.
  2. 실패를 분류한다. 요소가 아직 렌더링되지 않았거나, 네트워크가 흔들리거나, API가 5xx를 반환하는 등 일시적인 실패는 backoff를 적용해 재시도할 수 있습니다. 계정 제한, 잘못된 파라미터, 대상 리소스 없음과 같은 확정적 실패는 여러 번 재시도해도 달라지지 않으므로 종료 처리해 concurrency 용량을 계속 점유하지 않게 합니다.
  3. 상태를 정기적으로 영속화한다. 진행 상황, 중간 결과물, 현재 단계를 저장해 작업이 재시작된 뒤 첫 단계가 아니라 중단된 지점에서 계속되게 합니다.
  4. 작업별로 실행 환경을 격리한다. 각 계정이나 작업에 독립적인 브라우저 환경을 할당해 Cookies와 로컬 스토리지를 공유하지 않고, fingerprint 특성에는 합리적인 차이를 두며, 시간대와 언어를 출구 IP 지역과 맞춥니다.

네 번째 방법은 작업 규모가 커질수록 특히 중요합니다. 수십 개에서 수백 개의 작업이 동시에 실행될 때 환경 계층이 안정성의 상한을 결정하고, 문제가 생겼을 때 영향 범위도 좌우합니다. PurpleMark는 이런 상황에서 독립 환경을 필요할 때 생성하고 일괄 회수할 수 있는 기능을 제공하며, 각 계정이 자체 환경을 사용하므로 작업 간 상태가 서로 오염되지 않습니다.

이 내용은 기술 연구와 개발 실무 공유만을 위한 것입니다. 관련 기술은 법률과 규정을 준수해 사용하고 대상 플랫폼의 서비스 약관을 지키십시오.