한국어 음성 AI의 진짜 난관: 존댓말·코드스위칭·숫자 읽기
영어 데모 영상에서는 사람과 구분이 안 될 만큼 매끄럽던 음성 AI가, 막상 한국어로 돌려 보면 어딘가 어색해지는 경험을 해 보셨을 겁니다. 같은 모델인데 갑자기 존댓말이 흔들리고, 영어 단어 하나를 만나면 발음이 무너지고, "1,200원"을 "일천이백" 같은 이상한 방식으로 읽습니다. 흔히 "모델이 덜 똑똑해서"라고 생각하기 쉽지만, 진짜 원인은 한국어라는 언어가 가진 고유한 특성에 있습니다. 이번 글에서는 실시간 음성 대 음성(Speech-to-Speech, 이하 S2S) 시스템이 한국어에서 유독 부딪히는 난점들을, 언어 구조의 관점에서 하나씩 정리합니다.
[시리즈] S2S·LLM 음성 에이전트 엔지니어링 63편 · 현재 6-1편
← 이전: 5-7 프롬프트 A/B 테스트와 튜닝 / 다음 → 6-2 턴테이킹과 시맨틱 VAD
- 5-6 상담사 전환(Handoff) 설계
- 5-7 프롬프트 A/B 테스트와 튜닝
- 6-1 한국어 음성 AI의 난관 — 존댓말·코드스위칭 (현재 글)
- 6-2 턴테이킹과 시맨틱 VAD
- 6-3 보이스 페르소나 디자인
전체 목차 펼치기 (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편)
영어 기준으로 만든 모델이 한국어에서 무너지는 지점
오늘날 많은 음성·언어 모델은 영어 중심으로 설계되고 평가됩니다. 학습 데이터의 비중, 단어를 잘게 쪼개는 토크나이저, 성능을 재는 지표까지 영어에 최적화되어 있는 경우가 많습니다. 한국어는 그 위에 "추가로 지원되는" 언어로 얹히는 일이 흔합니다.
문제는 한국어가 영어와 구조적으로 꽤 다르다는 점입니다. 조사가 단어에 달라붙어 어절 경계가 유동적이고, 같은 한자어 숫자도 단위에 따라 읽는 법이 달라지며, 상대에 따라 문장 끝을 통째로 바꾸는 높임 체계가 있습니다. 영어 기준으로 잘 돌아가던 처리 방식이 한국어에서는 곳곳에서 어긋나는 이유입니다. 아래에서 그 어긋남이 가장 자주 드러나는 지점들을 차례로 살펴봅니다.
존댓말·화계: 일관된 높임 유지의 어려움
한국어에서 가장 까다로운 것 중 하나가 높임입니다. 한국어는 상대와 상황에 따라 문장 종결을 통째로 바꿉니다. "합니다"체와 "해요"체가 다르고, 호칭("고객님" vs 이름)과 어휘 높임("계시다" vs "있다")까지 함께 움직입니다. 영어의 정중함이 주로 단어 선택과 어조에 머무는 것과는 결이 다릅니다.
음성 AI에서 문제가 되는 지점은 "일관성"입니다. 한 통화 안에서 처음에는 "도와드리겠습니다"라고 했다가, 몇 마디 뒤에 "그건 안 돼요"처럼 화계가 슬쩍 내려가면 듣는 사람은 곧바로 위화감을 느낍니다. 모델은 매 발화를 비교적 독립적으로 생성하기 때문에, 명시적으로 묶어 주지 않으면 높임 수준이 발화마다 미세하게 흔들립니다. 그래서 실무에서는 높임 수준을 하나의 설정값처럼 고정하고, 생성 결과를 사후에 점검하는 후처리를 두기도 합니다.
[높임 일관성 후처리 의사코드]
목표화계 = "합쇼체" # 통화 단위로 고정
문장 = 생성결과
if 종결어미(문장) 가 목표화계 와 불일치:
종결어미를 목표화계로 교정 # "돼요" → "됩니다"
if 호칭(문장) in 반말_호칭_목록:
호칭을 "고객님" 등 목표 호칭으로 교정
if 어휘높임_누락(문장): # "있어요" → "계세요"
상대높임 어휘로 치환
return 문장
이런 후처리는 만능이 아닙니다. 규칙이 잡아내지 못하는 미묘한 경우가 늘 남고, 과교정으로 어색해질 위험도 있습니다. 다만 "최소한 화계가 뒤섞이지는 않게" 잡아 주는 안전망으로는 효과가 있습니다.
코드스위칭: 한·영 혼용 발음과 표기
한국어 대화에는 영어가 자연스럽게 섞입니다. "그 앱 업데이트하면 로그인이 안 돼요" 같은 문장이 일상입니다. 이 한·영 혼용, 즉 코드스위칭(code-switching)이 보이스봇의 입력과 출력 양쪽에서 흔들림을 만듭니다.
입력(인식) 측에서는 표기가 갈립니다. 사용자가 말한 "로그인"을 "login"으로 쓸지 "로그인"으로 쓸지, "API"를 알파벳으로 둘지 "에이피아이"로 풀지가 일관되지 않으면, 뒤따르는 처리가 흔들립니다. 출력(합성) 측에서는 발음이 문제입니다. 문장 중간의 영어 단어를 한국식으로 자연스럽게 읽어야 하는데, 갑자기 원어민 발음으로 튀거나 글자 그대로 어색하게 읽으면 몰입이 깨집니다. 한국어 문맥에서 영어 단어는 보통 한국식 외래어 발음으로 녹여 읽는 편이 자연스럽습니다. 핵심은 표기 규칙과 발음 규칙을 미리 정해 두고, 혼용 단어를 그때그때 즉흥 처리하지 않는 것입니다.
한 단계 더 어려운 경우는 한 통화 안에서 사용 언어 자체가 동적으로 바뀌는 상황입니다. 단어 몇 개가 섞이는 수준을 넘어, 같은 세션에서 한국어로 안내하다가 "방금 그 설명을 영어로 다시 해 줄 수 있나요", 이어서 "베트남어로도 가능한가요" 하는 식으로 응대 언어가 통째로 전환되는 흐름입니다. 다국어 사용자가 많은 응대 환경에서는 드물지 않은 요구인데, 시스템 입장에서는 발화마다 "지금 어떤 언어로 듣고 어떤 언어로 답해야 하는가"를 실시간으로 판정하고, 그 판정에 따라 인식·합성 경로를 바꿔 끼워야 합니다. 발화 의도를 분석해 처리 경로를 고르는 시멘틱 라우팅 관점에서 보면, 언어 전환도 결국 라우팅해야 할 하나의 의도인 셈입니다. 이렇게 한 세션 안에서 매끄럽게 언어를 갈아타는 코드스위칭은 한국어 음성 AI의 실전 난관이자, 잘 풀어내면 곧바로 차별점이 되는 지점입니다.
이 지점에서 설계상의 현실적인 절충도 드러납니다. 떠오르는 발상은 S2S 단일 모델 하나로 모든 언어를 끝까지 처리하는 것이지만, 막상 만들어 보면 다국어 실시간 인식까지 한 모델에 다 얹는 것은 오버스펙이 되기 쉽습니다. 그래서 한국어 응대가 주축인 환경에서는, 정확도가 가장 중요한 한국어 전사(STT)는 한국어에 최적화된 별도 모듈로 분리해 두고, 다국어가 필요한 구간만 그에 맞는 인식 경로로 따로 태우는 식의 분리 설계가 운영상 더 견고합니다. 하나의 거대한 모델이 모든 언어를 평균적으로 처리하게 두기보다, "주력 언어는 전용으로 깊게, 부가 언어는 필요한 만큼 별도로"라는 역할 분담이 한국어 품질과 다국어 유연성을 동시에 잡는 현실적인 방법입니다.
텍스트 정규화(TTS normalization): 숫자·날짜·주소·단위·전화번호 읽기
합성 음성이 어색해지는 가장 흔한 원인은 텍스트 정규화입니다. 화면의 표기를 "읽을 형태"로 펼치는 전처리인데, 한국어에서는 같은 숫자가 문맥에 따라 전혀 다르게 읽힙니다. 한자어 수사(일·이·삼)와 고유어 수사(하나·둘·셋)가 공존하고, 뒤에 오는 단위에 따라 어느 쪽을 쓸지 갈리기 때문입니다.
| 입력 표기 | 자연스러운 읽기 | 함정 포인트 |
|---|---|---|
| 3시 30분 | 세 시 삼십 분 | 시=고유어, 분=한자어 혼합 |
| 1,200원 | 천이백 원 | 자릿수 단위로 펼침, "일천" 아님 |
| 010-1234-5678 | 공일공 일이삼사 오륙칠팔 | 전화는 자릿수 낱개 읽기 |
| 2026. 6. 18. | 이천이십육 년 유월 십팔 일 | 6월=유월, 점은 날짜로 해석 |
| 3/4 | 사 분의 삼 (또는 삼월 사일) | 분수냐 날짜냐 문맥 의존 |
| 5kg | 오 킬로그램 | 단위 약어를 풀어 읽기 |
규칙을 코드로 옮기면 결국 "문맥을 보고 읽기를 분기"하는 형태가 됩니다.
[숫자·단위 읽기 정규화 분기]
def 읽기(토큰, 문맥):
if 전화번호_패턴(토큰):
return 자릿수_낱개_읽기(토큰) # 0→"공", 묶음 단위로 끊어 읽기
if 뒤_단위(문맥) in {"시", "개", "명", "살"}:
return 고유어_수사(토큰) # 3 → "세"
if 뒤_단위(문맥) in {"분", "초", "원", "월", "년"}:
return 한자어_수사(토큰) # 30 → "삼십"
if 날짜_패턴(문맥):
return 날짜_읽기(토큰) # 6 → "유월", 10 → "시월"
return 자릿수_펼치기(토큰) # 1200 → "천이백"
여기서 보이듯, 정규화는 단순 치환이 아니라 문맥 판단을 포함합니다. "6월"의 "유월", "10월"의 "시월"처럼 예외도 적지 않아, 도메인(금융·예약·물류 등)마다 자주 나오는 패턴을 따로 정리해 두는 편이 안전합니다.
띄어쓰기·동음이의어·외래어 표기
한국어에는 텍스트만으로는 풀리지 않는 모호함이 곳곳에 있습니다. 첫째는 띄어쓰기입니다. 띄어쓰기 하나로 의미가 갈리는 경우가 있고, 인식 결과의 띄어쓰기가 흔들리면 뒤따르는 처리가 어긋납니다. 둘째는 동음이의어입니다. "눈"(eye/snow), "배"(stomach/pear/ship)처럼 소리는 같고 뜻이 다른 단어가 많아, 텍스트만으로는 어느 쪽인지 단정하기 어렵습니다. 사람은 문맥과 운율로 구분하지만 시스템은 그 단서를 놓치기 쉽습니다.
셋째는 외래어 표기입니다. 표기 규범이 있어도 실제 사용에서는 "메시지/메세지", "컨텐츠/콘텐츠"처럼 표기가 제각각입니다. 인식 측에서는 어느 표기로 적을지, 합성 측에서는 어떻게 읽을지 기준이 흔들립니다. 이런 모호함은 완전히 없앨 수 없으므로, 자주 나오는 표현은 사전(lexicon)으로 고정해 두고 시스템 전체가 같은 표기·발음을 쓰도록 통일하는 것이 현실적인 대응입니다.
한국어 평가의 어려움(WER의 한계)
마지막으로, 한국어는 "잘 되고 있는지"를 재는 일조차 까다롭습니다. 음성 인식 품질을 잴 때 흔히 쓰는 지표가 WER(Word Error Rate, 단어 오류율)인데, 이 지표가 한국어에서는 체감 품질과 잘 맞지 않을 때가 있습니다.
이유는 앞서 본 특성들과 연결됩니다. 한국어는 띄어쓰기 기준이 유동적이고 조사가 단어에 붙어 어절 경계가 흔들립니다. "확인했습니다"를 "확인 했습니다"로 띄우는 것은 의미상 같지만, 단어 단위로 비교하면 오류로 잡힙니다. 반대로 조사 하나가 틀려 의미가 달라져도 어절 단위로는 작은 차이로 보일 수 있습니다. 정규화 변이("천이백" vs "1200")까지 겹치면 같은 발화도 채점 결과가 들쭉날쭉해집니다. 그래서 한국어에서는 WER만 보지 않고, 음절·문자 단위로 비교하는 CER(Character Error Rate)을 함께 보거나, 정답·예측을 같은 방식으로 정규화한 뒤 비교하는 식으로 보정합니다. 숫자 하나로 품질을 단정하기보다, 실제 통화에서 의미가 제대로 전달됐는지를 함께 점검하는 태도가 중요합니다. 한국어 평가 방법론의 전반적인 설계는 별도 편에서 더 다룹니다.
만약 이 세 가지 난점(존댓말 일관성, 코드스위칭, 텍스트 정규화)을 한꺼번에 뭉뚱그려 잡으려 한다면 어떻게 될까요. 실제로 그렇게 접근하면 규칙과 예외가 뒤엉켜 유지보수가 오히려 어려워지는 경우가 많습니다. 셋을 별개의 레이어로 나누어 각자 독립적으로 검증하고, 그 결과를 조합하는 순서로 접근할 때 품질이 더 안정적으로 쌓이는 편입니다. 그래서 한국어 S2S를 설계할 때는 세 도전과제를 한 문제로 뭉뚱그리지 않고, 아래처럼 각각의 대응 방향을 따로 정리해 두는 편이 실전에서 더 유용합니다.
한국어 S2S 3대 도전과제 요약
| 도전과제 | 대응 방향 |
|---|---|
| 존댓말·화계 일관성 유지 | 화계를 통화 단위 설정값으로 고정하고, 종결어미·호칭·어휘 높임을 사후 점검하는 후처리 레이어를 둡니다. |
| 한·영 코드스위칭과 텍스트 정규화 | 자주 쓰이는 혼용 표기와 숫자·날짜·단위 읽기 규칙을 도메인별 사전으로 선제 정의하고, 즉흥 처리를 최소화합니다. |
| 평가 지표(WER)의 한국어 한계 | WER 단독 사용을 지양하고 CER(음절 오류율)과 정규화 보정 비교를 병행하며, 실제 통화에서 의미 전달 여부를 함께 점검합니다. |
한국어는 언어 구조 자체가 영어 중심 모델의 설계 가정과 여러 지점에서 어긋나기 때문에, 모델을 도입한 뒤에도 이 세 축을 지속적으로 점검하는 운영 체계가 품질을 유지하는 핵심입니다. 이 글의 정리는 2026년 6월 기준이며, 변화가 빠른 분야인 만큼 세부 수치는 도입 시점에 다시 확인하는 것이 좋습니다.
댓글
댓글 쓰기