Intro
권한 요청에 대해서 따로 공부해본적 없어 일하는데 조금 부족함을 느꼈다.
공식문서를 읽으며 안드로이드 런타임 권한 요청에 대해 공부해보자.
권한 요청 종류
먼저 안드로이드의 권한 요청에는 두 가지가 있다. install-time, Runtime
1. Install-time permission
앱의 샌드박스 영역을 벗어난 데이터나 작업에 접근할 수 있도록 허용하지만, 사용자의 프라이버시에 제한적인 위험만을 초래하는 데이터(상대적으로 덜 위험한 권한)에 한한다. 예시로 인터넷 권한이 있다.
Android 플랫폼은 Linux 사용자 기반 보호 기능을 활용하여 앱 리소스를 식별하고 분리한다. 이러한 방법으로 앱을 서로 분리하고 앱과 시스템을 악성 앱으로부터 보호한다. 이를 위해 Android는 각 Android 애플리케이션에 고유한 사용자 ID(UID)를 할당하여 자체 프로세스에서 실행한다. Android는 UID를 사용하여 커널 수준의 애플리케이션 샌드박스를 설정한다.
https://source.android.com/docs/security/app-sandbox?hl=ko
애플리케이션 샌드박스 | Android Open Source Project
2025년 3월 27일부터 AOSP를 빌드하고 기여하려면 aosp-main 대신 android-latest-release를 사용하는 것이 좋습니다. 자세한 내용은 AOSP 변경사항을 참고하세요. 이 페이지는 Cloud Translation API를 통해 번역되
source.android.com
요약하자면, Android 는 커널 수준에서 샌드박스를 설정하여 앱과 앱을 서로 분리하고 보호한다.
2. Runtime permissions
사용자의 개인정보에 관련된 데이터에 접근 권한을 부여한다. 예시로 사진, 알림, 위치 권한 등이 있다.
이 중에서 런타임 권한을 어떻게 요청하는지 좀 더 깊게 알아보자.
런타임 권한 요청
런타임 권한을 요청하기 위한 기본 원칙은 다음과 같다.
- 사용자가 권한이 필요한 기능과 상호작용하기 시작할 때 컨텍스트에 따라 권한을 요청합니다.
- 사용자를 차단하지 않습니다. 교육용 UI 흐름(예: 권한 요청의 근거를 설명하는 흐름)을 취소하는 옵션을 항상 제공합니다.
- 사용자가 기능에 필요한 권한을 거부하거나 취소하면 권한이 필요한 기능을 사용 중지하는 등의 방법으로 앱의 성능을 단계적으로 저하시켜 사용자가 앱을 계속 사용할 수 있도록 합니다.
- 시스템 동작을 가정하지 않습니다. 예를 들어 여러 권한이 동일한 권한 그룹에 표시된다고 가정하지 마세요. 권한 그룹은 앱이 밀접하게 관련된 여러 권한을 요청할 때 시스템에서 사용자에게 표시하는 시스템 대화상자의 수를 최소화하는 데만 도움이 됩니다.
권한이 필요한 기능을 사용할 때 권한을 요청해야하고, 권한을 거부하더라도 앱을 계속 사용할 수 있게 해야한다. 마지막 원칙은 잘 이해가 되지 않는다.
마지막 원칙에 대해 이해가 잘 되지 않았는데 아래 글을 읽어보길 추천 받았다. 혹시 이해가 안되는 독자가 있다면 추천한다.
https://developer.android.com/guide/topics/permissions/overview#groups
- 권한 그룹은 연관있는 권한(e.g. 메세지 전송 권한, 수신 권한)을 카테고리화해서, 사용자에게 필요한 권한 목록을 한 UI에 담아서 보여준다. 하지만 권한 그룹이 예고없이 변경될 가능성이 있어 특정 권한이 특정 그룹에 속할 것이라고 함부로 가정하면 안된다. 따라서 시스템의 권한 요청 로직을 개발자가 완전히 제어할 수 없다는 것을 의미한다
Android에서의 권한 | Privacy | Android Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. Android에서의 권한 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 앱 권한은 다음 항목에 대한 액세스
developer.android.com
런타임 권한 요청 워크플로
권한 요청이 정말 필요한지 판단한 후에 다음과 같은 단계로 권한을 요청할 수 있다. 권한 요청 워크플로는 8 단계로 이루어져있다.

