권한 처리 패턴
clipboard, geolocation, camera, microphone, contacts, photos 같은 민감한 디바이스 기능은 모두 동일한 권한 모델을 공유합니다. 이 가이드는 그 모델을 한 곳에서 정리합니다 — 각 API 페이지의 "권한" 섹션은 이 문서를 역참조해서 중복을 피합니다.
비공식 문서
이 페이지는 커뮤니티가 작성한 설명입니다. SDK의 동작은 상위의 @apps-in-toss/web-framework 배포본을 기준으로 합니다.
권한 모델 한눈에 보기
| 개념 | 타입 | 설명 |
|---|---|---|
PermissionName | 'clipboard' | 'contacts' | 'photos' | 'geolocation' | 'camera' | 'microphone' | 권한이 부여되는 단위. 한 네임스페이스의 모든 메서드는 같은 PermissionName을 공유합니다 (예: getClipboardText, setClipboardText 모두 clipboard). |
PermissionStatus | 'notDetermined' | 'denied' | 'allowed' | 현재 사용자가 해당 권한에 대해 어떤 상태인지. 첫 진입은 notDetermined, 다이얼로그에서 거절했으면 denied, 승인했으면 allowed. |
| 권한이 필요한 함수 | callable + .getPermission() + .openPermissionDialog() | SDK는 권한이 필요한 함수에 두 유틸을 부착해 둡니다. 별도의 모듈을 import하지 않고도 호출부 가까이에서 권한을 다룰 수 있습니다. |
Storage 네임스페이스는 이 모델에 포함되지 않습니다 — Storage는 PermissionName에 바인딩되어 있지 않고, getPermission() / openPermissionDialog() 유틸도 노출하지 않습니다.
표준 흐름: check → prompt → invoke
권한이 필요한 모든 호출은 다음 세 단계로 정리할 수 있습니다.
import { setClipboardText } from '@apps-in-toss/web-framework';
async function copyWithPermission(value: string) {
// 1. 현재 상태를 먼저 확인한다.
const status = await setClipboardText.getPermission();
// 2. 거절 상태면 호출 자체가 실패한다 — 사용자에게 설정 화면 안내가 필요.
if (status === 'denied') {
throw new Error('PERMISSION_DENIED');
}
// 3. 미결정 상태면 시스템 다이얼로그로 사용자에게 묻는다.
if (status === 'notDetermined') {
const result = await setClipboardText.openPermissionDialog();
if (result === 'denied') {
throw new Error('PERMISSION_DENIED');
}
}
// 4. allowed가 보장된 시점에서 실제 호출.
await setClipboardText(value);
}
openPermissionDialog()는 'allowed' | 'denied'로 resolve 합니다 — notDetermined로 다시 떨어지지 않으므로, 다이얼로그 직후엔 두 상태만 다루면 됩니다.
짧게: 호출 후 catch
위 4단계가 정석이지만, 단순한 UX(예: "복사" 버튼 한 번)에서는 곧장 호출하고 실패만 잡아도 충분합니다.
try {
await setClipboardText(value);
showAppToast('복사되었습니다');
} catch {
showAppToast('권한이 없어 복사하지 못했어요. 설정에서 허용해 주세요.');
}
이 단축형은 notDetermined 상태가 호출을 그대로 통과시키는 환경에서 동작합니다. 그래도 첫 호출 시점에 시스템 다이얼로그가 뜰 가능성이 있으므로, 사용자가 명시적으로 액션을 트리거한 시점에만 사용하세요. 백그라운드 자동 호출에는 적합하지 않습니다.