Mobile-use with Memory

jinwook12분
개발추천

Maestro나 Google Artemis 사용해보셨나요?

LLM들이 앱을 조작하는 능력(이하 mobile-use라 부름)은 점점 좋아지는데 아직 저희 앱을 많이 써 본 사람처럼 조작하기는 힘든 것 같습니다.

사실 이건 당연하다고 생각해요.

사람은 앱을 쓰면서 버튼을 누르면 어떤 동작이 일어나는지, 어떤 설정이 어느 화면 안에 있는지를 기억하잖아요? 그런데 대부분의 mobile-use는 화면을 확인하고 하나를 누르고 다시 화면을 확인하는 루프를 매번 처음부터 수행합니다.

그래서 메모리를 달아봤어요. 한 번 들어가 본 화면이랑 거기서 한 조작을 DB에 기록하고 다음에 동일한 화면에 진입하면 DB부터 조회합니다. (이렇게 만든 걸 retriever라고 부를게요.)

성능을 측정해보니 Claude Opus 5.5를 쓴 Maestro MCP보다 최대 1.9배, ARTEMIS Flash보다 최대 2.4배 빨랐습니다.

주의

retriever만 메모리 DB를 가지고 진행했습니다. Claude Code로 돌린 retriever와 Maestro MCP는 Claude Code 자체의 auto memory도 끄고 돌렸습니다.

retriever는 같은 앱의 다른 미션으로 튜닝됐습니다. 벤치 미션은 튜닝이 끝난 뒤에 새로 썼습니다.

벤치 환경

비교 대상

조건 구성 모델
retriever Claude Code + retriever 플러그인 · CLI, DB를 넣은 상태로 시작 Claude Opus 5.5, effort medium
Maestro MCP Claude Code + Maestro MCP Claude Opus 5.5, effort medium
ARTEMIS Flash ARTEMIS Flash 기본 설정 Gemini 3.8 Flash 외
ARTEMIS Pro ARTEMIS Pro 기본 설정(Planner · Operator · Checker) Gemini 3.8 Flash 외
Jev mobile-jev CLI, 기기는 Mobilerun 클라우드로 조작 jev-1.13.0

코드는 참고하지 않게 하고 앱은 자사 앱을 사용했습니다.

미션

앱은 리셋한 상태에서 시작했고 프롬프트에는 목표와 입력할 값, 마지막에 열려 있어야 할 화면만 제공했습니다.

미션 해야 할 일 DB에 쌓인 기록
m1 약 알림과 백업 알림을 작은 알림으로 바꾸고, 백업은 6회 · 7분 간격으로 적음
m2 패치 약(21일 사용 · 7일 휴약, 7일마다 교체)을 만들고 첫 교체만 다음 날 오전 8시로 옮기기 많음 · 보통
m3 필요시 약을 등록하고 어제 두 번 먹은 기록을 남긴 뒤 한 기록에 메모 많음 · 보통
m4 부양가족(이름 · 성별 · 생년월일 · 알레르기)을 만들고 그 사람의 약을 매일 오후 8시로 많음
m5 약 세 개를 등록하고 오전 7:40 알림만 일 · 수요일에 무음 + 진동으로 적음

retriever가 가지고 시작한 DB는 그동안 pillo를 QA하며 쌓인 기록입니다. 세션 561개, 화면 1,159개, 이동 경로 2,501개, 조작 기록 18만여 건이 들어 있습니다.

"DB에 쌓인 기록"은 미션이 거치는 핵심 화면에 기록이 얼마나 있는지를 나타냅니다. 그 화면에서 시작한 조작이 50건 이상이면 많음, 20건 이하면 적음으로 나눴습니다. 미션과 같은 흐름이 DB에 있었던 건 m3 하나뿐입니다(같은 흐름의 세션 27개).

성공과 시간