- 앱의 매니페스트에 권한을 선언한다.
- 앱의 특정 작업이 알맞은 런타임 권한과 연결되도록 앱의 UX를 설계한다. 앱이 비공개 사용자 데이터(Private User Data)에 액세스하도록 권한을 부여해야 할 수 있는 작업을 사용자에게 알린다.
- 사용자가 권한이 필요한 작업을 실행할 때까지 기다린다. 실행하면 런타임 권한을 요청한다.
- 사용자가 이미 앱에 필요한 런타임 권한을 부여했는지 확인한다. 런타임 권한이 필요한 작업을 실행할 때마다 권한이 있는지 확인해야 한다.
권한 부여 O -> 비공개 사용자 데이터에 액세스할 수 있다.
권한 부여 X -> 다음 단계로 이동 - 사용자에게 앱에서 근거를 표시해야하는지 확인한다.
설명이 필요 O -> 근거를 UI 요소로 표시한다. 앱이 액세스하려는 데이터가 무엇인지, 런타임 권한을 부여하면 앱이 사용자에게 제공할 수 있는 이점이 무엇인지 명확하게 설명해야 한다.
설명이 필요 X -> 다음 단계로 이동 - 앱에서 비공개 사용자 데이터에 액세스하는 데 필요한 런타임 권한을 요청한다.
- 런타임 권한 부여를 선택했는지 또는 거부를 선택했는지 사용자의 응답을 확인한다.
- 권한 허용 O -> 비공개 사용자 데이터에 액세스할 수 있다.
권한 허용 X -> 사용자에게 기능을 제공하도록 앱 환경의 성능을 단계적으로 저하한다.
권한 요청 및 작업 실행
이제 권한이 필요한 작업일 때 권한 요청하는 과정을 코드로 살펴보자.
Activity 또는 Fragment 초기화 로직에서 다음과 같이 ActivityResultCallback 을 정의한다. 시스템 다이얼로그로 사용자에게 권한 요청을 했을 때 응답에 따라 어떻게 처리할지 정의할 수 있다.
val requestPermissionLauncher =
registerForActivityResult(RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
// 권한을 부여했으니 기능 실행
} else {
// 권한을 거부하였기 때문에 기능을 사용하지 못함을 사용자에게 알린다.
// 동시에 거부했다고해서 바로 설정 화면으로 넘기거나 하지말라. 사용자의 결정을 존중하라.
}
}
이제 권한이 필요한 기능을 사용할 때 권한 요청 로직을 수행한다.
when {
ContextCompat.checkSelfPermission(
context,
Manifest.permission.REQUESTED_PERMISSION
) == PackageManager.PERMISSION_GRANTED -> {
// 권한이 이미 있음.
}
ActivityCompat.shouldShowRequestPermissionRationale(
this, Manifest.permission.REQUESTED_PERMISSION) -> {
// 권한이 이 기능에 왜 필요한지, 어떤 권한이 필요한지 자세히 설명한다.
// 권한을 거부했을 때 사용할 수 없는 기능을 설명한다.
// 이 UI에는 사용자가 권한을 부여하지 않고도 앱을 계속 사용할 수 있도록
// “취소” 또는 “괜찮아요” 버튼을 포함한다.
showInContextUI(...)
}
else -> {
// 권한을 요청한다. 다시 묻지 않음 상태면 실행되지 않는다.
requestPermissionLauncher.launch(
Manifest.permission.REQUESTED_PERMISSION)
}
}
requestPermissions(), onRequestPermissionsResult() 를 사용해 직접 권한을 요청할 수도 있다고 공식문서에서 설명되어있지만 현재 Deprecated 되었다.

