← 전체 글 보기

로봇 음성 스택을 플러그인으로 분리하기: STT/TTS 교체 비용 줄이는 아키텍처

로봇 음성 인터랙션은 모델 하나 잘 붙인다고 끝나지 않는다. 마이크, 스피커, 네트워크, 엔진 교체, 현장 노이즈까지 모두 고려해야 한다.

이 글은 STT/TTS 기반 로봇 어시스턴트를 플러그인 구조로 설계한 이유와 효과를 정리한다.

문제 정의

선택

핵심 컴포넌트를 분리했다.

이 분리는 기능 확장보다 운영 안정성을 위한 선택이었다.

플러그인 인터페이스

class STTProvider:
    def transcribe(self, audio_chunk: bytes) -> str: ...

class TTSProvider:
    def synthesize(self, text: str) -> bytes: ...

엔진별 포맷 차이, 인증 방식, timeout 정책은 어댑터 내부에 격리했다. 상위 레이어에서 공급자별 분기문이 늘어나지 않게 한 것이 핵심이다.

효과

운영 체크리스트

장애 격리 전략

플러그인 경계가 명확하면 음성 엔진 한 곳의 장애가 대화 시스템 전체 중단으로 번지는 것을 막을 수 있다.

오디오 포맷 표준화

엔진마다 입력 포맷이 달라서, 포맷 변환을 호출부에서 처리하면 오류가 반복됐다.

그래서 내부 표준 포맷(예: PCM 16kHz mono)을 고정하고, 각 엔진 어댑터에서만 변환하도록 경계를 통일했다. 이 결정이 디버깅 시간을 가장 크게 줄였다.

배포 전략

플러그인 단위 버전 배포를 지원해, 엔진 교체를 전체 앱 배포와 분리했다.

덕분에 특정 공급자 장애가 발생해도 핵심 대화 플로우를 건드리지 않고 부분 롤백이 가능해졌다.

참고 및 인용

참고: ROS pluginlib은 런타임 플러그인 로딩으로 구현 결합도를 낮추는 표준 메커니즘을 제공한다. pluginlib

참고: OpenAI Speech-to-Text 가이드는 플러그인 공급자 구현 예시 중 하나로, 입력 포맷/지연/정확도 트레이드오프를 설명한다. Speech to text

참고: W3C SSML 1.1은 엔진별 차이를 줄이기 위한 음성 합성 마크업 표준으로, TTS 공급자 교체 시 호환 기준으로 활용된다. Speech Synthesis Markup Language (SSML) Version 1.1