AI 에이전트·운영Android

Alpine Agent CLI Client

신규 오프라인 설치에서 Python 패키지 3개가 더 필요했던 경험을 담았습니다. 정적 의존성 검사와 실제 Alpine 설치의 차이를 다듬은 Android CLI 클라이언트 제작기입니다.

AI Tools Lab · 소개 글 작성 · 수정

Alpine Agent CLI Client — 프로젝트 화면
Android의 Agent 선택 화면입니다. 앱 전용 Alpine Runtime에서 사용할 CLI와 준비 상태를 확인합니다.

오프라인 설치는 패키지를 넣는 것만으로 끝나지 않았습니다

Alpine Agent CLI Client에서는 Android 앱 전용 공간에 Alpine Runtime을 두고 공식 Codex·Grok CLI를 실행하도록 만들었습니다. 앱이 직접 모델 통신을 다시 구현하는 대신 각 CLI가 인증과 Provider 통신을 맡습니다. 화면 뒤에서 Python Gateway가 준비되어야 이 연결도 시작할 수 있습니다.

8월 16일에는 Gateway를 외부 다운로드 없이 시작할 Python 패키지 묶음을 준비했습니다. 처음 묶은 패키지는 18개였고 정적 의존성 검사는 통과했습니다. 하지만 완전히 새로 설치한 테스트 앱에서 Alpine의 오프라인 설치 사전 확인을 실행하자 추가 패키지가 필요했습니다.

이미 준비된 환경에서 실행하는 것과 빈 앱 공간에 필요한 파일을 갖추는 것은 다른 조건이었습니다. Runtime과 Python을 외부 다운로드 없이 준비하려면 새 설치에서 쓰는 패키지를 모두 포함해야 했습니다. 그래서 설치 화면 대신 패키지 묶음을 확인했습니다.

정적 의존성에 없는 설치 조건이 있었습니다

Alpine에는 일반 의존성 외에 install_if 조건으로 함께 선택되는 패키지가 있습니다. Python 묶음에는 pyc, python3-pyc, python3-pycache-pyc0 세 패키지가 더 필요했습니다. 처음 검사는 정적인 의존성 연결을 확인했지만 실제 설치기가 선택하는 전체 집합까지 포함하지 못한 것입니다.

저는 같은 공식 인덱스와 버전에서 세 패키지를 추가해 21개로 묶음을 다시 고정했습니다. 누락된 순간에 인터넷으로 받아오는 우회 경로는 넣지 않았습니다. 앱 내부 파일만으로 준비한다는 계약을 유지하려면 필요한 파일을 배포 구성에 포함해야 했기 때문입니다.

패키지 수가 늘었다는 사실보다 왜 늘었는지를 남기는 일이 중요했습니다. 일반 의존성만 훑는 검수와 실제 설치기의 선택을 확인하는 검수는 역할이 다릅니다. 이후에는 신규 공간에서 --no-network --simulate로 설치 선택을 확인하는 조건을 준비 과정에 포함했습니다.

아키텍처가 없는 패키지를 예외로 받아들였습니다

패키지 검사에도 수정할 부분이 있었습니다. 기기용 묶음은 aarch64를 대상으로 했지만 일부 패키지는 특정 CPU에 종속되지 않는 noarch였습니다. 모든 패키지가 aarch64여야 한다고 검사하면 정상 구성도 거절하게 됩니다.

저는 허용 범위를 aarch64와 noarch로 명시했습니다. 그렇다고 다른 기기용 파일을 모두 받아들이는 방식으로 풀지는 않았습니다. x86_64처럼 대상과 다른 아키텍처는 계속 거절합니다. 실제 묶음에 필요한 예외를 좁혀 넣은 선택입니다.

패키지마다 이름·버전·아키텍처·크기·SHA-256을 고정하고, 사용 조건과 다운로드 위치도 함께 기록했습니다. 파일 이름이 맞는 것과 내용이 맞는 것은 다르므로 앱을 만들 때 동일한 묶음인지 확인할 수 있어야 합니다. 준비하는 컴퓨터가 달라져도 무엇을 포함해야 하는지 읽을 수 있게 만든 부분입니다.