성공은 "에이전트가 끝났다고 보고했고 런이 끝난 뒤 확인한 앱의 저장 상태(Room DB · DataStore)가 판정 SQL을 통과했다"로 정했습니다. 화면에 보이는 값은 판정에 쓰지 않았습니다.

시간은 에이전트가 미션을 받은 순간부터 최종 상태를 확정한 순간까지 걸린 시간입니다. 대표값으로는 성공한 런의 중앙값을 썼습니다.

결과

성공 (x/5)

미션 retriever Maestro MCP ARTEMIS Flash ARTEMIS Pro Jev
m1 5/5 5/5 5/5 5/5 0/5
m2 5/5 5/5 5/5 5/5 0/5
m3 5/5 5/5 4/5 5/5 0/5
m4 5/5 5/5 5/5 5/5 0/5
m5 5/5 5/5 2/5 2/5 0/5
합계 25/25 25/25 21/25 22/25 0/25

시간 (성공한 런의 중앙값, 초)

미션 retriever Maestro MCP ARTEMIS Flash ARTEMIS Pro
m1 66 87 (1.3배) 104 (1.6배) 172 (2.6배)
m2 124 178 (1.4배) 186 (1.5배) 467 (3.8배)
m3 183 339 (1.9배) 379 (2.1배) 643 (3.5배)
m4 131 249 (1.9배) 311 (2.4배) 526 (4.0배)
m5 233 320 (1.4배) 368* (1.6배) 871* (3.7배)
합계 736 1,172 (1.6배) 1,349 (1.8배) 2,679 (3.6배)

*는 ARTEMIS가 m5에서 2번만 성공해서 그 2런의 중앙값입니다.

다섯 미션 모두 retriever가 가장 빨랐습니다. 다섯 번 사이의 편차도 작았습니다(m1은 61 ~ 80초, m4는 129 ~ 161초).

비용은 Maestro MCP와 거의 같았습니다. API 단가로 환산하면 런당 retriever $1.54, Maestro MCP $1.55입니다. 같은 비용으로 1.6배 빨리 끝난 셈이죠.

ARTEMIS가 실패한 7건

ARTEMIS는 Flash에서 4번, Pro에서 3번 실패했는데 7건 모두 성공했다고 스스로 보고했고 마지막 화면에도 고른 값이 보였습니다. 그런데 앱에 저장된 값은 달랐습니다.

그중 6건이 m5에서 나왔습니다. m5는 시간 슬롯 시트에서 요일과 무음을 고른 뒤 Save를 눌러야 저장되는데 Save 전에 시트를 닫아도 화면에는 고른 값이 그대로 남아 보입니다. 화면만 보고 채점했다면 이 7건은 전부 성공으로 쳤을 거예요.

retriever와 Maestro MCP에서는 이런 거짓 성공이 한 번도 없었습니다.

Jev의 실패 원인

Jev는 요즘 핫하다는 mobile-jev를 사용했는데 25번 모두 미션을 완료하지 못했습니다. 같은 대상에 같은 조작을 반복하다가 반복 감지에 걸려 스스로 멈췄고 멈춘 시점도 회차마다 거의 같았습니다(m1은 13 ~ 15초).

다만 이건 제 연동 방식의 한계일 수 있어요. Jev는 텍스트 필드에 입력할 글자를 스스로 정하지 않고 프롬프트에 그대로 적힌 값이나 실행할 때 --text로 넘겨준 값만 입력합니다. 그래서 제 벤치 스크립트가 프롬프트에서 입력값이 될 만한 부분(따옴표 안의 글자, 한글이 없는 짧은 구간)을 골라 넘겼는데 이 방식으로 뽑히지 않은 값은 채우지 못했습니다. 성공한 런이 없어서 시간은 비교하지 않았습니다. (좋은 방법이 있다면 알려주세요.)

메모리 동작 방식

retriever의 메모리 순환

retriever는 앱의 화면 하나하나와 화면 사이의 이동 경로를 기록합니다. 이 기록은 프로젝트 안의 DB 파일 하나(.qa/retriever.db)에 계속 쌓입니다. 세션 하나가 이 DB를 어떻게 쓰는지 순서대로 따라가 보겠습니다.

