콘텐츠로 이동

모바일 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종 세트

  1. available 판정 완화: voice 매칭이 아니라 window.speechSynthesis 지원 여부로만
  2. voice 못 찾아도 lang='ko-KR'만 달고 speak 시도 — OS가 자동 매칭
  3. setTimeout 폴백으로 voice 재탐색 (200/800/2000ms)
  4. 첫 사용자 제스처에서 unlock: 빈 utterance(volume=0) 한 번 던져서 권한 획득
    document.addEventListener('touchstart', function() {
      var u = new SpeechSynthesisUtterance('');
      u.volume = 0;
      speechSynthesis.speak(u);
    }, { once: true });
    

원인 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 붙이자