접근성
접근성 기능 및 TalkBack / VoiceOver 지원
개요
접근성 Bridge는 TTS(텍스트 음성 변환), STT(음성 인식), 햅틱 피드백, 접근성 패널을 웹 페이지에서 JavaScript로 제어할 수 있게 합니다. Android(TalkBack)와 iOS(VoiceOver) 모두 동일한 Bridge API를 지원합니다.
주입되는 전역 객체는 window.unveilyBridge(소문자) 하나뿐이며, 접근성 관련 기능은 tts, stt, haptic, accessibilityPanel 네임스페이스로 제공됩니다.
| 기능 | 네임스페이스 | Android | iOS |
|---|---|---|---|
| TTS | unveilyBridge.tts | ✓ | ✓ |
| STT | unveilyBridge.stt | ✓ | ✓ |
| Haptic | unveilyBridge.haptic | ✓ | ✓ |
| 접근성 패널 | unveilyBridge.accessibilityPanel | ✓ | ✓ |
브릿지 준비 시점
window.unveilyBridge는 페이지 로드 전에 등록되지만, 네임스페이스는 글루 스크립트 주입 이후에 생성됩니다. React·Vue 등 SPA의 마운트 시점(useEffect/onMounted)에서 접근성 API를 호출한다면 먼저 unveilyGlueReady 이벤트를 기다리세요. 버튼 클릭 등 사용자 동작으로 호출할 때는 필요 없습니다.
window.addEventListener('unveilyGlueReady', () => {
window.unveilyBridge.tts.speak("Hello, world", "en-US");
}, { once: true });모듈 활성화
assets/config.json에서 접근성 모듈을 활성화해야 합니다.
{
"modules": {
"accessibility": {
"enabled": true,
"topDownPanel": true
}
}
}TTS (텍스트 음성 변환)
unveilyBridge.tts의 메서드는 **위치 인자(positional)**를 사용합니다. 옵션 객체를 전달하지 않습니다.
speak
텍스트를 음성으로 읽어줍니다. 첫 번째 인자는 읽을 텍스트, 두 번째 인자는 언어 코드입니다.
window.unveilyBridge.tts.speak("Hello, world", "en-US");stop
현재 재생 중인 TTS를 중지합니다.
window.unveilyBridge.tts.stop();pause / resume
TTS를 일시정지하거나 재개합니다.
window.unveilyBridge.tts.pause();
window.unveilyBridge.tts.resume();setSpeed
TTS 재생 속도를 설정합니다. 1.0이 기본 속도이며 0.1~4.0 범위로 자동 제한됩니다.
window.unveilyBridge.tts.setSpeed(1.0); // 1.0 = normal, clamped to 0.1–4.0재생 상태 이벤트
TTS 재생 상태 변화는 전역 함수 window.onTTSStateChanged로 전달됩니다.
window.onTTSStateChanged = function (result) {
// result.state: 'started' | 'completed' | 'paused' | 'error'
console.log(result.state);
};지원 언어
TTS는 ko-KR, ja-JP, zh-CN을 인식하며, 그 외 값은 영어(en-US)로 처리됩니다.
| 코드 | 언어 |
|---|---|
"ko-KR" | 한국어 |
"ja-JP" | 일본어 |
"zh-CN" | 중국어(간체) |
"en-US" | 영어(기본값) |
TTS 재생 완료 후 즉시 getUserMedia({ audio: true })를 호출해도 정상 동작합니다. SDK가 TTS 재생 전후로 오디오 포커스를 자동 관리하므로 별도 딜레이 없이 마이크를 바로 사용할 수 있습니다.
STT (음성 인식)
unveilyBridge.stt는 위치 인자로 언어 코드만 받습니다. 결과와 에러는 전역 함수(window.onSTTResult, window.onSTTError)로 전달되며, 콜백 파라미터로 넘기지 않습니다.
start
음성 인식을 시작합니다.
window.unveilyBridge.stt.start("en-US");
window.onSTTResult = function (result) {
// result.isFinal === false means a partial (real-time) result
console.log(result.text, result.isFinal);
};
window.onSTTError = function (error) {
console.error(error.code, error.message);
};전달되는 객체 구조
// window.onSTTResult(result) — isFinal: false means a partial result
{ "text": "recognized text", "isFinal": true }
// window.onSTTError(error)
{ "code": "PERMISSION_DENIED", "message": "..." }stop
음성 인식을 중지합니다.
window.unveilyBridge.stt.stop();필요한 권한 — 마이크
STT는 마이크 권한이 필요합니다.
| 플랫폼 | 권한 |
|---|---|
| Android | RECORD_AUDIO — 매니페스트에서 주석 해제하여 활성화 |
| iOS | Info.plist에 NSMicrophoneUsageDescription 및 NSSpeechRecognitionUsageDescription 선언 |
iOS에서는 첫 STT 호출 시 시스템 마이크 권한 팝업이 자동으로 표시됩니다.
Haptic (햅틱 피드백)
unveilyBridge.haptic은 settings.haptic이 활성화되어 있어야 동작합니다.
vibrate
지정한 시간(ms)만큼 진동합니다. 위치 인자로 밀리초 값을 전달합니다.
window.unveilyBridge.haptic.vibrate(200);pattern
패턴 진동을 실행합니다. JSON 문자열로 [대기, 진동, 대기, 진동, ...] 배열을 전달합니다.
// JSON string: [wait, vibrate, wait, vibrate, ...]
window.unveilyBridge.haptic.pattern("[0, 100, 50, 200]");impact
미리 정의된 세기의 임팩트 진동을 실행합니다.
iOS에서는 UIImpactFeedbackGenerator, Android에서는 VibrationEffect를 사용합니다.
window.unveilyBridge.haptic.impact("medium"); // "light" | "medium" | "heavy"접근성 패널
사용자가 직접 접근성 옵션을 조절할 수 있는 패널 UI로, unveilyBridge.accessibilityPanel 네임스페이스로 제어합니다(unveilyBridge.accessibility 별칭도 사용 가능). config.json의 modules.accessibility.enabled로 활성화됩니다.
패널이 열릴 때 Android는 TYPE_WINDOW_STATE_CHANGED, iOS는 UIAccessibility.screenChanged를 자동 발송하여 스크린 리더(TalkBack/VoiceOver)가 즉시 인식합니다.