기동과 화면 준비를 따로 확인했습니다

오프라인 묶음은 당시 Samsung SM-S931N의 Android 16 신규 테스트 설치에서 확인했습니다. Alpine 안의 Python과 분리된 pyc 패키지, PRoot와 Gateway의 기동을 각각 살폈습니다. 과거에 설치된 앱의 화면이 열린다는 사실을 새 묶음의 검수로 대신하지 않았습니다.

앱의 조작 화면이 보이는 상태와 채팅을 처리할 backend가 준비된 상태도 나눴습니다. Agent·Model·Send 같은 조작 요소를 확인하는 것은 화면 준비이고, Runtime과 Gateway가 기대한 수로 살아 있는 것은 실행 준비입니다. 화면만 준비된 중간 상태를 전체 준비 완료로 표시하면 사용자 요청이 너무 일찍 들어갈 수 있습니다.

강제 종료 뒤 재실행도 같은 관점에서 확인할 조건입니다. 앱 프로세스가 다시 생기는 것과 Runtime이 다시 준비되는 시점은 다를 수 있습니다. 설치 검수는 첫 화면 캡처에서 끝내지 않고, 해당 앱의 생명주기와 실행 구성요소를 연결해서 봐야 했습니다.

오프라인 Runtime과 온라인 인증을 구분했습니다

이 작업의 오프라인 범위는 Runtime과 Python 준비입니다. 실제 AI 대화와 계정 인증까지 네트워크 없이 가능하다는 뜻은 아닙니다. 공식 CLI가 맡는 OAuth와 Provider 요청은 별도의 연결 조건을 가집니다.

앱과 Gateway가 CLI의 토큰이나 인증 파일을 읽어 복사하는 구조는 피했습니다. CLI 상태는 전용 작업 공간에 두고, Android와 Gateway 사이에는 앱 전용 통신 경계를 사용합니다. 모바일 화면이 생겼다고 인증의 소유권까지 앱으로 옮기지 않은 선택입니다.

배포용 서명도 별도 단계로 남겼습니다. 내부 테스트 APK의 기동과 공개 signed release의 인수는 같은 결과가 아닙니다. 외부 서명 입력과 인증서 확인이 준비되어야 공개 배포 후보를 만들 수 있습니다. 오프라인 설치가 확인되었다는 사실을 배포 전 과정의 완료로 확대하지 않았습니다.

최초 설치를 독립적인 검수 대상으로 남겼습니다

이 경험 이후 저는 Runtime을 붙이는 앱에서 기존 설치와 신규 설치를 따로 보게 됐습니다. 개발 중에는 이미 내려받은 패키지나 남아 있는 파일 때문에 누락이 보이지 않을 수 있습니다. 새 공간에서 설치기가 선택하는 파일을 확인해야 배포 묶음의 경계가 드러납니다.

같은 구성을 만들 때는 정적 의존성 확인, 네트워크 없는 설치 선택, 실제 기동, 강제 종료 뒤 복구를 나눠 검사하는 편이 좋습니다. 각각의 성공이 다음 단계의 성공을 자동으로 의미하지 않습니다. 실패한 지점을 알 수 있도록 출력과 상태도 분리해야 합니다.

Alpine Agent CLI Client에서 남기고 싶은 경험은 패키지 세 개를 더 넣은 결과보다 검사 조건을 바꾼 과정입니다. 설치기가 결정하는 구성과 앱이 준비되었다고 판단하는 조건을 실제 환경에 맞춰 좁혔습니다. 데스크톱 CLI를 모바일로 옮길 때는 채팅 UI보다 먼저 이 실행 기반을 설명할 수 있어야 했습니다.

개발 자료

프로젝트 링크

오프라인 최초 설치에서 드러난 Python 패키지 누락을 고치고, 실행 준비와 앱 표시를 나눠 검수했습니다.

원본 프로젝트 ↗ · 문의·정정 요청