앱 안에서만 되는 일이 아직 많다. 당근 나눔 신청, 예약 앱 체크인, 은행 앱 인증처럼 API가 없거나 막혀 있는 일은 자동화 스크립트가 손을 못 댄다. Phone Harness는 이 지점을 정면으로 건드린다. 에이전트에게 실제 폰 화면을 보여주고, 손가락 대신 탭하고 입력하게 만든다.
이 글은 Phone Harness가 무엇인지, 아이폰·안드로이드·클라우드 폰 중 무엇을 골라야 하는지, 설치와 첫 실행에서 어디서 막히는지 정리한다.
30초 요약
| 궁금한 것 | 답 |
|---|---|
| 무엇 | 에이전트가 실제 폰 앱을 탭·입력·스크롤하게 해주는 오픈소스 Python CLI (GitHub) |
| 라이선스 | MIT, Python, 2026-11-05 기준 GitHub 스타 4,449개 |
| 아이폰 경로 | 맥의 iPhone Mirroring 창을 캡처 → Apple Vision OCR로 글자·좌표를 읽고 클릭을 보낸다 |
| 안드로이드 경로 | adb로 스크린샷·입력, 접근성 트리로 정확한 요소를 찾는다 |
| 설치 | pip install phone-harness (Python 3.10 이상), phone-harness skill로 에이전트에 스킬 등록 |
| 아이폰 필수 조건 | macOS 15 이상 + Apple silicon 또는 T2 맥, iOS 18 이상, 같은 Apple 계정 |
| 클라우드 요금 | 안드로이드 분당 5¢(월 $20에 1,000분 포함), 클라우드 아이폰 월 $80 |
| 못 하는 것 | 멀티터치, 카메라·Face ID, DRM 영상 캡처, adb 한글 직접 입력 |
| 제일 큰 위험 | 모델이 쓴 Python이 내 맥에서 그대로 실행된다. 승인 게이트를 끄면 안 된다 |
목차
- Phone Harness란?
- 설치 전에 확인할 것 — 아이폰·안드로이드·클라우드
- 설치와 에이전트 연결 (Claude Code·Codex·OpenClaw)
- 아이폰·안드로이드 연결 — 두 경로의 차이
- 실제로 시키는 일 — 헬퍼 명령
- 클라우드 폰 요금과 쓰는 법
- 한계와 보안
- 내가 막혔던 곳
- 참고 자료

에이전트는 앱을 열고, 화면 글자에서 버튼 위치를 찾아 탭한 뒤 다시 화면을 읽는다. 사람이 폰을 쓰는 순서와 같다.
위 화면은 에이전트가 "설정 앱 열고 상위 10개 항목 읽기"를 수행하는 흐름을 도식으로 정리한 것이다. 사람이 하는 동작을 그대로 흉내 낸다는 점이 핵심이다.
Phone Harness란?
한 줄로 말하면 "폰을 다루는 손과 눈을 에이전트에게 붙여주는 도구"다. 탈옥도, Xcode 빌드도, 폰에 무언가를 설치하는 일도 없다. README는 이렇게 소개한다. "에이전트가 스크롤하고, 탭하고, 입력하고, 폰을 읽는다. 탈옥 없이, Xcode 없이, 폰에 설치되는 것도 없이." (GitHub README)
구조는 단순하다. Claude Code나 Codex 같은 CLI 에이전트가 내 컴퓨터에서 돌고, 그 에이전트가 phone-harness를 호출한다. Phone Harness는 폰 화면을 읽어 텍스트와 좌표를 돌려주고, 에이전트가 고른 좌표로 탭을 보낸다. 모델은 폰에 올라가지 않는다. 폰은 화면과 입력 장치 역할만 한다.
여기서 "하네스"라는 말이 낯설 수 있다. 원래 하네스는 모델을 둘러싸고 도구·권한·실행 환경을 붙여주는 껍데기다. 하네스(harness)란?에서 개념을 먼저 잡고 오면 이 글이 훨씬 빨리 읽힌다. Phone Harness는 그 껍데기에 "휴대폰"이라는 몸을 하나 더 단 셈이다.
지원 범위는 세 갈래다. 개인 아이폰은 맥의 iPhone Mirroring을 거친다. 개인 안드로이드는 adb로 붙는다. 폰이 없거나 여러 대가 필요하면 Phone Harness Cloud에서 빌려 쓴다. 세 경로의 요구사항이 완전히 다르므로, 설치보다 먼저 자기 폰이 어느 쪽인지 확인해야 한다.
설치 전에 확인할 것 — 아이폰·안드로이드·클라우드
| 연결 | 필요한 것 | 안 되는 경우 |
|---|---|---|
| 개인 아이폰 | macOS 15 이상, Apple silicon 또는 T2 맥, iOS 18 이상, iPhone Mirroring 페어링, 터미널에 손쉬운 사용·화면 기록 권한 | 인텔 맥(2017년형 등), macOS 14 이하, EU 지역 |
| 개인 안드로이드 | macOS·Linux·Windows 아무거나, Android Platform Tools(adb), USB 디버깅 또는 무선 디버깅 | 잠긴 폰은 직접 풀어야 함 |
| 클라우드 안드로이드 | Phone Harness Cloud 계정, 호스트에 adb | 분당 과금 |
| 클라우드 아이폰 | Cloud 계정만 (HTTPS로 제어) | 월 구독, 실기기 한정 수량 |
아이폰 조건이 특히 빡빡하다. Apple 문서는 iPhone Mirroring 요구사항을 이렇게 못 박는다. "Mac이 macOS Sequoia 15 이후이고 Apple silicon 또는 Apple T2 보안 칩이 탑재된 Mac일 것, iPhone이 iOS 18 이후이고 암호가 설정되어 있을 것, 두 기기가 같은 Apple 계정으로 2단계 인증을 사용할 것." (Apple — iPhone Mirroring) T2 칩이 없는 인텔 맥은 여기서 탈락한다. 내 맥이 정확히 그 경우였고, 자세한 건 8번 절에 적었다.