이 메서드는 ActivityResultContract를 통해 타입 안전성이 강화된 Activity Result API를 사용하기 위해 더 이상 권장되지 않는다. android.activity.result.contract 패키지에서 제공하는 사전 구성된 여러 인텐트 계약을 사용할 수 있으며, ActivityResultContracts는 테스트를 위한 훅(hook)을 제공하고, 프래그먼트와 독립적인 별도의 테스트 가능한 클래스에서 결과를 받을 수 있도록 해준다.
권한 거부 처리
사용자가 권한을 거부하면 거부에 따른 영향을 이해하도록 지원해야한다. 권한이 없어서 작동하지 않는 기능을 사용자가 인식하도록 해야한다. 권장 사항은 다음과 같다.
- 사용자의 주의를 유도한다. 앱에 필요한 권한이 없어서 기능이 제한된 앱 UI의 특정 부분을 강조표시한다.
- 자세히 설명한다. 일반적인 메시지는 표시하지 않아야한다. 대신 앱에 필요한 권한이 없어서 어떤 기능을 사용할 수 없는지 명확히 설명한다.
- UI 를 차단하지 않는다. 앱을 계속 사용하는 것을 막는 전체 화면 경고 메시지를 표시하지 않는다.
동시에 앱은 권한을 거부하겠다는 사용자의 결정을 존중해야 한다. Android 11(API 수준 30)부터 사용자가 앱이 기기에 설치된 전체 기간 동안 특정 권한에 관해 거부를 두 번 이상 탭하면 앱에서 그 권한을 다시 요청하는 경우 사용자에게 시스템 권한 대화상자가 표시되지 않는다.이러한 사용자의 작업은 '다시 묻지 않음'을 의미한다.
Outro
오늘은 런타임 권한 요청에 대해 간단하게 알아보았다.
권한이 필요한 기능이 많은데 권한을 어떻게하면 잘 얻을 수 있을지 고민해봐야겠다.
'Android' 카테고리의 다른 글
Nested Scrollable List in Android Views (RecyclerView 를 사용한 중첩 스크롤 방식) (0) | 2025.01.09 |
---|---|
[페스타고] 안드로이드에서 중첩된 페이지는 어떻게 개발해야 할까 (0) | 2024.06.17 |
페스타고 상세 페이지 이동 애니메이션 변경 및 UX 개선 (0) | 2024.05.12 |
[Android] Encryption & Decryption in Android (0) | 2024.01.10 |
[안드로이드] DataStore 이해하기 (0) | 2024.01.08 |
Intro
권한 요청에 대해서 따로 공부해본적 없어 일하는데 조금 부족함을 느꼈다.
공식문서를 읽으며 안드로이드 런타임 권한 요청에 대해 공부해보자.
권한 요청 종류
먼저 안드로이드의 권한 요청에는 두 가지가 있다. install-time, Runtime
1. Install-time permission
앱의 샌드박스 영역을 벗어난 데이터나 작업에 접근할 수 있도록 허용하지만, 사용자의 프라이버시에 제한적인 위험만을 초래하는 데이터(상대적으로 덜 위험한 권한)에 한한다. 예시로 인터넷 권한이 있다.
Android 플랫폼은 Linux 사용자 기반 보호 기능을 활용하여 앱 리소스를 식별하고 분리한다. 이러한 방법으로 앱을 서로 분리하고 앱과 시스템을 악성 앱으로부터 보호한다. 이를 위해 Android는 각 Android 애플리케이션에 고유한 사용자 ID(UID)를 할당하여 자체 프로세스에서 실행한다. Android는 UID를 사용하여 커널 수준의 애플리케이션 샌드박스를 설정한다.
https://source.android.com/docs/security/app-sandbox?hl=ko
애플리케이션 샌드박스 | Android Open Source Project
2025년 3월 27일부터 AOSP를 빌드하고 기여하려면 aosp-main 대신 android-latest-release를 사용하는 것이 좋습니다. 자세한 내용은 AOSP 변경사항을 참고하세요. 이 페이지는 Cloud Translation API를 통해 번역되
source.android.com
요약하자면, Android 는 커널 수준에서 샌드박스를 설정하여 앱과 앱을 서로 분리하고 보호한다.
2. Runtime permissions
사용자의 개인정보에 관련된 데이터에 접근 권한을 부여한다. 예시로 사진, 알림, 위치 권한 등이 있다.
이 중에서 런타임 권한을 어떻게 요청하는지 좀 더 깊게 알아보자.
런타임 권한 요청
런타임 권한을 요청하기 위한 기본 원칙은 다음과 같다.
- 사용자가 권한이 필요한 기능과 상호작용하기 시작할 때 컨텍스트에 따라 권한을 요청합니다.
- 사용자를 차단하지 않습니다. 교육용 UI 흐름(예: 권한 요청의 근거를 설명하는 흐름)을 취소하는 옵션을 항상 제공합니다.
- 사용자가 기능에 필요한 권한을 거부하거나 취소하면 권한이 필요한 기능을 사용 중지하는 등의 방법으로 앱의 성능을 단계적으로 저하시켜 사용자가 앱을 계속 사용할 수 있도록 합니다.
- 시스템 동작을 가정하지 않습니다. 예를 들어 여러 권한이 동일한 권한 그룹에 표시된다고 가정하지 마세요. 권한 그룹은 앱이 밀접하게 관련된 여러 권한을 요청할 때 시스템에서 사용자에게 표시하는 시스템 대화상자의 수를 최소화하는 데만 도움이 됩니다.
권한이 필요한 기능을 사용할 때 권한을 요청해야하고, 권한을 거부하더라도 앱을 계속 사용할 수 있게 해야한다. 마지막 원칙은 잘 이해가 되지 않는다.
마지막 원칙에 대해 이해가 잘 되지 않았는데 아래 글을 읽어보길 추천 받았다. 혹시 이해가 안되는 독자가 있다면 추천한다.
https://developer.android.com/guide/topics/permissions/overview#groups
- 권한 그룹은 연관있는 권한(e.g. 메세지 전송 권한, 수신 권한)을 카테고리화해서, 사용자에게 필요한 권한 목록을 한 UI에 담아서 보여준다. 하지만 권한 그룹이 예고없이 변경될 가능성이 있어 특정 권한이 특정 그룹에 속할 것이라고 함부로 가정하면 안된다. 따라서 시스템의 권한 요청 로직을 개발자가 완전히 제어할 수 없다는 것을 의미한다
Android에서의 권한 | Privacy | Android Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. Android에서의 권한 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 앱 권한은 다음 항목에 대한 액세스
developer.android.com
런타임 권한 요청 워크플로
권한 요청이 정말 필요한지 판단한 후에 다음과 같은 단계로 권한을 요청할 수 있다. 권한 요청 워크플로는 8 단계로 이루어져있다.

