
ESP32-iPhone-agent는 약 7달러짜리 ESP32-S3 보드와 아이폰 앱을 연결해 AI 모델이 실제 아이폰을 조작하도록 하는 오픈소스 프로젝트다. 컴퓨터나 탈옥은 필요 없지만, 아이폰에는 iOS 18 이상과 셀룰러 데이터가 필요하다.
보드와 아이폰 앱으로 작동하는 방식
최신 버전에서는 ESP32-S3 보드가 에어플레이(AirPlay) 수신기와 USB 마우스 역할을 맡고, 같은 아이폰에 설치한 앱이 화면을 분석하고 조작 명령을 만든다. 이전 버전은 Mac 또는 Linux 컴퓨터에서 UxPlay와 파이썬 서버를 실행해야 했다. 이 버전은 v0.1.0 태그와 legacy 브랜치에 남아 있으며, 자세한 내용은 레거시 버전 문서에서 볼 수 있다.
예시 작업은 “오전 8시에 월요일과 화요일마다 반복되는 알람을 설정하고 저장해”라는 요청이다. 에이전트는 앱을 벗어나 시계 앱을 열고, 시간 입력 휠을 조작한 뒤 반복 요일을 선택해 저장한다. 저장소는 이 장면이 v0.1.0에서 촬영됐지만 작업 내용은 같다고 설명한다.
작동 과정은 다음과 같다.
- 화면을 보는 과정에서 보드는 자체 와이파이 핫스폿을 열고, 아이폰의 화면 미러링 목록에
ESP32 Agent로 표시된다. 아이폰은 화면을 H.264 스트림으로 보내며, 보드는 이를 디코딩하지 않고 블루투스 저에너지(BLE)를 통해 앱으로 전달한다. 아이폰은 보드 핫스폿에 연결된 동안에도 셀룰러 데이터를 사용해 모델에 접속한다. - 조작은 USB 휴먼 인터페이스 장치(HID) 마우스와 키보드로 이뤄진다. 보드는 표준 USB 마우스와 키보드로 동작한다. 아이폰에서 AssistiveTouch를 켜면 화면 포인터를 움직일 수 있어 클릭은 탭으로, 드래그는 스와이프로 작동한다.
- 아이폰 앱은 스트림을 디코딩하고, 화면 캡처를 OpenAI 호환 비전 모델에 보낸다. 앱에는 계획기와 실행기가 있으며 탭, 스와이프, 그리기, 입력, 키 누르기, 홈 화면 이동, 작업 완료 등의 명령을 수행한다. 작업 중 앱은 백그라운드에서 실행되고 다이내믹 아일랜드에 진행 상황을 표시한다.
- 포인터 위치는 상대적으로 추적된다. 앱은 포인터를 화면 모서리로 되돌리고, 정확한 탭을 하기 전 포인터를 조금 움직여 화면에서 위치를 확인한 뒤 빗나간 지점을 보정한다. 각 동작 뒤에는 화면이 안정될 때까지 기다리고, 화면이 바뀌었는지 모델에 전달한다. 보드나 핫스폿, 미러링 연결이 끊기면 실행을 멈췄다가 같은 단계에서 다시 시작한다.
- 각 실행 기록은 아이폰에 저장된다. 탭과 스와이프 표시를 화면 위에 겹쳐 단계별로 재생할 수 있다.
하드웨어와 설치 조건
| 구성 요소 | 조건 |
|---|---|
| ESP32-S3 보드 | Seeed Studio XIAO ESP32S3 일반형(PSRAM 8MB, Sense 및 Plus 모델 제외)에서 시험했다. 가격은 약 7달러다. USB-C 포트에 네이티브 USB가 있고 PSRAM을 갖춘 ESP32-S3라면 작동할 수 있다. |
| 아이폰 | iOS 18 이상과 셀룰러 데이터가 필요하다. 와이파이는 보드 핫스폿에 연결되므로 모델 접속에는 셀룰러 데이터를 사용한다. USB-C 모델은 보드에 직접 연결하고, 라이트닝 모델은 Lightning to USB Camera Adapter가 필요하다. 아이폰이 보드에 전원을 공급한다. |
| 비전 모델 | 이미지를 받을 수 있는 OpenAI 호환 채팅 API가 필요하다. 클라우드 API나 자체 서버를 사용할 수 있다. |
| Mac과 Xcode | 보드 플래시와 앱 빌드에 한 번 필요하다. 실행 중에는 필요하지 않다. |
보드를 플래시하려면 Mac에 연결하고 arduino-cli, ESP32 코어 3.3.x, NimBLE-Arduino 2.5.x를 설치한다. 그다음 다음 명령을 실행한다.
arduino-cli lib install "NimBLE-Arduino@2.5.1"
hardware/flash.sh # optional: [serial port] [--debug]
보드를 플래시할 때는 항상 flash.sh를 사용해야 한다. 이 스크립트가 hardware/hid_bridge/nimble_cfg.h에 설정된 BLE 버퍼 크기를 적용한다.
앱을 설치하려면 설정 파일을 복사하고 DEVELOPMENT_TEAM과 IA_BUNDLE_ID를 입력한 다음 Xcode에서 프로젝트를 열어 아이폰에 IPhoneAgent 스킴을 실행한다.
cp ios/Config/Local.xcconfig.example ios/Config/Local.xcconfig # set DEVELOPMENT_TEAM and IA_BUNDLE_ID
open ios/IPhoneAgent.xcodeproj # run the IPhoneAgent scheme on your iPhone
프로젝트는 ios/project.yml에서 XcodeGen으로 생성한다. 명령은 cd ios && xcodegen이다. 무료 Apple ID로 앱에 서명할 수 있지만 7일마다 다시 서명해야 한다. 핫스폿에 한 번에 연결하는 기능에는 유료 계정의 Hotspot Configuration 권한이 필요하다. 이 권한이 없으면 앱이 핫스폿 비밀번호를 보여주고 사용자가 직접 연결해야 한다.
앱 설정과 작업 실행
보드를 아이폰에 연결하고 ESP32 Agent 앱을 열면 앱이 네 단계의 설정을 안내하고 각 단계를 직접 확인한다.
- 보드와 블루투스로 페어링한다.
- 보드 와이파이에 연결한 뒤 제어 센터에서 화면 미러링을 열고
ESP32 Agent를 선택한다. - AssistiveTouch를 켠다. 앱이 포인터를 자동으로 보정한다.
- 모델 엔드포인트와 키를 입력한다. 키는 키체인에 저장된다.
설정을 마치면 “설정을 열고 와이파이로 이동해”와 같은 목표를 입력하고 시작을 누른다. 다이내믹 아일랜드에서 중단하거나 앱으로 돌아올 수 있다. 저장한 작업은 Siri, 단축어, 위젯, 제어 센터에서도 실행할 수 있다.
앱은 vLLM, SGLang, llama.cpp, Ollama, 클라우드 API 등 이미지 입력을 지원하는 OpenAI 호환 비전 엔드포인트를 사용할 수 있다. 엔드포인트의 모델 목록을 불러와 모델을 선택하며, 사용자가 모델을 지정하거나 계획기와 실행기에 서로 다른 모델을 설정할 수도 있다. 프롬프트는 prompts/에 일반 텍스트로 저장되고 앱에 포함된다. 프롬프트를 수정한 뒤 앱을 다시 빌드하면 된다.
프로젝트는 두 대의 DGX Sparks에서 제공하는 nvidia/Qwen3.8-Flash-Next-NVFP4로 개발됐다. 관련 구성은 TensorFold 저장소에 공개돼 있다.
제약과 프로젝트 자료
BLE 대역폭은 약 300~500kbps다. 이에 따라 화면은 480×1040 해상도, 초당 최대 5프레임으로 미러링되며 각 단계에는 몇 초가 걸린다. 저장소는 이 시간의 대부분이 모델 처리에 쓰인다고 설명한다.
iOS는 암호 입력 화면, Apple Pay, DRM 영상 등 일부 화면을 미러링하지 않는다. 에이전트는 이런 화면을 볼 수 없으며, 아이폰이 잠기면 미러링도 중단된다. 작업 중 아이폰 와이파이는 보드 핫스폿에 연결돼 인터넷에 접속할 수 없고, 모델에는 셀룰러 데이터로 연결한다. 앱은 아이폰에서 앱을 나가게 하는 비공개 iOS API인 suspend를 사용한다. 저장소는 자체 빌드 앱에서는 사용할 수 있지만 앱스토어 출시 전에는 대체해야 한다고 밝힌다. 키보드 입력은 ASCII만 지원하며 가로 화면 앱은 아직 지원하지 않는다.
로드맵에는 가로 화면 앱 지원, 중국어 병음 키보드 입력과 같은 비ASCII 문자 입력, 모델 호출 한 번에 여러 동작을 처리하고 필요할 때만 포인터를 확인해 단계를 빠르게 하는 작업이 포함돼 있다.
프로젝트는 앱의 SwiftUI 코드와 BLE 연결, H.264 디코딩, 에이전트, 설정, 실행 기록, 라이브 액티비티와 위젯을 ios/에 둔다. 프롬프트는 prompts/, Arduino 기반 ESP32-S3 펌웨어와 플래시 스크립트, 호스트 테스트 및 Mac BLE 테스트 도구는 hardware/에 있다. BLE 프로토콜과 이전 버전 설명은 docs/, 현재 버전에서 사용하지 않는 이전 컴퓨터 측 서버는 server/에 있다. 아이폰 앱 없이 디버깅하려면 Mac에서 BLE를 통해 앱 역할을 수행하는 hardware/tools/board_test.py를 사용할 수 있다. 자세한 내용은 도구 문서와 BLE 프로토콜 문서를 참고하면 된다.
저장소는 소유하거나 사용할 권한이 있는 기기와 계정만 자동화하고 관련 앱의 이용 약관을 지키라고 안내한다. 에이전트는 사용자를 대신해 조작하므로 실행을 지켜보고 중지 버튼을 가까이 두어야 한다. 이슈와 풀 리퀘스트는 기여 안내를 참고할 수 있으며, 보안 제보는 보안 정책에 안내돼 있다.
관련 프로젝트와 차이점은 다음과 같다.
| 프로젝트 | 접근 방식 | 이 프로젝트와의 차이 |
|---|---|---|
| VersaiOS | UxPlay 미러링, ESP32-S3 블루투스 마우스, 비전 모델 | 컴퓨터가 필요하고 지시 하나에 한 번 탭한다. |
| ja1chen/actell | 애플 CoreDevice 디버그 채널을 이용한 아이폰 에이전트 앱 | 개발자 모드와 Developer Disk Image가 필요하다. |
| AidenAI-IO/aiden-firmware | HDMI 캡처, USB 키보드·마우스, 멀티모달 모델 | 캡처 하드웨어가 필요하며 주로 안드로이드를 대상으로 한다. |
| yoyicue/glassbox | PicoKVM HDMI 캡처와 USB HID | macOS 컨트롤러와 PicoKVM을 사용한다. |
| boboabw/phone-agent | ESP32-S3 블루투스 HID와 AssistiveTouch, 아이폰 에이전트 앱 | 이 프로젝트와 가장 비슷하다. ESP32-iPhone-agent는 보드의 에어플레이로 화면을 가져오는 기능도 제공한다. |
| VKCOM/devicehub | iOS 기기 팜용 ESP32 블루투스 마우스 | 기기 팜 도구이며 AI 에이전트는 없다. |
mobile-mcp와 Midscene처럼 WebDriverAgent/XCUITest를 사용하는 도구는 Mac과 코드 서명이 필요하다.
프로젝트는 MIT 라이선스를 사용한다. 단, UxPlay에서 포팅한 hardware/hid_bridge/src/airplay/는 GPL-3.0 라이선스이며, 이를 링크하는 펌웨어 바이너리도 GPL-3.0으로 배포된다. 자세한 내용은 MIT 라이선스와 AirPlay 코드의 GPL-3.0 라이선스에서 확인할 수 있다. 프로젝트는 UxPlay, NimBLE-Arduino, Arduino ESP32 코어, TinyUSB를 사용한다.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요