open / close / toggle
window.unveilyBridge.accessibilityPanel.open();
window.unveilyBridge.accessibilityPanel.close();
window.unveilyBridge.accessibilityPanel.toggle();getSettings
현재 접근성 설정을 읽어옵니다. 콜백 함수명을 문자열로 전달하며, 생략 시 기본값은 onAccessibilitySettingsLoaded입니다.
window.unveilyBridge.accessibilityPanel.getSettings("onAccessibilitySettingsLoaded");
window.onAccessibilitySettingsLoaded = function (settings) {
console.log(settings.fontSize); // "normal" | "large" | "extraLarge"
console.log(settings.highContrast); // boolean
};applySettings
설정을 프로그램적으로 적용합니다. getSettings와 동일한 필드를 가진 JSON 문자열을 전달합니다.
window.unveilyBridge.accessibilityPanel.applySettings(JSON.stringify({
highContrast: true,
fontSize: "large",
tts: true,
easyRead: false,
haptic: true,
tabAlwaysShow: false,
leftHanded: false,
oneHanded: false
}));설정 객체
패널에서 사용자가 조절할 수 있는 항목이며, getSettings / applySettings가 공유하는 필드입니다.
| 설정 키 | 타입 | 설명 |
|---|---|---|
highContrast | boolean | 고대비 모드 |
fontSize | "normal" | "large" | "extraLarge" | 글자 크기 |
tts | boolean | TTS 활성화 여부 |
easyRead | boolean | 쉬운 읽기 (단순한 레이아웃으로 전환) |
haptic | boolean | 햅틱 피드백 활성화 여부 |
tabAlwaysShow | boolean | 탭 바 항상 표시 (자동 숨김 비활성화) |
leftHanded | boolean | 왼손잡이 모드 |
oneHanded | boolean | 한손 모드 |
config.json의 modules.accessibility.topDownPanel: true로 설정하면 화면 상단에서 내려오는 패널 형태로 표시됩니다.