- 앱의 매니페스트에 권한을 선언한다.
- 앱의 특정 작업이 알맞은 런타임 권한과 연결되도록 앱의 UX를 설계한다. 앱이 비공개 사용자 데이터(Private User Data)에 액세스하도록 권한을 부여해야 할 수 있는 작업을 사용자에게 알린다.
- 사용자가 권한이 필요한 작업을 실행할 때까지 기다린다. 실행하면 런타임 권한을 요청한다.
- 사용자가 이미 앱에 필요한 런타임 권한을 부여했는지 확인한다. 런타임 권한이 필요한 작업을 실행할 때마다 권한이 있는지 확인해야 한다.
권한 부여 O -> 비공개 사용자 데이터에 액세스할 수 있다.
권한 부여 X -> 다음 단계로 이동 - 사용자에게 앱에서 근거를 표시해야하는지 확인한다.
설명이 필요 O -> 근거를 UI 요소로 표시한다. 앱이 액세스하려는 데이터가 무엇인지, 런타임 권한을 부여하면 앱이 사용자에게 제공할 수 있는 이점이 무엇인지 명확하게 설명해야 한다.
설명이 필요 X -> 다음 단계로 이동 - 앱에서 비공개 사용자 데이터에 액세스하는 데 필요한 런타임 권한을 요청한다.
- 런타임 권한 부여를 선택했는지 또는 거부를 선택했는지 사용자의 응답을 확인한다.
- 권한 허용 O -> 비공개 사용자 데이터에 액세스할 수 있다.
권한 허용 X -> 사용자에게 기능을 제공하도록 앱 환경의 성능을 단계적으로 저하한다.
권한 요청 및 작업 실행
이제 권한이 필요한 작업일 때 권한 요청하는 과정을 코드로 살펴보자.
Activity 또는 Fragment 초기화 로직에서 다음과 같이 ActivityResultCallback 을 정의한다. 시스템 다이얼로그로 사용자에게 권한 요청을 했을 때 응답에 따라 어떻게 처리할지 정의할 수 있다.
val requestPermissionLauncher =
registerForActivityResult(RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
// 권한을 부여했으니 기능 실행
} else {
// 권한을 거부하였기 때문에 기능을 사용하지 못함을 사용자에게 알린다.
// 동시에 거부했다고해서 바로 설정 화면으로 넘기거나 하지말라. 사용자의 결정을 존중하라.
}
}
이제 권한이 필요한 기능을 사용할 때 권한 요청 로직을 수행한다.
when {
ContextCompat.checkSelfPermission(
context,
Manifest.permission.REQUESTED_PERMISSION
) == PackageManager.PERMISSION_GRANTED -> {
// 권한이 이미 있음.
}
ActivityCompat.shouldShowRequestPermissionRationale(
this, Manifest.permission.REQUESTED_PERMISSION) -> {
// 권한이 이 기능에 왜 필요한지, 어떤 권한이 필요한지 자세히 설명한다.
// 권한을 거부했을 때 사용할 수 없는 기능을 설명한다.
// 이 UI에는 사용자가 권한을 부여하지 않고도 앱을 계속 사용할 수 있도록
// “취소” 또는 “괜찮아요” 버튼을 포함한다.
showInContextUI(...)
}
else -> {
// 권한을 요청한다. 다시 묻지 않음 상태면 실행되지 않는다.
requestPermissionLauncher.launch(
Manifest.permission.REQUESTED_PERMISSION)
}
}
requestPermissions(), onRequestPermissionsResult() 를 사용해 직접 권한을 요청할 수도 있다고 공식문서에서 설명되어있지만 현재 Deprecated 되었다.

