400ms 이하 음성 AI 구현: WebRTC와 FastAPI를 서버리스 Cloud Run에 배포하여 확장하기
요약
실시간 음성 AI 에이전트 구축의 핵심은 400ms 이하의 초저지연 통신입니다. 기존의 WebSocket/HTTP 스트리밍 방식은 순차적 블로킹 구조로 인해 지연 시간이 길어 대화 흐름을 깨뜨립니다. 본 글에서는 WebRTC와 FastAPI, Cloud Run을 활용하여 이 문제를 해결하고, 양방향 인터럽트가 가능한 AI 스크리닝 엔진 구축 방법을 제시합니다.
핵심 포인트
- WebRTC는 UDP 기반 전송으로 Head-of-line blocking 문제 없이 실시간 오디오 스트리밍에 최적입니다.
- FastAPI와 WebRTC를 결합하여 비용 효율적인 서버리스 환경에서 복잡한 AI 음성 에이전트를 구현할 수 있습니다.
- 진정한 양방향 통신을 통해 사용자가 AI가 말하는 도중에 말을 시작하는 '바지인(barge-in)' 경험을 제공합니다.
AI 기술 면접관을 구축하는 것은 독특한 물리적 문제를 제시합니다. 인간 엔지니어가 생각하느라 잠시 멈추면, 그들은 면접관이 기다려주기를 기대합니다. 만약 지원자가 잘못된 방향으로 전개되면, 그들은 면접관이 부드럽게 끼어들어 주기를 기대합니다.
이러한 자연스러운 대화 흐름을 달성하려면 400ms 이하의 지연 시간(latency)과 풀-듀플렉스(full-duplex) 통신이 필요합니다. 표준 생성형 AI(generative AI) 래퍼는 순차적이고 블로킹(blocking) 아키텍처에 의존하기 때문에 여기서 실패합니다.
여기서는 FastAPI, WebRTC, 그리고 GCP Cloud Run을 사용하여 높은 동시성 및 끼어들기(interruptible)가 가능한 AI 스크리닝 엔진을 구축하면서 표준 LLM 병목 현상을 어떻게 우회했는지 설명합니다.
병목 현상: 왜 WebSocket과 HTTP 스트리밍이 실패하는가
대부분의 음성 AI 파이프라인은 순차적인 '무전기(walkie-talkie)' 패턴을 따릅니다:
- 클라이언트가 오디오 청크를 녹음합니다.
- 클라이언트가 WebSocket 또는 HTTP를 통해 STT(Speech-to-Text) 서비스로 오디오를 전송합니다 (100~200ms 소요).
- 텍스트는 LLM으로 전달되어 응답을 생성합니다 (300~500ms 소요).
- 텍스트는 TTS(Text-to-Speech) 서비스로 전달됩니다 (100~200ms 소요).
- 오디오가 클라이언트로 스트리밍됩니다.
TTS 오디오가 브라우저에 도달할 때쯤이면, 총 종단 간 지연 시간은 1초에서 2초 사이에 놓이게 됩니다. 이 지연 임계점에서는 대화의 주고받음(turn-taking) 자체가 완전히 무너집니다. 지원자들은 에이전트와 말을 겹치거나 어색한 침묵 속에서 기다리게 됩니다.
WebRTC로 전환: 양방향 스트리밍
대화 지연 시간을 제거하기 위해, 우리는 전송 계층(transport layer)을 완전히 WebRTC로 전환했습니다. 원래 피어-투-피어 비디오 컨퍼런싱을 위해 설계된 WebRTC는 실시간 AI 오디오 전송의 황금 표준입니다.
WebRTC는 AI 음성 에이전트에게 세 가지 중요한 이점을 제공합니다:
– UDP 기반 전송: WebSockets(TCP 위에서 작동하며 Head-of-line blocking 문제 발생)와 달리, WebRTC는 패킷을 UDP를 통해 스트리밍합니다. 오디오 패킷이 손실되면 재전송을 기다리며 스트림을 멈추기보다 해당 패킷을 건너뜁니다.
– 내장 오디오 처리: WebRTC는 클라이언트 측에서 오디오가 네트워크에 도달하기 전에 에코 제거(echo cancellation), 자동 게인 제어(automatic gain control), 배경 소음 필터링 등을 네이티브하게 처리합니다.
– 진정한 양방향 인터럽트 가능성: 오디오가 동시에 양방향으로 흐르기 때문에, 백엔드는 수신되는 스트림에 대해 빠른 음성 활동 감지(Voice Activity Detection, VAD) 모델을 실행할 수 있습니다. 사용자가 AI가 말하는 동안 말을 시작하면, 서버는 즉시 TTS 스트림을 중단하고 청취하여 끊김 없는 '바지인(barge-in)' 경험을 만듭니다.
서버리스 FastAPI 백엔드
비용이 많이 드는 전용 미디어 서버를 운영하지 않고 WebRTC 시그널링을 처리하기 위해, 우리는 Python과 FastAPI를 사용하여 백엔드를 구축했습니다.
후보자가 Kovi 인터뷰 세션에 참여할 때:
- 클라이언트가 WebRTC Session Description Protocol (SDP) 오퍼를 생성합니다.
- FastAPI 백엔드는 표준 HTTP POST 요청을 통해 이 오퍼를 수신합니다.
- 백엔드는 연결을 협상하고, 미디어 스트림을 내부 STT/LLM/TTS 처리 파이프라인에 바인딩한 후, SDP 답변을 반환합니다.
- 그 시점부터 모든 오디오는 WebRTC 데이터 채널을 통해 직접 흐릅니다.
초기 HTTP 시그널링과 지속적인 UDP 미디어 스트림을 분리함으로써, 우리는 실시간 미디어를 지원하면서도 상태 비저장(stateless) API를 유지할 수 있습니다.
GCP Cloud Run에서의 확장성
GCP Cloud Run 같은 서버리스 환경에 WebRTC를 배포하는 것은 특정한 어려움을 야기합니다. WebRTC는 지속적이고 상태가 있는(stateful) UDP 연결을 필요로 하지만, 서버리스 컨테이너는 일시적(ephemeral)입니다.
우리는 세 가지 구성 변경을 통해 Cloud Run 배포를 최적화하여 이 문제를 처리했습니다:
세션 친화성 (Session Affinity)
WebRTC 피어 연결이 설정된 후, 모든 후속 시그널링 및 스트림 상태 로직 라우팅이 해당 특정 컨테이너 인스턴스에 고정되도록 Cloud Run에서 세션 친화성(sticky sessions)을 활성화했습니다.
콜드 스타트 완화 (Cold Start Mitigation)
Cloud Run 컨테이너는 시작하는 데 몇 초가 걸릴 수 있으며, 이는 초기 인터뷰 경험을 망칩니다. WebRTC 핸드셰이크가 밀리초 단위로 완료되도록 시그널링 서비스에 최소 인스턴스(min-instances = 1)를 활용했습니다.
CPU 할당 (CPU Allocation)
Cloud Run이 요청 처리 중일 때만 CPU를 할당하는 것이 아니라 항상 CPU를 할당하도록 구성했습니다. WebRTC는 들어오는 UDP 패킷을 처리하고 오디오 스트림 버퍼를 관리하기 위해 지속적인 백그라운드 CPU 사이클을 필요로 합니다. HTTP 요청 사이에 CPU가 제한되면, 오디오 파이프라인이 끊깁니다.
결과 (The Outcome)
네이티브 WebRTC 전송과 서버리스 FastAPI 백엔드를 결합함으로써, 이 아키텍처는 음성 AI의 전통적인 제약 사항을 완전히 우회합니다.
그 결과는 자연스러운 중단을 처리하고, 기술적 응답을 동적으로 처리하며, 오디오 품질 저하 없이 수천 건의 동시 엔지니어링 평가에 확장할 수 있는 인터뷰 환경입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기