Claude Code를 안드로이드 태블릿에 붙이려는데, 음성비서 앱은 어디부터 만들까?
PC에서 쓰던 개인 음성비서를 안드로이드 태블릿으로 옮기려 했다. PC 버전은 호출어(hey_jarvis)를 듣고, 들은 문장을 claude -p(Claude Code를 한 번 실행해 답만 받는 명령)에 넘기고, 받은 답을 음성으로 읽어주는 Windows용 Python 프로그램이다. 목표는 충전 거치해 둔 태블릿이 항상 귀를 열어두는 앱이었지만, Claude Code를 어디서 실행할지와 앱이 무엇을 맡을지가 뒤섞여 무엇부터 만들지 정리해야 했다.
결론
앱은 귀·입을 맡고, 답을 만드는 두뇌는 인터페이스 뒤로 분리한다. 첫 버전에는 실제 Claude 연결 대신 MockBrain을 둔다. 이 대화에서 정리한 출발점이다. MockBrain은 들은 문장을 되돌려주거나 미리 정한 답을 내는 대역으로 제안됐다.
두뇌가 태블릿 안(Termux)에 있든 PC 서버에 있든, 앱 입장에서는 "텍스트 한 줄 보내고 텍스트 한 줄 받기"로 똑같다. 그래서 귀·입 부분은 어느 쪽으로 가든 버려지지 않는 작업이다.
제안된 첫 버전의 흐름은 다음과 같다. 실제 구현 코드가 아니라 설계 요약이다.
앱(Foreground Service): 마이크 상시 → 호출어 감지 → 음성을 텍스트로 변환
↓
BrainClient.ask(text)
↓
MockBrain의 정해둔 응답
↓
앱: 응답 텍스트를 음성으로 읽기 + 상태·로그 표시
실제 연결 후보는 TermuxBrain과 HttpBrain으로 남겼다. 다만 여기서 확인된 것은 설계 방향까지다. 기록은 빌드·설치 환경을 정해야 한다는 답변으로 끝나며, 앱을 만들거나 태블릿에서 실행한 결과는 담겨 있지 않다.
상황
처음 계획은 태블릿이 호출어 감지·음성 인식(STT)·음성 출력(TTS)만 하고, 인식한 텍스트를 PC로 보내 답을 받는 구조였다. 그런데 PC를 거치지 않고 태블릿 안에서 Claude Code까지 돌리는 방향으로 요구가 바뀌면서 구조가 복잡해졌다.
걸림돌은 Claude Code가 Node.js로 된 명령줄 프로그램이라는 점이다. 안드로이드 앱(APK)은 Java/Kotlin 세계라 claude 실행 파일을 품을 수 없다. 그래서 안드로이드용 리눅스 터미널 앱인 Termux에 Node.js와 Claude Code를 설치하고, 직접 만든 네이티브 앱이 Termux에 "이 문장을 claude에 넣고 결과를 달라"고 시키는 구조가 제안됐다. 앱이 Termux에 일을 시키는 방법으로는 RUN_COMMAND 인텐트가 언급됐다.
이렇게 나눈 책임은 두 가지다. 호출어 감지, STT, TTS, 화면은 앱 쪽에 두고, 질문 텍스트를 받아 응답 텍스트를 만드는 부분은 별도로 둔다.
증상
이번 사건의 증상은 실행 오류가 아니라 구조에 대한 혼동이었다. 먼저 "termux 를 이용하면 앱 개발이 되는건 아닌셈인가?"라는 질문이 나왔고, 이어 앱이 "termux 에 돌고 있는 claude code"로 전달하는 것인지 되물었다. 앱 개발의 범위와, 무엇이 상시 대기하는지가 아직 분명하지 않았던 지점이다.
전환점은 "난 앱이 좀 궁금한거라서"라는 말이었다. 듣고 말하는 것은 앱에서 하고 두뇌 처리 위치만 달라진다는 점을 이해한 뒤, 두뇌를 목킹하고 앱부터 올려볼 수 있는지로 요청이 좁혀졌다.
원인
대화를 가로막은 것은 듣고 말하는 앱을 만드는 일과 실제 답변 엔진을 연결하는 일을 한 덩어리로 생각한 것으로 읽힌다. Termux는 앱 개발을 대신하는 것이 아니라, 앱이 혼자 못 하는 한 가지(Claude Code 실행)만 메우는 보조 장치다. 두 책임을 나누자 실제 엔진의 위치를 결정하지 않고도 앱부터 만들어보자는 요청이 나왔다. 이는 발화 흐름에 대한 해석이며, 실행 장애의 원인을 찾아낸 사례는 아니다.
또한 이때 제안된 Termux 연결안에서 Claude Code는 계속 대기하는 서버가 아니었다. 평소에는 설치만 돼 있고, 앱이 문장을 넘길 때마다 claude -p를 새로 실행하고 응답 후 끝내는 방식으로 설명됐다. 상시 음성 대기는 앱의 마이크가 맡는다. 이는 해당 설계안의 설명이지, Claude Code의 모든 실행 방식에 대한 단정은 아니다.
해결
해결은 구현 완료가 아니라 첫 개발 범위를 정한 것이었다. 두뇌를 interface로 분리하고 지금은 MockBrain, 나중에는 TermuxBrain 또는 HttpBrain을 연결하는 안이다. 앱은 구체적인 실행 위치 대신 질문과 응답을 주고받는 경계만 바라보도록 제안됐다.
첫 앱에는 마이크를 상시 켜두는 Foreground Service, 호출어 감지(PC와 같은 openWakeWord hey_jarvis 모델), SpeechRecognizer를 이용한 음성 인식, BrainClient.ask(text), TextToSpeech를 이용한 음성 출력, 현재 상태(대기중/듣는중/처리중)와 인식·응답 로그 화면이 제안됐다. 이 목록은 구현·검증된 구성표가 아니라 만들려던 범위다.
설치 준비는 별도 과제로 남았다. 개발 PC를 확인한 결과 JDK는 16이라 최신 안드로이드 빌드에 필요한 17 이상을 새로 깔아야 하고, adb, Android SDK, Android Studio, Gradle은 없다고 보고됐다. 앱 소스는 작성할 수 있어도 APK로 빌드해 태블릿에 올리려면 툴체인부터 갖춰야 한다. 원본의 환경 확인 명령 출력은 기록에 없으므로 여기서는 보고된 상태까지만 인용한다.
확인하지 못한 것
이 기록에는 태블릿에서 Claude Code를 실행한 결과, 앱 설치 결과, 상시 음성 감지 시험 결과가 없다. 따라서 MockBrain으로 앱 검증이 성공했다거나 실제 엔진으로 교체해 동작했다고 결론 내릴 수 없다.
RUN_COMMAND와 SpeechRecognizer도 각각 연결 방식과 음성 인식 후보로 언급됐을 뿐이다. 이 기사에서는 전자를 유일한 통신 경로로, 후자를 항상 로컬에서 동작하는 인식기로 단정하지 않는다. 해당 성질을 시험한 결과가 이번 기록에 없기 때문이다.
취재 후기 — 귀와 입부터 만들어보자는 결정
설계 대화를 네 사람의 작업 회의로 재구성했다. 실기기 재현 장면은 없고, 환경 관찰은 개발 PC 확인 결과로 제한했다.
claude -p로 답을 받아 읽어주는 음성비서 있잖아. 이걸 충전 거치한 태블릿에서 항상 듣게 만들고 싶어. PC 없이 태블릿 혼자서 Claude Code까지 돌리는 걸로. claude -p를 새로 실행해서 답이 나오면 끝나. 상시로 깨어 있는 건 앱의 마이크뿐이야. interface, 그러니까 여러 구현이 똑같이 따르는 약속으로 빼두는 거야. 지금은 MockBrain이 "○○라고 하셨네요"처럼 들은 말을 돌려주고, 나중엔 TermuxBrain이나 PC에 붙는 HttpBrain으로 바꿔 끼우면 돼. BrainClient.ask(text), 글자를 소리로 읽는 TTS, 그리고 상태·로그 화면이야. 어느 두뇌로 가든 이 부분은 안 버려져.