실시간 인터럽트(끼어들기) 감지: 사람처럼 대화하는 음성 AI
상담 음성봇과 통화하다가, 답을 이미 알아챘는데 봇은 안내 멘트를 끝까지 읽어 내려가는 경험을 한 번쯤 해보셨을 겁니다. "네 알겠어요, 그건 됐고요" 하고 끼어들어도 봇은 아랑곳없이 자기 말을 마칩니다. 이 한순간에 사용자는 직감합니다. "아, 기계구나." 음성 AI의 자연스러움을 가르는 결정적 분기점은 발음의 품질이나 어휘가 아니라, 바로 이 끼어들기를 받아낼 수 있느냐입니다. 이번 글에서는 사용자가 봇의 말을 끊고 들어오는 바지인(barge-in)을 어떻게 감지하고, 진행 중이던 음성 출력을 어떻게 멈추고 다시 듣는 상태로 전환하는지를 정리합니다.
[시리즈] S2S·LLM 음성 에이전트 엔지니어링 63편 · 현재 3-1편
← 이전: 2-4 감정·톤 조절이 CS를 바꾸는 이유 / 다음 → 3-2 실시간 음성에 MCP가 필요한 이유
- 2-3 음성 토큰(Audio Token)이란
- 2-4 감정·톤 조절이 CS를 바꾸는 이유
- 3-1 실시간 인터럽트(끼어들기) 감지 (현재 글)
- 3-2 실시간 음성에 MCP가 필요한 이유
- 3-3 스트리밍 중 MCP 초고속 데이터 룩업
전체 목차 펼치기 (63편)
Part 1 — 음성 AI가 느린 이유: 레이턴시 진단 (4편)
- 1-1 AI 보이스봇이 답답한 이유 — Cascaded 레이턴시
- 1-2 1초의 벽 — 지연이 UX를 결정하는 이유
- 1-3 지연 줄이기 — 스트리밍·청크로 TTFT 단축
- 1-4 RAG 병목과 오디오 버퍼링 제어
Part 2 — 텍스트를 넘어: End-to-End S2S의 원리 (4편)
- 2-1 End-to-End S2S 작동 원리
- 2-2 OpenAI Realtime API vs 오픈소스 S2S
- 2-3 음성 토큰(Audio Token)이란
- 2-4 감정·톤 조절이 CS를 바꾸는 이유
Part 3 — 실시간 대화와 에이전트화: 인터럽트·MCP·도구 (5편)
- 3-1 실시간 인터럽트(끼어들기) 감지 (현재 글)
- 3-2 실시간 음성에 MCP가 필요한 이유
- 3-3 스트리밍 중 MCP 초고속 데이터 룩업
- 3-4 통화 중 외부 API 도구 호출
- 3-5 실시간 세션 관리 — 통화 맥락·고객 데이터
Part 4 — 인프라·세션·보안: 프로덕션 백엔드 (5편)
- 4-1 동적 컨텍스트 윈도우 관리
- 4-2 WebRTC·WebSocket 초저지연 음성
- 4-3 비동기 이벤트 루프와 동시 콜 처리
- 4-4 트래픽 스파이크를 견디는 확장성 설계
- 4-5 실시간 음성 보안 — 암호화·PII 마스킹
Part 5 — 운영·품질·평가: 에이전틱 워크플로우와 신뢰성 (7편)
- 5-1 에이전틱 워크플로우 — 응대를 넘어 완결로
- 5-2 상용화의 한계와 트러블슈팅
- 5-3 보이스 에이전트 평가(Eval) 설계
- 5-4 관측성(Observability) — 어디서 끊기나
- 5-5 가드레일과 환각 제어
- 5-6 상담사 전환(Handoff) 설계
- 5-7 프롬프트 A/B 테스트와 튜닝
Part 6 — 음성 경험 고도화·실전 통합: 한국어·UX·전화망·엣지 (5편)
- 6-1 한국어 음성 AI의 난관 — 존댓말·코드스위칭
- 6-2 턴테이킹과 시맨틱 VAD
- 6-3 보이스 페르소나 디자인
- 6-4 SIP·PSTN 전화망 연동
- 6-5 온디바이스·엣지 S2S와 프라이버시
Part 7 — S2S 도입 전략·구매 의사결정 (4편)
Part 8 — LLM 콜봇 PoC 현장 (6편)
- 8-1 LLM 콜봇 PoC — 검증의 갭
- 8-2 STT 정확도 93% 목표가 부족한 이유
- 8-3 금융 콜봇에서 소수점이 중요한 이유
- 8-4 TTFT 1.5초, 콜봇 스트리밍 파이프라인 설계
- 8-5 콜봇 SLM: 30B vs 70B 트레이드오프
- 8-6 PoC와 본사업 사이의 성능 괴리
Part 9 — 상담어시스트: 상담사 화면을 바꾸는 실시간 AI (7편)
- 9-1 상담어시스트란 무엇인가 — 실시간 STT가 상담사 화면을 바꾸는 구조
- 9-2 상담어시스트의 뼈대 — STT·인텐트·KMS 파이프라인
- 9-3 추천의 근거 — KMS·RAG 지식 그라운딩
- 9-4 통화 중 놓친 고지를 잡는 실시간 필수 안내 체크
- 9-5 AI가 상담 품질을 자동 채점하는 법 — AutoQA
- 9-6 신입 상담사에게 어시스트가 더 필요한 이유
- 9-7 온프레미스 상담어시스트 — GPU 제약과 모델 선택
Part 10 — 직접 만든 롤플레이 챗봇: RAG 에이전트 구축기 (8편)
- 10-1 왜 롤플레이 챗봇을 직접 만들었나
- 10-2 전체 아키텍처 한 장
- 10-3 RAG 파이프라인과 로컬 임베딩
- 10-4 멀티 LLM 백엔드 스위칭
- 10-5 AI 고객 페르소나 프롬프트 엔지니어링
- 10-6 퀴즈 풀 사전생성
- 10-7 대화가 끝나면 채점한다
- 10-8 혼자 쓰는 챗봇의 현실
Part 11 — KMS 실무 — 지식관리시스템의 설계와 운영 현실 (8편)
왜 끼어들기가 음성 AI의 결정적 분기점인가
그림 1. 사용자 발화가 시작되는 시점을 감지해 봇이 재생 중이던 TTS를 그 즉시 중단시킨다.
텍스트 채팅은 본질적으로 턴이 분리되어 있습니다. 한 사람이 메시지를 보내면 상대가 읽고 답합니다. 겹칠 일이 없습니다. 그러나 음성 대화는 다릅니다. 사람과 사람의 대화에서 화자 교대(turn-taking), 즉 한 사람의 말이 끝나고 다음 사람이 시작하기까지의 전이 간격(gap)은 평균적으로 200밀리초 안팎으로 알려져 있는데, 이는 상대의 말이 끝나는 지점을 미리 예측하지 않고서는 불가능한 속도입니다. 게다가 사람은 상대의 말을 끊고 들어오거나, 말하는 도중에 "응, 응" 하며 맞장구를 칩니다. 이 겹침과 끼어듦은 결함이 아니라 자연스러운 대화의 기본 문법입니다.
전통적인 음성봇은 이 문법을 무시했습니다. 봇이 안내 멘트를 재생하는 동안에는 마이크 입력을 아예 무시하거나, 사용자가 무슨 말을 해도 멘트가 끝난 뒤에야 처리했습니다. 이런 한 방향 진행은 사용자가 끼어드는 순간 곧바로 무너집니다. 끼어들기를 제대로 받아내는 일은 단순한 편의 기능이 아니라, 음성 에이전트가 "대화"로 인식되느냐 아니면 "녹음 재생기"로 인식되느냐를 가르는 핵심 역량입니다.
이 한계가 우연이 아니라 구조에서 비롯된다는 점이 중요합니다. STT-LLM-TTS를 차례로 잇는 캐스케이드(파이프라인형) 콜봇은 본질적으로 반이중(half-duplex), 즉 무전기와 같은 구조입니다. 무전기는 한쪽이 송신 버튼을 누르고 말하는 동안 상대의 소리를 듣지 못합니다. 캐스케이드 음성봇도 똑같습니다. 봇이 출력 스크립트를 재생하는 동안에는 듣는 채널, 즉 입력을 받는 리스닝 모듈이 사실상 닫혀 있습니다. 각 단계가 독립적인 모듈로 끊어져 순차로 넘겨지는 구조라, 출력이 끝나기 전에는 입력 경로가 활성화되지 않는 것입니다. 그래서 사용자가 중간에 말을 걸어도 봇은 그 소리를 받지 못하고, 받더라도 단순 에너지 임계값에 기댄 VAD가 오작동하기 쉬워 끼어들기가 구조적으로 막힙니다. 이것이 캐스케이드에서 바지인이 유독 까다로운 근본 이유입니다. 반대로 입력과 출력을 한 모델 안에서 동시에 다루는 풀 듀플렉스로 전환하면, 봇이 말하는 도중에 사람이 끼어들어도 즉시 듣기 모드로 넘어가 "말하고 듣고"가 유연하게 오가는 동적 대화 구조가 만들어집니다. 끊긴 발화의 맥락을 어떻게 정리하느냐는 별개의 문제로, 화자 교대(turn-taking)를 다루는 글에서 따로 짚습니다.
끼어들기 처리의 세 가지 신호: 무엇을 감지할 것인가
끼어들기 처리를 "사용자가 소리를 내면 봇을 멈춘다"로 단순화하면 반드시 실패합니다. 여러 케이스를 겹쳐 놓고 보면, 실제로 구분해야 하는 신호는 최소 세 가지로 수렴합니다.
- 발화 시작 자체: 사용자가 입을 열었는가. 이것은 음성 활동 감지(VAD)가 담당하는 1차 신호입니다.
- 의미 있는 끼어들기: 봇의 말을 실제로 끊으려는 의도가 있는 발화인가, 아니면 기침·잡음·짧은 소음인가.
- 백채널(backchannel): "네", "음", "아하" 같은 맞장구입니다. 사용자는 봇이 계속 말하기를 바라며 동의를 표하는 것일 뿐, 발화를 멈추라는 신호가 아닙니다. 이를 끼어들기로 오인하면 봇이 시도 때도 없이 멈춰 오히려 부자연스러워집니다.
즉 끼어들기 처리는 "소리 감지" 문제가 아니라 "끊을 의도 판별" 문제입니다. 이 재정의가 출발점입니다.
VAD 고도화: 단순 임계값을 넘어서
가장 단순한 VAD는 입력 오디오의 에너지(음량)가 임계값을 넘으면 발화로 간주하는 방식입니다. 구현은 쉽지만, 에어컨 소음이나 키보드 소리에도 반응하고, 조용히 말하는 사용자는 놓칩니다. 그래서 실무에서는 보통 여러 기법을 겹쳐 씁니다.
- 신경망 기반 VAD: 음성과 비음성을 학습으로 구분합니다. 공개된 경량 모델(예: Silero VAD 계열)이 널리 쓰이며, 잡음 환경에서 에너지 방식보다 견고합니다.
- 엔드포인트 디텍션(endpointing): 발화의 시작뿐 아니라 "끝"을 판단합니다. 사용자가 잠깐 숨을 고르는 침묵과, 말을 마친 침묵을 구분하는 것이 핵심입니다. 너무 빨리 끝으로 판단하면 말허리를 자르고, 너무 늦으면 응답이 굼뜨게 느껴집니다.
- 에코 캔슬레이션(AEC): 봇 스스로 재생한 음성이 마이크로 되돌아 들어와 "자기 목소리에 자기가 끊기는" 자기 인터럽트(self-interruption)를 막습니다. WebRTC의 AEC가 대표적이며, 풀 듀플렉스 설계에서는 사실상 필수입니다.
- 적응형 임계값과 홀드오버(hangover): 배경 잡음 수준에 맞춰 기준을 동적으로 조정하고, 짧은 무음 구간에서 발화가 끊겼다고 성급히 판단하지 않도록 일정 시간 상태를 유지합니다.
| 방식 | 강점 | 한계 | 주된 역할 |
|---|---|---|---|
| 에너지 기반 VAD | 매우 가볍고 지연이 거의 없음 | 잡음·작은 목소리에 취약 | 1차 빠른 게이팅 |
| 신경망 VAD | 잡음에 견고, 음성/비음성 분별력 | 약간의 연산·지연 추가 | 정밀 발화 감지 |
| 엔드포인트 디텍션 | 발화 종료 시점 판단 | 침묵 길이 튜닝 민감 | 턴 종료 판정 |
| 에코 캔슬레이션(AEC) | 자기 음성 되먹임 제거 | 환경·하드웨어 의존 | 자기 인터럽트 방지 |
이 네 가지는 경쟁 관계가 아니라 계층입니다. 가벼운 에너지 게이팅으로 1차 거른 뒤, 신경망 VAD로 정밀 판정하고, AEC로 자기 목소리를 솎아내며, 엔드포인터가 턴의 끝을 정하는 식으로 쌓아 올립니다.
양방향 스트리밍 중 생성 중단·재개 로직
끼어들기를 감지했다고 끝이 아닙니다. 핵심은 봇이 이미 말하고 있는 도중에 그 출력을 깔끔하게 멈추고 다시 듣는 상태로 넘어가는 것입니다. 무엇을 멈출지는 구조에 따라 다릅니다. 캐스케이드는 LLM이 만든 텍스트를 TTS가 음성으로 합성하는 2단계라서, TTS 합성을 중단하고 이미 클라이언트로 흘러간 재생 버퍼를 플러시하는 것이 핵심입니다. 반면 엔드투엔드 S2S는 모델이 오디오 토큰을 직접 생성·스트리밍하므로, 오디오 토큰 생성 자체를 취소하는 것이 곧 발화 중단입니다. 어느 쪽이든 음성 출력은 재생 측에 수백 밀리초 분량의 버퍼가 쌓여 있어, 단순히 생성을 멈춘다고 소리가 곧바로 그치지 않습니다.
처리 시퀀스는 대략 다음과 같습니다.
on_user_speech_detected(t):
if state == BOT_SPEAKING and is_real_interruption(t):
cancel_response_generation() # 1. 토큰/오디오 생성 중단
flush_playback_buffer() # 2. 재생 큐 즉시 비우기 (남은 소리 차단)
played_text = get_spoken_so_far() # 3. 사용자가 실제로 들은 지점 계산
truncate_assistant_turn(played_text) # 4. 컨텍스트를 들은 만큼만 반영
state = LISTENING # 5. 다시 듣기 상태로 전환
여기서 가장 자주 빠뜨리는 부분이 4번, 트렁케이션 정합성입니다. 모델은 대개 응답을 끝까지 생성해 두지만, 사용자는 그중 앞부분만 들었습니다. 만약 생성된 전체 문장을 대화 이력에 그대로 남기면, 봇은 자기가 "다 말했다"고 착각합니다. 그러면 사용자가 "방금 그거 다시 말해줘"라고 했을 때 맥락이 어긋납니다. 사용자가 실제로 들은 지점까지만 어시스턴트 발화로 기록해야 이후 대화가 자연스럽게 이어집니다.
재개 측면에서는, 끊긴 직후 사용자의 새 발화를 받아 정상적인 턴으로 처리하면 됩니다. 다만 끊자마자 사용자가 곧바로 말을 멈추는 경우(잘못된 끼어들기)도 있으므로, 일정 시간 발화가 이어지지 않으면 직전 맥락으로 복귀하는 안전장치를 두는 것이 좋습니다.
풀 듀플렉스 대화 구현 방식
끼어들기 처리의 종착점은 풀 듀플렉스, 즉 듣기와 말하기가 동시에 가능한 구조입니다. 두 방식을 비교하면 차이가 분명합니다.
- 하프 듀플렉스(턴 기반): 봇이 말할 때는 입력을 닫고, 사용자가 말할 때는 출력을 멈춥니다. 구현이 단순하고 에코 문제가 적지만, 봇이 말하는 동안의 끼어들기를 구조적으로 받을 수 없습니다.
- 풀 듀플렉스(상시 청취): 봇이 말하는 중에도 마이크를 계속 열어 둡니다. 진정한 끼어들기와 백채널, 발화 겹침을 모두 다룰 수 있지만, AEC와 상태 관리가 필수이고 설계 난도가 높습니다.
풀 듀플렉스의 핵심은 명확한 상태 머신입니다. 최소한 LISTENING(듣기), THINKING(처리), SPEAKING(말하기) 상태를 두고, SPEAKING 도중 의미 있는 발화가 들어오면 앞 절의 중단 시퀀스를 거쳐 LISTENING으로 전이합니다. 입력 스트림과 출력 스트림을 동시에 굴리되, 두 스트림이 같은 상태 머신을 공유하도록 묶는 것이 안정성의 관건입니다.
엔드투엔드 방식의 음성 모델은 입력과 출력을 한 모델 안에서 다루기 때문에 끼어들기 대응이 구조적으로 유리한 편이고, STT-LLM-TTS를 잇는 캐스케이드 방식은 각 단계 사이에 인터럽트 신호를 전파하는 배선을 직접 깔아야 합니다. 어느 쪽이든 "출력 중에도 입력을 듣는다"는 원칙은 동일합니다.
실무 튜닝 포인트와 함정
끼어들기 처리는 과민과 둔감 사이의 줄타기입니다. 너무 예민하면 잡음이나 맞장구에도 봇이 멈춰 대화가 토막 나고, 너무 둔하면 사용자가 답답해합니다. 몇 번을 반복해 튜닝해 보면 대개 다음 지점을 조정하게 됩니다.
- 임계 파라미터(최소 발화 지속시간·침묵 임계): 끼어들기로 인정할 최소 발화 지속시간을 두면 헛기침·잡음 같은 짧은 소리의 오발화를 줄이고, 엔드포인트 판정의 침묵 임계(턴이 끝났다고 보는 무음 길이)를 함께 조정합니다. 두 값은 보통 수백 밀리초 안팎에서 환경에 맞춰 잡되, 통화처럼 양쪽 소리가 섞이는 교차 토크 상황에서는 다소 보수적으로 두어 오인터럽트를 억제합니다.
- 반응 지연 목표: 사용자가 끊은 뒤 봇이 멈추기까지의 지연이 길면 끼어든 보람이 없습니다. 체감상 응답·반응이 1초를 넘기면 부자연스럽게 느껴지므로, 그 안쪽을 목표로 잡는 경우가 많습니다.
평가도 빼놓을 수 없습니다. 인터럽트 반응 지연(끊은 후 멈추기까지), 오인터럽트율(false barge-in), 미감지율을 함께 보아야 한 지표만 좋게 만드는 함정을 피할 수 있습니다.
끼어들기를 받아내는 순간, 보이스봇은 비로소 안내 멘트 재생기가 아니라 대화 상대가 됩니다.
지금까지는 봇이 사용자의 말을 끊고 들어오는 순간을 어떻게 받아내는지에 집중했습니다. 하지만 자연스러운 대화만으로는 부족합니다. 통화 중에 "제 주문 상태가 어떻게 되나요"처럼 실제 데이터를 물어보면, 봇은 그 자리에서 외부 시스템을 조회해 답해야 합니다. 다음 편에서는 실시간 음성에 MCP(Model Context Protocol)를 연동해, 대화가 끊기지 않는 상태로 통화 중에 데이터를 조회하고 도구를 호출하는 방법을 다룹니다.
댓글
댓글 쓰기