콘텐츠로 이동

모바일 브라우저 사운드 자동재생 정책 실측 정리

인트로·튜토리얼처럼 진입 직후 탭을 강제하지 않는 흐름이면, 게임만 연 상태로는 사용자 제스처(탭/클릭)가 없다. 이때 BGM/SFX는 브라우저 자동재생 정책에 걸린다.

제스처 없이 사운드를 틀면 재생이 막힐 수 있고, 브라우저와 시나리오마다 결과가 다르다. 결과는 모바일 기기에서 실측했다.

여기서 “사용자 제스처”는 브라우저 자동재생 정책의 user gesture / user activation이다. 탭, 클릭처럼 사용자가 직접 발생시킨 입력을 뜻하며, UI 햅틱이나 터치 피드백과는 별개다.

  • iOS Safari와 iOS Chrome은 실측한 네 시나리오 모두에서 사용자 제스처 없이 소리 있는 BGM/SFX 재생이 막혔다.
  • Android Chrome은 첫 진입에서 재생될 수 있지만, MEI, PWA 여부, 이전 상호작용 이력에 따라 달라진다.
  • 새로고침이나 새 세션에서는 사용자 활성화가 리셋되므로 양쪽 모두 제스처 기반 재개 처리가 필요하다.
  • AudioContext resume/unlock은 H5 프레임워크의 Sound가 담당한다. initializeFramework()가 부팅 시 Sound.initialize()를 호출하고, 전역 제스처(pointerdown/touchstart/click)에서 AudioContext를 푼다. 게임 코드에서 audioCtx.resume()을 직접 부르지 않는다.
플랫폼 브라우저 사운드 출력 (제스처 없음) 사운드 출력 (제스처 있음) 비고
iOS Safari X O iOS Chrome도 같다
Android Chrome O O 환경에 따라 달라질 수 있다 (아래)

Android Chrome에서 “제스처 없음 = O”는 항상 나오지 않는다. 같은 origin의 이전 상호작용 이력과 Chrome의 MEI(Media Engagement Index), 홈 화면 추가/PWA, 진입 경로(직접 URL vs 인앱 WebView)에 따라 갈린다. QA할 때는 재현 조건을 고정한다. iOS의 “제스처 없음 = X”는 네 시나리오에서 모두 같았다.

플랫폼 브라우저 사운드 출력 (제스처 없음) 사운드 출력 (제스처 있음) 비고
iOS Safari X O iOS Chrome도 같다
Android Chrome X O 문서 재로드로 활성화가 리셋된다
플랫폼 브라우저 사운드 출력 (제스처 없음) 사운드 출력 (제스처 있음) 비고
iOS Safari X O iOS Chrome도 같다
Android Chrome X O 새 세션/리로드와 같다
플랫폼 브라우저 사운드 출력 (제스처 없음) 사운드 출력 (제스처 있음) 비고
iOS Safari X O iOS Chrome도 같다
Android Chrome O O 페이지가 유지된 복귀 기준이다

Android에서 네트워크 단절 뒤 재진입(리로드)하면 첫 진입과 같다. 페이지가 살아 있는 채로 복귀하면 AudioContext가 이미 running일 수 있어 제스처 없이도 재생될 수 있다.

시나리오 해석
첫 진입 문서/오디오 컨텍스트가 생성된다. Android는 제스처 없이 재생된 경우가 있고, iOS는 제스처가 필수다
새로고침 문서 재로드로 사용자 활성화가 리셋된다. 양쪽 모두 제스처가 필요해진다
강제 종료 복귀 새 세션/리로드와 같다
네트워크 단절 복귀 리로드 여부에 따라 갈린다. 페이지가 유지되면 Android에서 O가 가능하고, 재진입이면 첫 진입과 같다

한국 iOS Chrome은 Apple WebKit과 iOS 미디어 정책을 쓴다. 실측에서도 자동재생 결과가 네 시나리오 모두 iOS Safari와 같았다.

대체 브라우저 엔진 허용은 현재 EU에 한정된다. 한국 iOS Chrome에는 해당하지 않는다.

  • iOS 무음 스위치(링거 무음): 제스처 후에 Web Audio가 들리는지, HTML audio/video와 결과가 같은지 따로 확인한다.
  • iOS 저전력 모드: 자동재생·백그라운드 복귀·오디오 재개 조건을 별도 케이스로 확인한다.
  • Telegram 등 인앱 WebView: 일반 브라우저 표와 결과를 따로 확인한다.
  • PWA / 홈 화면 추가: Chrome 모바일 자동재생 결과가 달라지므로 따로 확인한다.
  • 테스트 전제: 캐시·사이트 데이터 삭제 여부, 직접 URL vs 딥링크, 기기 무음 여부를 기록한다.

진입 직후 아무 조작 없이 소리가 난다고 가정하지 않는다. iOS에서 소리가 나지 않는 것은 버그가 아니라 브라우저 정책이다.

게임 핸들러에서 audioCtx.resume()을 부르지 않는다. 프레임워크의 Sound.initialize()가 첫 탭, 시작 버튼, 튜토리얼 닫기 같은 사용자 제스처를 전역으로 받아 AudioContext를 푼다.

// H5 프레임워크 Sound.initialize() — initializeFramework()가 부팅 시 호출한다.
// 게임 코드에서 audioCtx.resume()을 직접 부르지 않는다.
const gestureOptions: AddEventListenerOptions = { capture: true, passive: true };
const gestureEvents = ['pointerdown', 'pointerup', 'touchstart', 'touchend', 'click'];
for (const eventName of gestureEvents) {
document.addEventListener(eventName, Sound.onUserGestureUnlock, gestureOptions);
}

제스처가 없는 진입 경로가 있으면 iOS 무음 진입을 막을 수 없다. 튜토리얼 닫기나 시작 버튼처럼 사용자가 직접 탭하는 흐름이 있어야 프레임워크의 전역 unlock이 동작한다.

Safari video 문서는 muted 자동재생 설명이 많다. 게임 BGM처럼 Web Audio를 쓰면 User Activation 쪽이 더 직접적인 근거다. 소리 있는 재생에 사용자 제스처가 필요하다는 점은 같다.