아이폰·안드로이드·클라우드 폰의 조건을 한 장으로 비교했다. 아이폰 경로의 요구사항이 가장 빡빡하다.
표에 담은 세 경로를 그림으로 비교하면 위와 같다. "폰을 이미 갖고 있는가"와 "아이폰인가" 두 질문으로 갈린다고 보면 된다.
설치와 에이전트 연결 (Claude Code·Codex·OpenClaw)
기본은 PyPI 설치다. 2026-11-05 기준 최신 버전은 0.3.3이고 Python 3.10 이상을 요구한다. (PyPI — phone-harness)
pip install phone-harness
phone-harness --doctor # 연결 상태 점검
phone-harness config set telemetry false # 익명 사용 통계 끄기 (선택)
소스를 고치고 싶으면 Git 체크아웃으로 설치한다.
git clone https://github.com/phone-harness/phone-harness ~/.phone-harness
cd ~/.phone-harness
pip install -e .
다음은 에이전트에 스킬을 등록하는 단계다. 여기서부터가 진짜다. CLI만 깔면 사람이 명령어를 외워야 하지만, 스킬을 등록하면 에이전트가 헬퍼 목록과 요령을 스스로 읽는다.
# Claude Code
mkdir -p ~/.claude/skills/phone-harness
phone-harness skill > ~/.claude/skills/phone-harness/SKILL.md
# Codex
mkdir -p "${CODEX_HOME:-$HOME/.codex}/skills/phone-harness"
phone-harness skill > "${CODEX_HOME:-$HOME/.codex}/skills/phone-harness/SKILL.md"
OpenClaw를 쓴다면 플러그인으로 붙는 쪽이 편하다. 설치는 한 줄이다. (OpenClaw 통합 문서)
openclaw plugins install clawhub:phone-harness
조건은 OpenClaw 2026.10.9 이상과 게이트웨이가 도는 머신에 uv가 있는 것이다. 플러그인은 phone_exec 도구 하나를 노출한다. 모델이 짧은 Python 스크립트를 쓰면 승인 창에 스크립트 전문이 뜨고, 내가 허용해야 폰에서 실행된다. 스크립트 앞 500자가 넘으면 승인 창에 다 못 담기 때문에 아예 승인 요청이 오지 않는다. 그래서 모델이 스크립트를 잘게 쪼개서 보낸다.
MCP 클라이언트를 쓴다면 https://mcp.phone-harness.com/mcp를 등록하면 된다. 다만 MCP는 아직 클라우드 폰(안드로이드 에뮬레이터·클라우드 아이폰)만 지원한다. 내 방에 있는 실기기를 MCP로 직접 부르는 건 안 된다.
아이폰·안드로이드 연결 — 두 경로의 차이
아이폰: iPhone Mirroring이 전부다
아이폰 경로의 원리는 이렇다. 맥에서 iPhone Mirroring을 켜면 폰 화면이 맥 창으로 흘러나온다. Phone Harness는 그 창을 캡처해서 Apple Vision 프레임워크로 글자를 읽고, 읽은 글자의 좌표에 클릭과 키 입력을 보낸다. 폰 입장에서는 맥이 보낸 터치와 키보드 입력으로 보인다.
phone-harness --doctor ios
순서는 네 단계다.
- 맥에서 iPhone Mirroring을 열고 아이폰과 페어링한다.
- 시스템 설정 → 개인정보 보호 및 보안에서 터미널(또는 게이트웨이 앱)에 손쉬운 사용과 화면 기록을 허용한다.
- 화면 기록 권한을 준 뒤 터미널을 재시작한다. 이걸 빼먹으면 캡처가 계속 검게 나온다.
- 아이폰은 잠근 상태로 둔다. 잠금을 풀면 미러링이 끊긴다.
마지막 항목이 실사용에서 제일 걸린다. 내가 폰을 들고 잠금을 풀면 에이전트의 세션이 끊긴다. 반대로 말하면, 에이전트에게 폰을 맡기는 동안에는 폰을 건드리지 않는 습관이 필요하다. 문서도 잠금 해제가 미러링을 멈춘다고 명시한다.
안드로이드: adb와 접근성 트리
안드로이드 쪽은 요구사항이 훨씬 관대하다. 맥이든 리눅스든 윈도우든 상관없다. 대신 폰에서 개발자 옵션을 열어야 한다.
# 1) 폰: 설정 → 휴대전화 정보 → 빌드번호 7번 탭 → 개발자 옵션 → USB 디버깅 켜기
# 2) USB로 연결하고 폰 화면의 디버깅 허용 팝업 승인
phone-harness --doctor android
# 무선으로 붙일 때 (Android 11 이상)
phone-harness android pair 123456 # 폰에 뜬 6자리 코드
USB를 뺄 때는 무선 디버깅을 쓰면 된다. 같은 Wi-Fi에서 페어링 코드만 넣으면 선 없이 붙는다. 노트북을 들고 다니며 폰을 조작하는 상황이면 이쪽이 편하다.
아이폰과 갈리는 지점은 "무엇을 보고 판단하느냐"다. 아이폰은 OCR로 글자를 읽고 좌표를 추정한다. 안드로이드는 접근성 트리에서 요소의 정확한 텍스트·경계·리소스 ID를 받는다. 그래서 tap_ui()처럼 이름으로 요소를 집는 명령이 안드로이드에만 있다. 글자가 안 보이는 버튼도 리소스 ID로 찾을 수 있다는 뜻이다.
단, 접근성 트리를 노출하지 않는 화면도 있다. 그럴 때는 결국 스크린샷을 보고 다음 동작을 정해야 한다. OCR과 트리를 오가는 구조라고 이해하면 된다.
실제로 시키는 일 — 헬퍼 명령
CLI는 헬퍼를 미리 불러온 상태로 Python 코드를 받는다. 터미널에서 바로 실행해 볼 수 있다.
phone-harness <<'PY'
open_app("Notes")
tap_text("New Note")
type_text("hello from the harness")
print([o["text"] for o in ocr()][:10])
PY
에이전트에게는 이렇게 시키면 된다. "노트 앱을 열고 새 메모를 만들어 '내일 9시 회의'라고 적은 다음, 화면에 제대로 들어갔는지 확인해줘." 에이전트는 앱 열기 → 버튼 찾기 → 입력 → 화면 다시 읽기 순으로 스스로 판단한다. 각 동작 뒤에 화면을 다시 읽는 것이 이 도구의 기본 리듬이다.
| 헬퍼 | 하는 일 |
|---|---|
ocr() | 화면 글자와 탭 좌표 읽기 |
screenshot() | 현재 화면 캡처 |
open_app() | 설치된 앱 실행 |
tap_text() | 보이는 텍스트로 컨트롤 누르기 |
tap() / long_press() | 좌표로 탭·길게 누르기 |
type_text() | 포커스된 입력란에 문자열 입력 |
swipe() / scroll() | 스와이프·스크롤 |
scroll_collect() | 긴 목록을 끝까지 훑어 모으기 |
wait_stable() | 화면 변화가 멈출 때까지 대기 |
tap_ui() / back() | 안드로이드 전용, 접근성 요소 선택·뒤로 가기 |
실무에서 쓸 만한 작업은 세 부류다. 첫째, 반복 입력이다. 매일 같은 앱에 같은 형식으로 기록하는 일. 둘째, 긴 목록 수집이다. scroll_collect()로 끝까지 내리며 텍스트를 모으면 손으로 캡처하는 것보다 빠르고 누락이 적다. 셋째, 앱 상태 확인이다. "이 화면에 오류 팝업 떴어?" 같은 질문은 스크린샷 한 장으로 끝난다.
클라우드 폰 요금과 쓰는 법
폰이 없거나, 여러 대를 동시에 돌리거나, 내 폰을 자동화에 쓰기 싫을 때 쓰는 경로다. (Phone Harness 요금)
| 플랜 | 가격 | 포함 |
|---|---|---|
| Basic (클라우드 안드로이드) | 월 $0, 분당 5¢ | 시작 크레딧 $5, 앱·로그인 유지, 라이브 뷰어, MCP 서버 |
| Plus | 월 $20 | 1,000분 포함, 초과분 분당 4¢ |
| Cloud iPhone | 월 $80 (연 결제 $64), eSIM 포함 $100 | 실기기, 실번호, 분당 과금 없음 |
| Scale | 문의 | 전용 실기기 상시 점유, 다중 프로필, 프록시 |
과금 규칙에서 놓치기 쉬운 부분이 있다. 세션 시간에 프로비저닝 시간이 포함되고, 요금은 폰이 준비된 시점부터 시작된다. 세션을 끝내면 임시 폰과 앱 데이터가 삭제된다. 로그인을 유지하려면 "저장된 폰"으로 띄워야 한다는 뜻이다. (Cloud 개요)
phone-harness cloud login # 최초 1회, 브라우저에서 승인
phone-harness cloud ls # 계정의 폰과 진행 중인 세션 확인
phone-harness cloud start # 기본 안드로이드, 15분
phone-harness cloud stop
클라우드 아이폰은 HTTPS로 제어하기 때문에 맥 OS 버전과 무관하다. 인텔 맥이라 iPhone Mirroring을 못 쓰는 경우에도 이 경로는 열린다. 월 $80이 비싸 보이지만, 중고 아이폰을 사서 상시 켜두는 비용과 전기·관리 공수를 생각하면 숫자가 달라진다.
한계와 보안
기능 목록보다 못 하는 일을 먼저 확인하는 편이 시간을 아낀다.
- 멀티터치 제스처(핀치 줌 등), 카메라, Face ID 조작은 지원하지 않는다.
- DRM이 걸린 영상은 캡처되지 않는다. 넷플릭스 화면을 읽히려는 시도는 처음부터 막힌다.
- 아이폰의 백그라운드 제어는 macOS 비공개 API에 의존한다. 미러링 창이 다른 창에 가려지면 캡처가 흔들린다.
- 잠긴 안드로이드는 직접 풀어야 한다. adb 텍스트 입력은 ASCII만 가능해서 한글은 그대로 타이핑되지 않는다.
마지막 항목은 한국 사용자에게 실제로 아프다. 한글 검색어를 앱에 넣어야 하는 작업이라면, 한글 입력은 클립보드 붙여넣기나 앱 자체의 최근 검색어를 쓰는 쪽으로 우회해야 한다. adb의 input text가 ASCII만 받는 것은 도구의 버그가 아니라 안드로이드 쪽 제약이다.
보안은 더 진지하게 봐야 한다. Phone Harness는 폰에 설치되는 앱이 아니라 내 컴퓨터에서 도는 프로그램이다. 에이전트가 쓴 Python이 내 계정 권한으로 실행되고, 그 코드가 실제 폰의 실제 앱을 건드린다. 결제·송금·삭제가 가능한 앱이 로그인된 폰이라면 위험도 그만큼 크다.
그래서 승인 게이트를 끄면 안 된다. OpenClaw 플러그인은 기본값이 "매 호출 승인"이고, 자동 실행(classifierAutoRun)은 꺼져 있다. 켜면 분류기가 "폰만 건드리는 코드"라고 판단한 스크립트를 묻지 않고 실행하는데, 문서 스스로 이 분류기가 휴리스틱이라 우회될 수 있다고 적는다. 그리고 샌드박스 세션에는 이 도구가 아예 주어지지 않는다. 플러그인이 게이트웨이 안에서 돌기 때문에, 샌드박스 밖인 내 맥에서 스크립트가 실행되기 때문이다.
내가 막혔던 곳
첫 번째 벽은 내 맥이었다. 아이폰 경로를 쓰려고 보니 요구사항이 macOS 15 이상에 Apple silicon 또는 T2였다. 내 장비에서 확인한 값은 이렇다.
$ sw_vers
ProductVersion: 13.7.8 # Ventura, macOS 15 미만
$ sysctl -n machdep.cpu.brand_string
Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz # T2 칩 없음
$ ls -d "/System/Applications/iPhone Mirroring.app"
No such file or directory # 미러링 앱 자체가 없음
세 줄이 동시에 걸린다. OS가 낮고, 칩이 T2가 아니고, 미러링 앱이 설치조차 되어 있지 않다. 이 조합에서는 iPhone Mirroring을 켜는 것부터가 불가능하니, Phone Harness 이전에 Apple 쪽에서 막힌 셈이다. 결론은 두 가지였다. 안드로이드 실기기로 가거나, 클라우드 아이폰을 쓰거나.