이 메서드는 ActivityResultContract를 통해 타입 안전성이 강화된 Activity Result API를 사용하기 위해 더 이상 권장되지 않는다. android.activity.result.contract 패키지에서 제공하는 사전 구성된 여러 인텐트 계약을 사용할 수 있으며, ActivityResultContracts는 테스트를 위한 훅(hook)을 제공하고, 프래그먼트와 독립적인 별도의 테스트 가능한 클래스에서 결과를 받을 수 있도록 해준다.
권한 거부 처리
사용자가 권한을 거부하면 거부에 따른 영향을 이해하도록 지원해야한다. 권한이 없어서 작동하지 않는 기능을 사용자가 인식하도록 해야한다. 권장 사항은 다음과 같다.
- 사용자의 주의를 유도한다. 앱에 필요한 권한이 없어서 기능이 제한된 앱 UI의 특정 부분을 강조표시한다.
- 자세히 설명한다. 일반적인 메시지는 표시하지 않아야한다. 대신 앱에 필요한 권한이 없어서 어떤 기능을 사용할 수 없는지 명확히 설명한다.
- UI 를 차단하지 않는다. 앱을 계속 사용하는 것을 막는 전체 화면 경고 메시지를 표시하지 않는다.
동시에 앱은 권한을 거부하겠다는 사용자의 결정을 존중해야 한다. Android 11(API 수준 30)부터 사용자가 앱이 기기에 설치된 전체 기간 동안 특정 권한에 관해 거부를 두 번 이상 탭하면 앱에서 그 권한을 다시 요청하는 경우 사용자에게 시스템 권한 대화상자가 표시되지 않는다.이러한 사용자의 작업은 '다시 묻지 않음'을 의미한다.
Outro
오늘은 런타임 권한 요청에 대해 간단하게 알아보았다.
권한이 필요한 기능이 많은데 권한을 어떻게하면 잘 얻을 수 있을지 고민해봐야겠다.
'Android' 카테고리의 다른 글
Nested Scrollable List in Android Views (RecyclerView 를 사용한 중첩 스크롤 방식) (0) | 2025.01.09 |
---|---|
[페스타고] 안드로이드에서 중첩된 페이지는 어떻게 개발해야 할까 (0) | 2024.06.17 |
페스타고 상세 페이지 이동 애니메이션 변경 및 UX 개선 (0) | 2024.05.12 |
[Android] Encryption & Decryption in Android (0) | 2024.01.10 |
[안드로이드] DataStore 이해하기 (0) | 2024.01.08 |