모바일 브라우저 사운드 자동재생 정책 실측 정리
인트로·튜토리얼처럼 진입 직후 탭을 강제하지 않는 흐름이면, 게임만 연 상태로는 사용자 제스처(탭/클릭)가 없다. 이때 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()을 직접 부르지 않는다.
실측 결과
섹션 제목: “실측 결과”1. 첫 진입
섹션 제목: “1. 첫 진입”| 플랫폼 | 브라우저 | 사운드 출력 (제스처 없음) | 사운드 출력 (제스처 있음) | 비고 |
|---|---|---|---|---|
| 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”는 네 시나리오에서 모두 같았다.
2. 새로고침
섹션 제목: “2. 새로고침”| 플랫폼 | 브라우저 | 사운드 출력 (제스처 없음) | 사운드 출력 (제스처 있음) | 비고 |
|---|---|---|---|---|
| iOS | Safari | X | O | iOS Chrome도 같다 |
| Android | Chrome | X | O | 문서 재로드로 활성화가 리셋된다 |
3. 강제 종료 후 복귀
섹션 제목: “3. 강제 종료 후 복귀”| 플랫폼 | 브라우저 | 사운드 출력 (제스처 없음) | 사운드 출력 (제스처 있음) | 비고 |
|---|---|---|---|---|
| iOS | Safari | X | O | iOS Chrome도 같다 |
| Android | Chrome | X | O | 새 세션/리로드와 같다 |
4. 네트워크 단절 후 복귀
섹션 제목: “4. 네트워크 단절 후 복귀”| 플랫폼 | 브라우저 | 사운드 출력 (제스처 없음) | 사운드 출력 (제스처 있음) | 비고 |
|---|---|---|---|---|
| iOS | Safari | X | O | iOS Chrome도 같다 |
| Android | Chrome | O | O | 페이지가 유지된 복귀 기준이다 |
Android에서 네트워크 단절 뒤 재진입(리로드)하면 첫 진입과 같다. 페이지가 살아 있는 채로 복귀하면 AudioContext가 이미 running일 수 있어 제스처 없이도 재생될 수 있다.
시나리오별 해석
섹션 제목: “시나리오별 해석”| 시나리오 | 해석 |
|---|---|
| 첫 진입 | 문서/오디오 컨텍스트가 생성된다. Android는 제스처 없이 재생된 경우가 있고, iOS는 제스처가 필수다 |
| 새로고침 | 문서 재로드로 사용자 활성화가 리셋된다. 양쪽 모두 제스처가 필요해진다 |
| 강제 종료 복귀 | 새 세션/리로드와 같다 |
| 네트워크 단절 복귀 | 리로드 여부에 따라 갈린다. 페이지가 유지되면 Android에서 O가 가능하고, 재진입이면 첫 진입과 같다 |
iOS Chrome
섹션 제목: “iOS Chrome”한국 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이 동작한다.
참고 문서
섹션 제목: “참고 문서”- Chrome: Chrome Autoplay Policy
- Chrome Web Audio: Web Audio Autoplay Policy
- Safari (video/muted 중심): Delivering Video Content for Safari
- WebKit (Web Audio, 사용자 활성화): WebKit User Activation API
- iOS 대체 브라우저 엔진 (EU 한정): Using alternative browser engines in the European Union
Safari video 문서는 muted 자동재생 설명이 많다. 게임 BGM처럼 Web Audio를 쓰면 User Activation 쪽이 더 직접적인 근거다. 소리 있는 재생에 사용자 제스처가 필요하다는 점은 같다.