내 맥에서 직접 확인한 결과다. OS 버전, 칩, 미러링 앱 세 가지가 동시에 걸려 아이폰 경로는 시도조차 할 수 없었다.
위 화면은 실제로 내 맥에서 돌린 점검 결과를 그대로 옮긴 것이다. 세 개의 조건이 동시에 어긋나면 아이폰 경로는 시도조차 할 수 없다.
두 번째 벽은 Python 버전이었다. 이 맥의 기본 python3는 3.9.6인데 Phone Harness는 3.10 이상을 요구한다. uv도 없었다. 이때 시스템 파이썬을 건드리는 대신 uv를 새로 깔고 3.12를 따로 받는 쪽을 택했다. 시스템 파이썬에 직접 패키지를 넣으면 나중에 다른 스크립트가 깨진다. 이 맥에서 Python을 여러 버전으로 쓰는 방법은 Python 가상환경 venv 만들기에 정리해 두었다.
세 번째는 권한이었다. 손쉬운 사용과 화면 기록을 켜고도 캡처가 계속 검게 나왔다. 원인은 터미널을 재시작하지 않은 것이었다. 화면 기록 권한은 앱이 새로 뜰 때 반영된다. 권한을 준 뒤에는 터미널을 완전히 종료했다가 다시 열어야 한다.
네 번째는 승인 창이었다. 스크립트를 길게 쓰면 승인 요청이 아예 오지 않는다. 처음엔 버그인 줄 알았는데, 500자 제한 때문에 긴 스크립트는 승인 화면에 전문을 못 보여줘서 거부되는 구조였다. 지금은 "앱 열고 → 읽고 → 다음 판단"처럼 잘게 끊어서 시킨다. 폰 상태는 호출 사이에 유지되므로 쪼개도 결과는 이어진다. 에이전트를 다루는 기본기는 AI 에이전트란과 Claude Code 설치·사용법에 있다.
참고 자료
- Phone Harness 공식 사이트 (기능, 클라우드, 요금표)
- GitHub — phone-harness (설치, 헬퍼, 지원 범위)
- Phone Harness 문서 (Cloud API, 세션 과금 규칙)
- PyPI — phone-harness 0.3.3 (버전, Python 3.10 이상)
- OpenClaw 통합 README (phone_exec, 승인, 샌드박스 제한)
- Apple — iPhone Mirroring 요구사항 (macOS 15, Apple silicon/T2, iOS 18)
- ScriptByAI — Phone Harness 정리 (헬퍼 표, 한계 정리)
'IT' 카테고리의 다른 글
| 멀티모달 AI란 — 이미지 한 장이 토큰 1296개가 되는 이유 (0) | 2026.11.05 |
|---|---|
| 컨텍스트 윈도우란 — 1M 토큰이 1M처럼 안 쓰이는 이유 (0) | 2026.11.04 |
| 할루시네이션 뜻 — AI가 자신 있게 틀린 답을 말하는 이유 (0) | 2026.11.03 |
| LLM wiki 구축 — 100명 조직은 사람 수가 아니라 질문 경계로 나눈다 (0) | 2026.11.03 |
| LLM wiki란? RAG 차이 — 카파시 위키 방식, 잘 만든 RAG와 같이 쓰는 법 (0) | 2026.11.03 |



















