토스 네뷸라 디바이스 팜
가져올 기법이 0종이었습니다. 대신 남의 원칙 하나가 제 코드의 갈라진 곳을 찾아줬습니다.
기법 0종, 도입 0건입니다. 초판에서 하나 채택했던 것이 2판에서 기각됐습니다 — 근거로 삼은 실측이 맞았는데 그 호출이 제 파이프라인에 0건이었습니다. 게임 클라이언트는 화면을 네이티브 서피스 하나에 그려서 접근성 트리가 애초에 안 잡히고, 그 사실은 제 프로젝트 문서에 이미 적혀 있었습니다. 그런데 이 조사가 헛되지 않았습니다 — 이 시스템의 원칙 하나를 자로 삼아 제 코드를 재보니 관문이 두 벌이었습니다.
무엇을 만든 것인가
팀마다 맥미니에 폰 대여섯씩 꽂아 각자 굴리던 작은 팜들을 하나로 통합한 것이 출발점이다. 맥미니 5대·기기 15대·개발자 1명으로 시작해 1년 만에 기기 100대를 넘겼다.
사용자가 보는 건 이게 전부다.
POST /device/occupy { platform: "android", tags: ["smoke"] }
POST /actions/click { x: 540, y: 1200 }
“기기 하나 잡아 줘 → 거기 (540,1200)을 눌러 줘.” 그 기기가 어느 맥미니에 물렸는지도, 드라이버 세팅도 알 필요가 없다.
기존 도구를 키우는 대신 기기 계층부터 새로 만들었다
이 글에서 제일 큰 결정이다. 규모를 키울수록 기존 자동화 프레임워크의 구조적 한계에 반복해서 부딪혔고, 임시 수리보다 소유가 낫다고 판단했다.
| 무엇을 걷어냈나 | 왜 |
|---|---|
| 세션 개념 | 세션 기동에 매번 15~40초, 규모가 커질수록 세션 실패가 급증, 관리 비용이 기기 수에 비례 |
| 데스크톱 전제 미러링 | 기존 도구는 “기기 화면 → 데스크톱 앱” 전제라 서버 경유 브라우저 다중 배포에 안 맞는다 |
| USB를 독점하는 캡처 | 독점하면 조작과 공존이 안 된다. 다른 방식은 10~15fps 슬라이드쇼 |
세션을 걷어낸 자리에 상시 떠 있는 컨트롤러 + 상태 없는 HTTP 호출을 놓았다. 그리고 인터페이스를 스펙 하나로 정의해 클라이언트를 자동 생성한다.
그 소유가 만든 부수 효과가 진짜 값어치다. 자체 한글 입력기(글자가 안 깨진다), 사내 빌드 즉시 설치, 보안 정책을 드라이버 규격 안에서 강제 — 스펙을 소유하니 남의 도구가 지원해 주기를 기다릴 필요가 없다.
깨본 결과 — 13.5배는 동종 비교가 아니다
간판 수치가 이렇다. 엘리먼트 클릭이 52ms 대 702ms = 13.5배.
그런데 저자가 스스로 단서를 붙였다 — 격차의 약 80%가 기존 도구의 화면 안정 대기이고, 그 대기를 끄면 2~3배로 좁혀진다. 즉 안전장치를 켠 값과 끈 값의 비교다. 정직하게 밝힌 건 좋은데, 표에서 “13.5배”만 떼어 인용하면 틀린 말이 된다. 선택 자체는 합리적이다 — 실시간으로 보며 조작하는 용도엔 속도가 맞다. 다만 철학의 교환이지 공짜 이득이 아니다.
더 큰 결손은 따로 있다. p50만 있고 p99가 없다. 테스트 자동화를 죽이는 건 중앙값이 아니라 꼬리다. 세션·명령 실패율, 기기 가동률, 플레이키 감소폭 — 안정성 수치가 글 전체에 하나도 없다.
나머지도 적어 둔다. 효과 근거가 증언 두 건이고 측정 조건·표본이 없다. 가장 가까운 오픈소스 선행 사례를 비교 대상에서 뺐다 — “왜 그게 아니라 자체 구축인가”가 답해지지 않았다. 그리고 iOS 캡처 경로가 특정 OS 계층이라 호스트를 통일 못 하는 구조적 비용이 생기는데 비용으로 서술되지 않았다. 마지막으로 드라이버가 비공개라 제3자가 표의 수치를 검증할 수 없다.
내 환경을 재봤다 — 그리고 대상이 틀렸다
실기기 하나로 읽기 전용 항목만 쟀다(조작계는 기기 상태를 바꾸므로 제외).
UI 덤프가 2,350ms로 저쪽의 10배 느렸다. 그래서 초판에서 기기 안 상주 컨트롤러를 유일한 수확으로 채택했다.
2판에서 기각됐다. 코드를 전수 대조하니 제 파이프라인에 그 호출이 0건이었다.
이유는 제 프로젝트 문서에 이미 적혀 있었다. 게임 클라이언트는 화면 전체를 네이티브 서피스 하나에 그린다 — 접근성 트리가 애초에 안 잡힌다. 그래서 제 화면 조작은 스크린샷 → 비전 → 좌표 탭 루프다. 그 도구를 붙여도 빈 트리가 온다. 10배 빨라질 대상 자체가 존재하지 않는다.
2,350ms는 실측이 맞았는데 대상이 틀렸다. 벤치마크를 재기 전에 “이 호출이 내 런에서 실제로 일어나는가”를 먼저 확인했어야 했다.
같은 실측이 가설 두 개를 더 기각했다. “케이블로 바꾸면 빨라진다” — 전송 구간이 전체의 5%라 최대 이득이 5%다. “프로세스를 상시 띄워 재사용한다” — 왕복이 73ms라 최대 4%다. 저쪽의 이득은 호스트가 아니라 기기 안에서 나오는데, 그걸 호스트 최적화로 오독하면 헛수고한다.
남은 건 남의 기법이 아니라 제 쪽 규율
이 글에서 “모든 도구가 공개 API 하나로 만들어졌다”고 한 지점을 자로 삼아 제 코드를 재봤다.
게이트웨이를 우회해 명령을 직접 부르는 곳이 7개 파일 14건이었다. 래퍼를 경유하는 파일과 거의 반반이다.
그런데 더 나쁜 게 나왔다. 우회 파일이 문제가 아니라 관문 자체가 두 벌이었다.
| 락 | 에러 분류 | 실제 런이 쓰는 것 | |
|---|---|---|---|
| 정식 관문 | 있음 | 있음 | ✗ |
| 다른 한 벌 | 없음 | 없음 | ✓ |
정식 관문의 방어가 실제 런에는 하나도 안 걸려 있었다. 나중에 계측기를 붙일 때도 이 사실 때문에 방어 없는 쪽에 달아야 했다.
판정
기법 0종, 도입 0건. 이 조사가 만든 건 제 코드에 대한 발견 하나다.
그게 벤치마킹의 정직한 결과일 때가 있다. 남의 시스템에서 베낄 게 없어도, 그 시스템의 원칙을 자로 삼아 제 걸 재보면 갈라진 데가 보인다.
기각한 것에도 재개 조건을 붙여 뒀다 — 대상이 일반 앱이 되거나, 빌드가 접근성 노드를 노출하도록 바뀔 때.