LLM 기반 Android 자동화 실행을 디버깅하는 방법
요약
LLM 기반 Android 자동화 에이전트의 실패 원인을 분석하고 디버깅하기 위한 실행 트레이스 저장 전략을 제안합니다. UI 덤프, 모델의 선택, 실제 명령, 로그 등을 단계별로 기록하여 에이전트의 복구 능력을 높이는 방법을 다룹니다.
핵심 포인트
- 모든 에이전트 단계에서 UI 덤프와 모델 행동을 기록해야 함
- 전체 XML 대신 압축된 액션 테이블 사용 권장
- 스크린샷은 시각적 검토가 필요한 경우에만 선택적으로 저장
- 모델의 출력값과 실제 실행 명령을 분리하여 기록하여 번역 오류 확인
LLM (Large Language Model) 기반 Android 자동화는 기이한 방식으로 실패합니다.
모델이 잘못된 레이블을 탭할 수도 있습니다. 관찰(Observation)과 행동(Action) 사이에 화면이 바뀔 수도 있습니다. 키보드가 버튼을 가릴 수도 있습니다. 권한 대화 상자가 나타날 수도 있습니다. 앱이 여전히 로딩 중일 수도 있습니다. UI 덤프(UI dump)에 동일한 "Continue" 버튼이 두 개 노출될 수도 있습니다.
만약 최종 스크린샷만 저장했다면, 디버깅은 고통스러울 것입니다.
실행 트레이스(Run trace)가 필요합니다.
빠른 답변
모든 Android 에이전트 단계마다 다음을 저장하세요:
- 압축된 UI 덤프 (Compact UI dump)
- 필요 시 스크린샷
- 모델이 선택한 행동 (Model's chosen action)
- 실제 디바이스 명령 (Actual device command)
- 결과 또는 구조화된 에러 (Result or structured error)
- 최근 로그 (Recent logs)
- 최상위 패키지/액티비티 (Top package/activity)
최소한으로 유용한 트레이스는 다음과 같습니다:
observe: tap Button "Continue" #continue 540,860
model: tap "Continue"
action: hs tap "Continue" --visible --unique
...
이는 단순히 "에이전트가 실패했다"라고 하는 것보다 디버깅하기 훨씬 쉽습니다.
실패 모드 (The failure modes)
Android 에이전트의 실패는 보통 몇 가지 범주로 나뉩니다.
| 실패 (Failure) | 의미 (What it means) |
|---|---|
NOT_FOUND | 대상 레이블 또는 셀렉터가 보이지 않음 |
| ... |
좋은 툴링(Tooling)은 어떤 범주의 실패가 발생했는지를 보존해야 합니다.
모든 것이 "클릭 실패"로 변해버린다면, 에이전트는 지능적으로 복구할 수 없습니다.
행동 전 UI 덤프 저장하기
UI 덤프는 에이전트가 바라보는 세상의 모습입니다.
모델의 각 결정 전에 이를 저장하세요:
hs ui > run/0007-ui.txt
LLM 에이전트의 경우, 전체 XML보다는 압축된 액션 테이블 (Compact action table)이 일반적으로 더 좋습니다:
fill EditText "Email" #email 540,540
fill EditText "Password" #password 540,640 [password]
tap Button "Continue" #continue 540,860
모델이 잘못된 행동을 선택했을 때, 이 파일은 모델이 합리적인 선택을 했었는지를 알려줍니다.
스크린샷 선택적 저장
스크린샷은 가치가 있지만, 모든 단계마다 전체 네이티브 PNG가 필요하지는 않습니다.
대부분의 에이전트 디버깅을 위해서는:
hs see --size 768 run/0007-screen.jpg
다음과 같은 경우에 스크린샷을 사용하세요:
- UI 덤프 (UI dump)에 정보가 너무 적은 경우
- 앱이 커스텀 컨트롤 (custom controls)을 렌더링하는 경우
- 시각적 레이아웃 (visual layout)이 중요한 경우
- 실패에 대해 사람의 검토 (human review)가 필요한 경우
텍스트 UI를 기본값으로 사용하세요. 스크린샷은 증거로 사용하세요.
모델 동작을 별도로 기록하세요
최종 명령만 저장하지 마세요.
모델이 실제로 출력한 내용을 저장하세요:
{
"step": 7,
"model_action": "tap \"Continue\"",
...
이것이 중요한 이유는 버그가 번역 (translation) 과정에서 발생할 수 있기 때문입니다:
- 모델은 올바른 레이블 (label)을 선택했지만, 도구 호출 (tool call)에서 잘못된 셀렉터 (selector)를 사용한 경우.
- 레이블을 사용할 수 있음에도 모델이 좌표 (coordinate)를 선택한 경우.
- 모델이 모호성 경고 (ambiguity warning)를 무시한 경우.
모델 계층 (model layer)과 도구 계층 (tool layer)을 분리하여 유지하세요.
구조화된 에러를 선호하세요
종료 코드 (exit codes)와 에러 코드 (error codes)를 사용하는 것이 stderr 스크래핑 (stderr scraping)보다 좋습니다.
Handsets는 다음과 같은 공통 종료 코드를 가집니다:
0 ok
2 NOT_FOUND
3 TIMEOUT
...
JSON 모드에서는 구조화된 에러를 보존하세요:
hs --json tap "Continue" --visible --unique
그러면 에이전트 (agent)가 다음과 같이 결정할 수 있습니다:
NOT_FOUND: UI 덤프를 다시 수행하거나 스크롤AMBIGUOUS: 더 좁은 범위의 셀렉터 요청TIMEOUT: 스크린샷 및 로그 캡처SECURE_WINDOW: 스크린샷 없이 계속 진행
로그를 실패한 단계 근처에 유지하세요
Android 로그는 노이즈가 많습니다. 실패 지점 근처의 짧은 tail 로그만으로도 보통 충분합니다:
hs logs --tail 200 > run/0007-logcat.txt
로그를 동일한 단계의 UI 덤프 및 스크린샷과 쌍으로 맞추세요. 그렇지 않으면 기술적으로는 존재하지만 서로 연관 짓기 어려운 아티팩트 (artifacts)들이 남게 됩니다.
간단한 아티팩트 레이아웃
번호가 매겨진 파일을 사용하세요:
run/
0001-ui.txt
0001-action.json
...
이것은 화려하지 않습니다. 바로 그 점이 핵심입니다.
대시보드 (dashboard)를 구축하기 전에, 일반 파일만으로도 실행 결과(run)를 조사할 수 있도록 만드세요.
리플레이 (Replay)는 다음 단계입니다
추적 데이터 (traces)를 확보하면 리플레이가 가능해집니다.
유용한 리플레이는 픽셀 단위로 완벽한 비디오가 아닙니다. 그것은 타임라인 (timeline)입니다:
Step 1: observed Sign in
Step 2: tapped Sign in
Step 3: filled Email
...
팀의 경우, 이 타임라인(timeline) 자체가 제품이 됩니다. 이를 통해 엔지니어는 모델(model), 도구(tool), 또는 앱(app) 중 무엇이 실패를 일으켰는지 확인할 수 있습니다.
FAQ
왜 LLM Android 에이전트(agents)는 디버깅하기 어려운가요?
실패의 원인이 모델(model), 앱(app), Android UI 상태(UI state), 자동화 도구(automation tool), 또는 타이밍(timing)에서 발생할 수 있기 때문입니다. 마지막 스크린샷만으로는 어느 계층(layer)에서 실패했는지 알 수 없습니다.
모든 단계마다 스크린샷을 저장해야 하나요?
항상 그럴 필요는 없습니다. 모든 단계에 대해서는 압축된 UI 덤프(UI dumps)를 저장하세요. 시각적 상태(visual states), 실패 상황, 그리고 커스텀 렌더링된 화면(custom-rendered screens)의 경우에만 스크린샷을 추가하세요.
가장 중요한 아티팩트(artifact)는 무엇인가요?
동작 수행 전의 UI 덤프(pre-action UI dump)입니다. 이는 모델이 동작(action)을 선택했을 때 무엇을 보았는지 보여줍니다.
이것이 신뢰성(reliability)에 어떻게 도움이 되나요?
구조화된 트레이스(Structured traces)를 통해 타겟팅된 복구(recovery)를 구축할 수 있습니다. 예를 들어 NOT_FOUND 시에는 스크롤을 하고, AMBIGUOUS 시에는 선택자(selectors)를 좁히며, TIMEOUT 시에는 로그를 캡처함으로써 맹목적인 재시도를 피할 수 있습니다.
관련 가이드
- Android Automation for LLM Agents
- Android Device Cloud for LLM Agents
- Stop Wasting Tokens on Android Automation
원문은 https://handlets.dev/blog/debug-llm-android-automation-runs/에 게시되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기