세션을 시작하면 explore-plan이 목표 화면까지 가는 경로를 DB에서 먼저 계산합니다. 이번 벤치에서는 25런 중 22런이 이 계획을 따라 움직였습니다.

화면에 들어갈 때마다 screen-analyze가 지금 어느 화면인지 알아냅니다. 이때 그 화면에 붙은 메모("첫 진입에 권한 팝업이 뜬다" 같은 것)와 지난 세션들이 이 화면에서 이어 간 조작 순서(## TRAIL)도 함께 보여 줍니다.

조작은 act 명령 하나로 처리합니다. 조작을 실행하고 화면 변화가 멈출 때까지 기다린 뒤 화면의 요소 목록을 텍스트로 돌려줍니다. 모델은 그 텍스트를 읽고 다음 조작을 정합니다.

조작이 실패하면 잠금이 걸립니다. 원인과 사유를 적기 전에는 다음 조작을 할 수 없어요. 이렇게 모인 사유는 /retriever:learn이 한 줄짜리 회피 규칙으로 줄여서 그 화면의 메모에 추가합니다. 다음 세션이 그 화면에 들어오면 screen-analyze가 이 규칙을 함께 보여 주고요.

성공한 이동 경로와 실패에서 얻은 회피 규칙이 이렇게 DB에 남으니까 같은 앱을 오래 쓸수록 헤매는 시간이 줄어듭니다.

한 번 완료한 흐름은 세션이 끝나면 회귀 테스트 .sh로 승격됩니다. 승격된 스크립트는 bash와 retriever CLI만으로 실행돼서 다시 실행할 때는 LLM이 필요 없습니다. 이번 벤치는 이 기능을 끄고 쟀습니다.

속도 차이의 원인

retriever와 Maestro MCP는 모델, effort, Claude Code 버전, 기기가 전부 같습니다. 그래서 둘을 비교하면 모델 밖에서 생긴 차이만 볼 수 있습니다. 차이는 retriever의 구조와 DB에서 나왔습니다.

구조가 만든 차이

먼저 두 에이전트의 시간을 모델이 생각한 시간과 기기에서 명령이 실행된 시간으로 나눠 봤습니다.

다섯 미션 중앙값의 합 retriever Maestro MCP
턴 170 165
모델 시간(초) 약 410 약 407
명령 실행(초) 약 318 약 757
턴 하나의 명령 실행 평균(초) 2.0 4.7
명령 호출(25런 합계) 826 1,510

모델이 생각하고 출력한 시간은 거의 같았습니다. 다섯 미션을 합쳐 보면 차이는 거의 전부 기기에서 명령이 실행된 시간에서 나왔습니다.

Maestro MCP를 쓴 Claude는 791턴 가운데 703턴에서 조작(run)과 스크린샷(take_screenshot)을 함께 호출했습니다. 조작한 뒤에 화면이 어떻게 바뀌었는지 보려면 스크린샷을 한 장 더 받아야 하니까요.

retriever는 조작과 관찰이 한 명령(act)입니다. 조작을 실행한 뒤에는 연속한 화면 덤프 두 개가 500ms 동안 같아질 때까지 CLI 안에서 기다립니다. 그리고 변화가 멈춘 화면을 텍스트로 돌려줍니다. 스크린샷은 필요할 때만 열었습니다. 25런에서 스크린샷을 연 건 138번이었고 그중 75번은 휠 피커의 값을 확인하려던 것이었습니다.

명령 하나가 기기에 전달되는 과정도 줄였습니다. UIAutomator2 서버는 세션 내내 하나를 다시 쓰고 화면 캡처는 에뮬레이터 콘솔로 받습니다. CLI도 매번 새로 실행하지 않고 미리 실행해 둔 JVM 하나가 소켓으로 명령을 받습니다.

이 차이는 DB와 관계가 없습니다. 실제로 DB에 기록이 적은 m5에서 retriever는 Maestro MCP보다 턴을 오히려 더 썼는데도(49 대 38) 1.4배 빨랐습니다.

DB로 인한 차이

DB의 효과는 미션별로 나눠 봐야 보입니다.

미션 DB에 쌓인 기록 Maestro MCP 대비 ARTEMIS Flash 대비
m1 적음 1.3배 1.6배
m5 적음 1.4배 1.6배
m2 많음 · 보통 1.4배 1.5배
m3 많음 · 보통 1.9배 2.1배
m4 많음 1.9배 2.4배

DB에 기록이 적은 m1 · m5에서는 Maestro MCP보다 1.3 ~ 1.4배 빨랐습니다. 기록이 많은 m3 · m4에서는 1.9배로 벌어졌고 턴도 Maestro MCP보다 적게 썼습니다(m3 40 대 45 · m4 30 대 35).

DB가 있으면 모델이 다음 조작을 덜 고민합니다. 세션을 시작하면 explore-plan이 DB에서 목표 화면까지의 경로를 계획해 줬고 25런 중 22런이 이 계획을 썼습니다. 그리고 화면을 관찰할 때마다 지난 세션들이 그 화면에서 이어 간 조작 순서(TRAIL)가 함께 나옵니다. 모델은 다음 화면의 버튼 이름을 모르면 조작을 묶지 않는데 TRAIL이 그 이름을 미리 알려 줍니다.

bench로 다듬기

사실 처음 이 아키텍처를 넣었을 때는 기대만큼 빨라지지 않았어요. 알고 보니 명령마다 기다리는 시간이 길었고 모델은 DB에 있는 정보를 제대로 쓰지 못하고 있었어요. 그래서 요즘 많이 쓰는 방식대로 bench를 돌려 가며 고쳐 보기로 했습니다.

아이디어는 Andrej Karpathy가 올해 3월에 공개한 autoresearch에서 가져왔습니다. 에이전트가 학습 코드를 고치고 5분씩 학습을 돌려서 점수가 좋아진 수정만 남기는 방식입니다. 채점은 에이전트가 손대지 못하게 막아 둡니다. 저희는 이 루프를 retriever에 적용했습니다.

튜닝 과정

라운드마다 먼저 지난 라운드의 트랜스크립트를 열어 한 런의 시간을 모델이 생각한 시간과 기기에서 명령이 실행된 시간으로 나눴습니다. 기기 쪽은 다시 준비 · 조작 · 화면 대기 · 관찰로 쪼갰습니다. 여기서 가설을 하나 골라 별도 worktree에서 retriever의 CLI나 스킬 문서를 고쳤습니다.

그다음 직전에 채택한 버전을 대조군으로 두고, 튜닝용 미션 4 ~ 6개를 두 버전이 3번씩 번갈아 수행했습니다. 한쪽을 몰아서 실행하면 그 시간대에 API가 느렸던 것까지 효과로 착각하게 되기 때문입니다. "어떤 지표가 얼마나 바뀔지"는 라운드를 실행하기 전에 적어 두었습니다. 그리고 빨라졌는데 성공률이 떨어지지 않았을 때만 채택해서 릴리스했습니다.

과적합도 막아야 했습니다. 앱의 화면 이름이나 버튼 문구가 CLI나 스킬 문서에 들어가면 채택하지 않았습니다. 그리고 튜닝에는 위 결과 표와 다른 미션을 썼습니다. 마지막 튜닝 라운드는 10월 9일 밤에 끝났고 m1 ~ m5는 그다음 날 저녁에 별도 에이전트가 앱 소스를 보고 새로 썼습니다. 이 에이전트는 이전 측정의 기록도, 그걸 보고 고친 내용도 보지 않았습니다.

채택한 변경

배율은 대조군 대비 시간입니다.

바꾼 것 측정된 변화 배율
조작 결과를 모델이 바로 읽을 수 있는 텍스트로 돌려주기 (run --text) 모델이 출력을 파이썬으로 다시 거르던 호출이 183번에서 1번으로 0.90배
지난 세션들이 이 화면에서 이어 간 조작 순서를 관찰 결과에 붙이기 (## TRAIL) 한 호출에 여러 조작을 묶은 횟수가 런당 0.67회에서 2.42회로 0.86배
화면 변화가 멈췄다고 판단하는 대기를 800ms에서 500ms로 화면 대기 중앙값이 1,359ms에서 957ms로 0.92배
조작과 관찰을 한 명령(act)으로 합치고 마무리 단계의 불필요한 호출 줄이기 런당 턴 −1.4개, 출력 −970토큰, 명령 실행 −3.7초 0.87배
모델 effort를 high에서 medium으로 턴과 출력이 함께 줄었고 성공률은 그대로 0.92배
CLI를 상주 실행기로 (JVM 하나가 소켓으로 명령을 받는다) 기기 명령 한 번이 1,973ms에서 1,781ms로 기기 구간 −10%

9월 24일부터 10월 9일까지 이 루프를 74라운드 돌렸습니다. 튜닝용 미션 네 개를 한 번씩 수행하는 데 처음에는 약 1,150초(미션당 5분 가까이) 걸렸는데 마지막에는 345초(미션당 1분 반 남짓)까지 줄였어요. 약 3.3배! 앞에서 본 속도 차이도 대부분 이 루프에서 나왔습니다.

알게 된 점

  • 효과가 난 수정은 모델 턴을 줄이거나 명령마다 붙는 화면 대기 · JVM 기동 · 서버 기동 시간을 없애거나 턴마다 쓰는 출력 토큰을 줄인 경우였습니다. 재 보니 턴 하나의 모델 시간은 약 1초에 출력 토큰당 9.3ms를 더한 값이었고 명령 호출 하나를 없애면 약 3초가 줄었습니다.
  • 스킬 문서에 규칙을 적어도 모델은 거의 바뀌지 않았습니다. "한 호출에 조작을 1 ~ 3개씩 묶어라"라고 적어 둬도 다음 화면의 버튼 이름을 모르면 조작을 묶지 않았습니다. 행동을 바꾼 건 TRAIL처럼 CLI 출력이 다음 조작을 직접 알려 줄 때였습니다.
  • 모델을 바꾸거나 effort를 낮춰도 빨라지지 않았습니다. Sonnet은 턴마다 20 ~ 29% 빨랐지만 경로를 덜 검토해서 턴 수가 늘었고 저장이 안 됐는데 성공이라고 보고한 런도 하나 나왔습니다. effort low도 마찬가지로 기기 호출이 늘었습니다.
  • 줄이면 안 되는 대기도 있었습니다. 화면 대기를 350ms까지 줄였더니 휠 피커가 멈추기 전의 값을 읽어 버려서 스크린샷으로 다시 확인하는 횟수가 오히려 늘었습니다. 500ms가 하한이었습니다.

한계

  • DB를 가지고 시작한 건 retriever뿐이라 같은 조건에서 에이전트만 바꾼 비교는 아닙니다.
  • ARTEMIS와 Jev는 기본 설정 그대로 돌렸고 모델도 달라서 배율에는 모델 차이와 에이전트 차이가 함께 들어 있습니다.
  • 앱 하나와 기기 한 대로만 측정했습니다. retriever는 그 앱의 다른 미션으로 튜닝됐습니다.
  • 미션은 retriever를 만든 저희가 준비했습니다. 그래서 미션과 판정 SQL, 집계 스크립트를 측정 전에 커밋 하나로 묶어 태그를 달아 두고 그 뒤로는 규칙을 고치지 않았습니다.

jinwook

Mobile-use with Memory - Maestro MCP·ARTEMIS와 비교한 LLM 앱 조작 벤치 | hugdochi