Permission Group은 Android에서 권한을 그룹화하는 메커니즘으로, 기능적으로 관련된 위험한 권한을 하나의 논리적 범주로 결합합니다. Android Permissions Overview, 2024에 따르면, 권한 그룹은 사용자 인터페이스를 단순화합니다. 사용자가 그룹 내 하나의 권한을 부여하면 나머지는 추가 대화상자 없이 자동으로 부여됩니다. 이는 요청 수를 줄이고 UX를 개선합니다.
핵심 사항
Permission Group은 여러 위험한 권한을 기능적 목적에 따라 하나의 그룹으로 묶는 Android 시스템 메커니즘입니다. 각 그룹에는 문자열 식별자가 있으며, 예를 들어 android.permission-group.CAMERA 또는 android.permission-group.LOCATION이 있습니다. 하나의 그룹 내 모든 권한은 논리적으로 연결되어 있으며 장치의 관련 기능에 대한 액세스를 제공합니다.
권한 그룹은 Android 6.0 Marshmallow에서 런타임 권한 모델과 함께 등장했습니다. 주요 목적은 사용자 상호 작용을 단순화하는 것입니다. 개별 권한마다 일련의 대화상자를 표시하는 대신 시스템은 그룹당 하나의 대화상자를 표시합니다. 사용자가 그룹 내 하나의 권한을 부여하면 나머지는 자동으로 승인된 것으로 간주됩니다. Android UX Research(2015)에 따르면, 이로 인해 첫 실행 시 거부 횟수가 20% 감소했습니다.
개발자가 자신만의 Permission Group을 만들 수 없다는 것을 이해하는 것이 중요합니다. 그룹은 운영 체제 수준에서 미리 정의되어 있으며 각 기기의 permissions.xml 파일에 설명되어 있습니다. 앱은 uses-permission만 선언하면 시스템이 protectionLevel과 AOSP의 분류에 따라 권한을 자동으로 해당 그룹에 매핑합니다.
권한과 그룹의 매핑은 시스템 권한 정의의 permissionGroup 속성을 통해 이루어집니다. 예를 들어, CAMERA는 permissionGroup="android.permission-group.CAMERA", ACCESS_FINE_LOCATION은 permissionGroup="android.permission-group.LOCATION"으로 선언됩니다. 이 매핑은 Android Open Source Project 코드에 하드코딩되어 있으며 모든 인증된 기기에서 동일합니다.
그룹 메커니즘은 “그룹당 하나의 대화상자” 원칙에 따라 작동합니다. 앱이 처음으로 위험한 권한을 요청하면 시스템은 해당 Permission Group을 확인합니다. 이 그룹에서 아직 권한이 부여되지 않은 경우 대화상자가 표시됩니다. 동의 후 시스템은 전체 그룹을 부여된 것으로 표시하고, 동일한 그룹의 다른 권한에 대한 후속 요청은 UI 없이 처리됩니다.
단순화된 알고리즘은 다음과 같습니다:
이 메커니즘은 위험한 권한에만 적용됩니다. 일반 권한에는 그룹이 없으며 이 로직에 참여하지 않습니다. 특권 및 서명 권한도 그룹화되지 않습니다 — 별도의 액세스 제어 시스템이 있습니다.
그룹은 “역방향”으로 작동하지 않습니다. 설정을 통해 그룹에서 하나의 권한을 취소하면 해당 권한만 취소되고 다른 권한은 영향을 받지 않습니다. 또한 사용자가 그룹의 대화상자를 거부해도 다른 그룹이 차단되지 않습니다 — 다른 그룹의 각 새 권한은 자체 대화상자를 표시합니다. Permission Group은 요청 UX에만 영향을 미치며 보안 모델에는 영향을 미치지 않습니다.
Android는 위험한 권한에 대해 다음과 같은 시스템 Permission Group을 정의합니다. 각 그룹에는 공통 기능적 목적으로 결합된 하나 이상의 권한이 포함됩니다.
| 그룹 식별자 | 그룹 내 권한 | 설명 |
|---|---|---|
| CAMERA | CAMERA | 기기 카메라 액세스 |
| LOCATION | ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION | 위치 정보(정확 및 대략) |
| MICROPHONE | RECORD_AUDIO | 마이크를 통한 오디오 녹음 |
| PHONE | READ_PHONE_STATE, CALL_PHONE, READ_CALL_LOG, WRITE_CALL_LOG, ADD_VOICEMAIL, USE_SIP | 전화 기능 |
| CONTACTS | READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS | 연락처 및 계정 액세스 |
| SMS | READ_SMS, SEND_SMS, RECEIVE_SMS, RECEIVE_WAP_PUSH, RECEIVE_MMS | SMS 발신 및 수신 |
| STORAGE | READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE | 외부 저장소 읽기 및 쓰기 |
| CALENDAR | READ_CALENDAR, WRITE_CALENDAR | 캘린더 액세스 |
| SENSORS | BODY_SENSORS | 신체 센서(심박수 등) |
| ACTIVITY_RECOGNITION | ACTIVITY_RECOGNITION | 신체 활동 인식 |
Android 13(API 33)에서는 BLUETOOTH_SCAN, BLUETOOTH_CONNECT 및 BLUETOOTH_ADVERTISE를 결합한 새로운 그룹 NEARBY_DEVICES가 추가되었습니다. 또한 STORAGE 그룹이 미디어 권한 READ_MEDIA_IMAGES, READ_MEDIA_VIDEO 및 READ_MEDIA_AUDIO로 부분적으로 대체되었으며, 이는 STORAGE의 일부가 아니라 그룹화 없이 독립적인 위험한 권한입니다.
개발자는 매니페스트의 permissionGroup 속성을 통해 사용자 정의 Permission Group으로 자체 권한을 선언할 수 있습니다. 그러나 이는 동일한 앱의 사용자 정의 권한에 대해서만 작동하며 시스템 UI 대화상자에는 영향을 미치지 않습니다. 실제로 사용자 정의 Permission Group은 거의 사용되지 않습니다 — 동일한 스택의 앱 간 상호 작용을 위해 사용됩니다.
Permission Group의 영향은 사용자 경험에 상당합니다. 그룹화 덕분에 사용자는 다양한 권한에 대해 8개의 개별 대화상자가 아닌 몇 개의 그룹 대화상자를 보게 됩니다. 이는 인지 부하를 줄이고 사용자가 목적을 이해하지 못한 채 중요한 권한을 거부할 가능성을 낮춥니다.
UX 연구에 따르면 그룹 대화상자는 사용자에게 더 투명하게 인식됩니다. 앱이 “카메라 액세스 권한”을 요청하면 사용자가 맥락을 이해합니다. 각 권한이 개별적으로 요청된다면 — CAMERA, CAMERA2, FLASHLIGHT — 중복성이라는 인상을 줄 것입니다. Permission Group은 이러한 세분성을 추상화합니다.
모범 사례는 한 번에 하나의 그룹에서만 권한을 요청하는 것입니다. 앱에 카메라와 위치가 모두 필요한 경우 단일 requestPermissions 호출로 요청하지 마십시오. 먼저 하나의 그룹을 왜 필요한지 설명한 후 요청하고, 그다음 두 번째 그룹을 요청하십시오. 이렇게 하면 사용자에게 제어권과 각 기능에 대한 순차적 이해를 제공할 수 있습니다.
Permission Group과 ProtectionLevel은 Android 권한 시스템의 두 가지 다른 차원입니다. ProtectionLevel은 권한 부여 방식(normal, dangerous, signature, privileged)을 결정하고, Permission Group은 UI 표시를 위한 범주입니다. 이들은 독립적이지만 실제로는 dangerous + permission group 조합이 가장 일반적입니다.
동일한 ProtectionLevel의 권한이 다른 그룹에 속할 수 있습니다. 예를 들어, ACCESS_FINE_LOCATION과 CAMERA는 모두 protectionLevel이 dangerous이지만 LOCATION과 CAMERA라는 다른 그룹에 속합니다. 반대로, 이름이 유사한 권한은 항상 동일한 그룹에 속합니다: ACCESS_FINE_LOCATION과 ACCESS_COARSE_LOCATION은 모두 LOCATION에 있습니다.
더 높은 수준의 보호 수준 — signature와 privileged — 은 UI에 Permission Group을 사용하지 않습니다. 해당 권한 부여는 시스템 수준에서 제어됩니다. signature는 시스템과 동일한 인증서로 서명된 앱에 부여되고, privileged는 시스템 이미지의 앱에 부여됩니다. 이러한 권한에 대한 그룹은 존재하지만 UX 대화상자에 영향을 미치지 않습니다. 이러한 대화상자가 표시되지 않기 때문입니다.
개발자는 PackageManager를 통해 프로그래밍 방식으로 모든 권한의 Permission Group을 확인할 수 있습니다. getPermissionInfo 메서드는 그룹의 문자열 식별자가 포함된 group 필드가 있는 PermissionInfo를 반환합니다. 이는 로깅, 분석 및 사용자 정의 권한 UI 화면에 유용합니다.
fun getPermissionGroupName(
permission: String
): String? {
return try {
val pm = packageManager
val info = pm.getPermissionInfo(
permission,
PackageManager.GET_META_DATA
)
info.group
} catch (e: NameNotFoundException) {
null
}
}
fun getPermissionsByGroup(
group: String
): List<String> {
val pm = packageManager
val perms = pm.queryPermissionsByGroup(
group,
PackageManager.GET_META_DATA
)
return perms.map { it.name }
}
Permission Group에 대한 지식은 요청 아키텍처를 구축하는 데 도움이 됩니다. 특정 그룹의 권한 목록을 반환하는 PermissionGroupProvider라는 추상화를 만들 수 있습니다. 이는 테스트를 단순화합니다. 단위 테스트에서 제공자는 PackageManager를 호출하지 않고 모의 데이터를 반환합니다. 계측 테스트에서는 시스템에서 실제 그룹을 반환합니다.
Dagger Hilt 또는 Koin을 통한 PermissionGroupProvider 통합은 권한-그룹 매핑의 중앙 집중식 관리를 가능하게 합니다. 제공자에서 PackageManager.queryPermissionsByGroup의 결과를 캐시하여 요청할 때마다 반복적인 시스템 호출을 피할 수 있습니다. 이는 권한의 전체 목록과 상태가 표시되는 설정 화면에서 특히 중요합니다.
거부에 대한 분석을 수집할 때 권한 이름뿐만 아니라 해당 Permission Group도 로깅하는 것이 유용합니다. 이를 통해 어떤 기능 영역이 가장 많은 거부를 유발하는지 식별할 수 있습니다. 예를 들어, LOCATION 그룹은 전통적으로 가장 높은 거부율을 보입니다 — Google Play Console 통계에 따르면 약 40%입니다.
그룹별 분석은 제품 결정에 도움이 됩니다. CONTACTS 그룹의 거부율이 높은 경우 요청 시기를 재고하거나 근거 설명 대화상자를 추가해야 할 수 있습니다. 분석에 대한 그룹 기반 접근 방식은 개별 권한 분석보다 더 완전한 그림을 제공합니다. 전체 그룹의 거부 횟수는 기능 영역에 대한 사용자의 전반적인 태도를 반영하기 때문입니다.
자주 묻는 질문
Permission Group은 기능적으로 관련된 위험한 권한을 하나의 범주로 결합하는 메커니즘입니다. 사용자가 그룹 내 하나의 권한을 부여하면 나머지는 추가 대화상자 없이 자동으로 부여됩니다.
표준 Android에는 약 10개의 주요 그룹이 있습니다: CAMERA, LOCATION, MICROPHONE, PHONE, CONTACTS, SMS, STORAGE, CALENDAR, SENSORS 및 ACTIVITY_RECOGNITION. Android 13+에서 NEARBY_DEVICES가 추가되었습니다.
네, 사용자 정의 권한에 대해 AndroidManifest.xml의 permissionGroup 속성을 통해 가능합니다. 그러나 이는 앱 내 권한에 대해서만 작동하며 시스템 UI 대화상자에는 영향을 미치지 않습니다. 실제로는 거의 사용되지 않습니다.
그룹에서 하나의 권한을 취소해도 다른 권한은 취소되지 않습니다. 사용자가 ACCESS_FINE_LOCATION을 비활성화해도 ACCESS_COARSE_LOCATION은 활성 상태로 유지됩니다. 그룹은 부여에만 영향을 미치고 취소에는 영향을 미치지 않습니다.
PackageManager.getPermissionInfo를 사용하고 group 필드를 읽으세요. 메서드는 그룹의 문자열 식별자를 반환합니다. 예: android.permission-group.CAMERA. 권한에 그룹이 없으면 필드는 null이 됩니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.