top of page

[On-Device AI Chatbot] 4편: 챗봇의 귀와 입: 온디바이스 STT/TTS 통합기

최종 수정일: 5시간 전


챗봇의 귀와 입

온디바이스 STT/TTS 통합기


지난 3편에서는 거대 언어 모델을 스마트폰의 제한된 리소스에 맞게 압축하고, 모바일 NPU를 활용해 추론 속도를 끌어올리는 최적화 과정을 살펴보았습니다. 빠르고 똑똑하게 사고하는 '뇌(Brain)'를 기기 내부에 탑재하는 데 성공했다면, 이제는 사용자와 자연스럽게 상호작용할 수 있는 '귀와 입'을 달아줄 차례입니다.

모바일 환경에서 매번 긴 텍스트를 타이핑하는 것은 사용자 경험(UX) 측면에서 큰 제약이 됩니다. 따라서 TecAce 팀은 완벽한 오프라인 환경을 유지하면서도 음성으로 대화할 수 있는 멀티모달 인터페이스를 구현하기 위해 온디바이스 STT(음성 인식)와 TTS(음성 합성) 통합 작업에 착수했습니다.


1. 챗봇의 귀: 오프라인 STT (Speech-to-Text) 도입

보안과 프라이버시가 핵심인 이번 프로젝트의 특성상, 사용자의 음성 데이터 역시 클라우드 서버로 전송되어서는 안 됩니다. TecAce 팀은 초기 스프린트 단계에서 다양한 STT 솔루션을 비교 분석했습니다.


솔루션 검토 및 선정

  • 온라인/클라우드: Azure STT (정확도가 높고 빠르지만 오프라인/보안 요건에 불합격)

  • 오프라인 1: Vosk-Kaldi (가볍고 빠르지만, 문맥 인식 및 다국어 처리에서 아쉬움)

  • 오프라인 2: Whisper C++ (OpenAI의 Whisper 모델을 C/C++로 포팅한 버전)


최종적으로 정확도와 다국어 처리 능력이 가장 뛰어난 Whisper C++를 안드로이드 앱에 통합하기로 결정했습니다. 마이크 버튼을 누르면 즉시 백그라운드 노이즈를 필터링하며 사용자 음성을 청취하고, 발화가 끝나는 즉시 로컬에서 텍스트로 변환하여 LLM 프롬프트로 전달하는 파이프라인을 구축했습니다.


2. 챗봇의 입: 어떤 목소리로 대답할 것인가? (TTS)

STT를 통해 질문을 이해하고 LLM이 답변을 생성했다면, 이를 자연스러운 음성으로 읽어주는 TTS(Text-to-Speech)가 필요합니다.

TTS 솔루션 탐색과 한계 초기에는 안드로이드 OS에 내장된 네이티브 TTS를 활용하는 방안과, 보다 자연스러운 음성을 제공하는 서드파티 AI 오프라인 TTS(Kokoro 등)를 함께 검토했습니다. 가장 큰 기술적 장벽은 '합성 대기 시간(Latency)'이었습니다. LLM이 생성한 긴 답변 문장을 한 번에 TTS 엔진으로 넘길 경우, 음성을 합성하고 재생을 시작하기까지 너무 오랜 시간이 걸렸습니다. 이를 해결하기 위해 문장이나 문단 단위로 답변을 쪼개어(Chunking) 스트리밍하듯 순차적으로 음성을 재생하는 최적화 로직이 필수적이었습니다.

TTS Platform Research & Test
TTS Platform Research & Test

3. 모바일 환경의 늪: 예외 케이스와 UX 트러블슈팅

기기 내부에서 LLM, STT, TTS라는 무거운 세 가지 엔진이 동시에 돌아가다 보니, 앱 생명주기(Lifecycle) 및 메모리 관리와 관련된 다양한 버그들이 발생했습니다. 실제 v1.0.5 릴리즈를 준비하며 해결했던 대표적인 트러블슈팅 사례는 다음과 같습니다.


  • 앱 크래시 문제 (DeadObjectException): 세팅 화면을 오가거나 앱이 백그라운드로 전환될 때 TTS 엔진을 재초기화(Reinitializing)하는 과정에서 DeadObjectException이 발생하며 앱이 강제 종료되는 현상이 있었습니다. 안드로이드의 메모리 회수 정책과 TTS 서비스 간의 연결이 끊어지면서 발생하는 문제로, 생명주기에 맞춘 안전한 객체 해제와 예외 처리 로직을 보강하여 해결했습니다.


  • 무한 반복되는 챗봇의 혼잣말: 앱에서 홈 버튼을 눌러 바탕화면으로 나가거나 설정 페이지를 열었음에도, 챗봇이 생성된 답변을 끝까지 소리 내어 읽어주는(Background Playback) UX 결함이 발견되었습니다. 앱이 화면에서 사라질 때(onPause / onStop) 활성화된 TTS 재생을 즉각 중지하도록 생명주기 이벤트를 동기화했습니다. STT 역시 설정 화면에 다녀오면 이전 음성 인식이 반복해서 입력되는 버그를 잡아내어 상태 관리를 엄격하게 분리했습니다.


  • 'Stop 버튼' UI/UX 개선: LLM의 긴 답변을 중간에 끊고 싶을 때를 대비해 'Stop Speech' 버튼을 추가했습니다. 초기에는 텍스트 생성이 완료되면 음성 재생이 채 끝나기도 전에 중지 버튼이 사라지거나, 재생 도중 사용자가 새로운 질문을 던져도 이전 음성이 멈추지 않고 겹치는 문제가 있었습니다. 이를 개선하여 사용자가 인터럽트(새로운 음성 입력 시작)를 걸면 즉시 기존 TTS 출력을 멈추는 스마트한 대화 흐름을 구현했습니다.


결론: 진정한 '개인형 어시스턴트'의 완성

STT와 TTS를 성공적으로 온디바이스 환경에 통합함으로써, TecAce의 챗봇은 단순한 텍스트 메신저를 넘어 '비행기 모드에서도 음성으로 대화할 수 있는 진정한 AI 비서'로 거듭났습니다. 손에 물이 묻어 타이핑이 힘든 현장 작업자나 보안 시설 내에서도 자연스러운 음성 대화가 가능해진 것입니다.


다음 편 예고

"그렇다면 이 챗봇은 우리 회사의 업무나 내 개인적인 상황을 어떻게 이해하고 답변할까?" 아무리 모델이 똑똑하더라도, 사용자가 처한 특정 맥락이나 사내 규정을 모른다면 엉뚱한 답변을 내놓기 쉽습니다.

이어지는 [5편] 문맥을 이해하는 챗봇: RAG와 멀티 컨텍스트 구현에서는 외부 인터넷 연결 없이 오직 스마트폰 내부에 저장된 문서를 읽고 답변하는 로컬 RAG(검색 증강 생성) 기술과, 다양한 대화 주제를 넘나드는 멀티 컨텍스트 스위칭의 구현 과정을 상세히 다뤄보겠습니다.



댓글


bottom of page