모바일 Web Speech API + 카톡 인앱 브라우저 함정¶
(휴 앱 디버깅에서 배움 — 2026-05-03)
증상¶
- 데스크톱 / 일반 모바일 Chrome·Safari에서 음성 잘 나옴
- 카톡으로 받은 링크 누르면 음성 안 나옴
원인 1: 카톡 인앱 브라우저는 Web Speech API 미지원¶
- 카카오톡은 자체 WebView로 링크를 엶 (안드로이드/iOS 모두)
- 그 WebView는
window.speechSynthesis객체가 없거나speak()호출이 무시됨 - 페이스북, 인스타그램, Line 인앱 브라우저도 동일
해결: ?openExternalBrowser=1¶
카카오 공식 파라미터. 카톡에서 받은 링크에 이 쿼리가 붙어 있으면 인앱 안 거치고 외부 Chrome/Safari로 자동 열림.
var url = location.origin + '/game/?openExternalBrowser=1';
// 이걸 카톡으로 공유하면 받는 사람 카톡에서 누를 때 Chrome/Safari로 직접 열림
안전망: 인앱 브라우저 감지 + 안내 배너¶
이미 잘못 들어온 사용자도 보호.
var ua = navigator.userAgent;
var isKakao = /KAKAOTALK/i.test(ua);
var isFB = /FBAN|FBAV/i.test(ua);
var isInsta = /Instagram/i.test(ua);
var isLine = /Line\//i.test(ua);
var inApp = isKakao || isFB || isInsta || isLine;
if (inApp && /Android/i.test(ua)) {
// 안드로이드: Chrome으로 자동 점프 가능
// intent://example.com/path#Intent;scheme=https;package=com.android.chrome;end
}
// iOS는 강제 점프 불가 — "우상단 ··· → Safari로 열기" 가이드 노출
원인 2: 안드로이드 Chrome getVoices() 빈 배열 버그¶
- 페이지 로드 직후
speechSynthesis.getVoices()가 빈 배열 반환 onvoiceschanged이벤트도 안 옴 (또는 늦게)- 코드가 "voice 못 찾음 → available=false" 로 굳어버려 그 뒤 모든
speak()무시
해결 4종 세트¶
available판정 완화: voice 매칭이 아니라window.speechSynthesis지원 여부로만- voice 못 찾아도
lang='ko-KR'만 달고 speak 시도 — OS가 자동 매칭 setTimeout폴백으로 voice 재탐색 (200/800/2000ms)- 첫 사용자 제스처에서 unlock: 빈 utterance(volume=0) 한 번 던져서 권한 획득
원인 3: iOS Safari 15초 자동 멈춤 버그¶
긴 utterance 재생 중 ~15초 지나면 멈춤. pause/resume keep-alive 인터벌.
setInterval(function() {
if (speechSynthesis.speaking && !speechSynthesis.paused) {
speechSynthesis.pause();
speechSynthesis.resume();
}
}, 10000);
차선책: 사전 녹음 mp3¶
패치로도 안 풀리는 케이스가 많이 보고되면: - Cloud TTS (Google/ElevenLabs)로 시나리오 발화 미리 생성 - R2/S3에 캐싱 - 가장 안정적이지만 작업량 큼 (시나리오 92개 × 평균 5~7개 발화 = 500~600개 mp3)
핵심 교훈¶
- "폰에서는 안 돼요" 라고 들으면 다음 단계로 물어봐: "카톡으로 받은 링크인가요, 아니면 직접 브라우저에서 여신 건가요?"
- 카톡 인앱 = Web Speech API + 파일 업로드 + 일부 OAuth 등 다 막힘. 음성 콘텐츠 있으면 무조건
?openExternalBrowser=1붙이자