
안드로이드 앱을 개발하다 보면 카메라, 위치, 연락처 등 민감한 기능에 접근해야 하는 경우가 많다. 과거에는 앱 설치 시점에 모든 권한을 한 번에 요청했지만, 안드로이드 6.0(API 23)부터 도입된 런타임 권한 시스템은 이런 방식을 완전히 바꿔놓았다. 사용자가 앱을 사용하는 중에 필요한 시점에만 권한을 요청하고, 언제든 권한을 취소할 수 있게 된 것이다.
이 글에서는 런타임 권한 시스템을 올바르게 구현하는 방법과 함께, 사용자 개인정보 보호와 좋은 사용자 경험을 동시에 달성하는 전략에 대해 살펴보겠다.
안드로이드는 권한을 보호 수준에 따라 크게 네 가지로 분류한다. 일반 권한(Normal Permission)은 인터넷 접근이나 와이파이 상태 확인 같은 것들로, 매니페스트에 선언만 하면 자동으로 부여된다. 반면 위험한 권한(Dangerous Permission)은 사용자의 개인정보나 기기의 중요한 기능에 접근하는 권한들로, 런타임에 사용자의 명시적 승인이 필요하다.
서명 권한(Signature Permission)과 시스템 권한(SignatureOrSystem)은 시스템 앱이나 플랫폼 키로 서명된 앱에서만 사용할 수 있어, 일반 개발자가 접할 일은 거의 없다.
권한을 요청하는 기본적인 흐름은 다음과 같다. 먼저 매니페스트에 필요한 권한을 선언하고, 실제로 해당 기능을 사용하기 전에 권한이 있는지 확인한다. 권한이 없다면 사용자에게 요청하고, 결과에 따라 적절히 처리한다.
// 권한 확인 및 요청
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.CAMERA),
CAMERA_PERMISSION_REQUEST_CODE
)
} else {
openCamera()
}
권한 요청 결과는 onRequestPermissionsResult 콜백에서 처리하는데, 사용자가 승인했는지 거부했는지에 따라 다른 로직을 실행해야 한다.
Android 11부터는 Activity Result API를 사용하는 것이 권장된다. 이 방식은 코드가 더 깔끔하고 생명주기 관리도 자동으로 해준다.
private val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted ->
if (isGranted) {
openCamera()
} else {
showPermissionDeniedMessage()
}
}
// 권한 요청
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
여러 권한을 동시에 요청해야 할 때는 RequestMultiplePermissions를 사용할 수 있지만, 가능하면 권한을 개별적으로 요청하는 것이 사용자 경험 측면에서 더 좋다.
위치 권한은 다른 권한들보다 더 복잡한 처리가 필요하다. 안드로이드 10부터는 백그라운드 위치 접근이 별도의 권한으로 분리되었고, 안드로이드 11부터는 일회성 권한이라는 개념이 도입되었다.
위치 권한은 크게 세 가지로 나뉜다. ACCESS_COARSE_LOCATION은 네트워크 기반의 대략적인 위치를, ACCESS_FINE_LOCATION은 GPS 기반의 정확한 위치를 제공한다. ACCESS_BACKGROUND_LOCATION은 앱이 백그라운드에 있을 때도 위치에 접근할 수 있게 해주는 권한이다.
대부분의 경우 정확한 위치가 꼭 필요하지 않다면 COARSE_LOCATION만 요청하는 것이 좋다. 사용자도 더 쉽게 승인할 가능성이 높고, 배터리 소모도 적다.
안드로이드 11부터 사용자는 위치 권한을 "이번만 허용"으로 선택할 수 있다. 이 경우 앱이 백그라운드로 가면 권한이 자동으로 해제된다. 따라서 앱이 다시 포그라운드로 올 때마다 권한 상태를 확인해야 한다.
일회성 권한이 만료되었을 때는 강제로 다시 권한을 요청하기보다는, 사용자에게 상황을 설명하고 필요에 따라 권한을 다시 요청할 수 있도록 안내하는 것이 좋다.
권한을 요청하기 전에 사용자가 왜 이 권한이 필요한지 이해할 수 있도록 충분한 컨텍스트를 제공해야 한다. 앱을 처음 실행했을 때 갑자기 카메라 권한을 요청하는 것보다는, 사용자가 프로필 사진을 설정하려 할 때 "사진 촬영을 위해 카메라 접근이 필요합니다"라고 설명하는 것이 훨씬 자연스럽다.
shouldShowRequestPermissionRationale 메서드를 활용하면 사용자가 이전에 권한을 거부한 적이 있는지 알 수 있다. 이 경우에는 더 자세한 설명을 제공하여 사용자가 마음을 바꿀 수 있도록 도와야 한다.
한 번에 여러 권한을 요청하는 것보다는 실제로 필요한 시점에 개별적으로 요청하는 것이 좋다. 예를 들어 카메라 앱이라면 처음에는 저장소 권한만 요청하고, 사용자가 사진을 찍으려 할 때 카메라 권한을, 위치 태그를 추가하려 할 때 위치 권한을 요청하는 식이다.
이런 방식은 사용자가 각 권한의 필요성을 더 잘 이해할 수 있게 해주고, 권한 요청에 대한 거부감을 줄여준다.
권한이 거부되었을 때도 앱의 핵심 기능은 사용할 수 있도록 대안을 제공해야 한다. 카메라 권한이 거부되었다면 갤러리에서 사진을 선택할 수 있게 하고, 위치 권한이 거부되었다면 수동으로 주소를 입력할 수 있게 하는 식이다.
사용자가 "다시 묻지 않음"을 선택한 경우에는 앱 설정으로 이동할 수 있는 버튼을 제공하되, 강제로 이동시키지는 말아야 한다.
런타임 권한 시스템은 사용자의 개인정보를 보호하는 중요한 메커니즘이다. 개발자로서는 이 시스템을 올바르게 이해하고 구현하여, 사용자의 신뢰를 얻으면서도 앱의 기능을 원활하게 제공해야 한다.
가장 중요한 것은 사용자의 관점에서 생각하는 것이다. 권한이 왜 필요한지 명확히 설명하고, 적절한 시점에 요청하며, 거부되었을 때도 대안을 제공한다면 사용자는 기꺼이 필요한 권한을 허용할 것이다.
권한 요청은 단순한 기술적 구현이 아니라 사용자와의 소통이다. 이런 관점으로 접근한다면 더 좋은 앱을 만들 수 있을 것이다.