[Flutter] 플러터 권한/퍼미션 획득(Get permission) 구조 설계 및 방법
플러터에서 휴대폰 장치와 관련된 접근을 위해서는 권한/퍼미션(Permission) 획득이 필요하다. 예를 들어, 주소록, 저장소, 카메라, 블루투스 등을 제어하기 위해서는 보안 등의 이유로 사용자로부터 권한 사용에 대한 승인을 받아야 한다. 오늘은 권한 획들을 위한 구조 설계를 어떻게 하고 어떤 부분들이 고려가 되어야 하는지를 위주로 살펴보겠다.
1. 방법
플러터의 특징이기도 하지만 일정한 단위의 기능 요소들은 패키지화가 잘 되어 있어서 해당 패키지를 설치하는 것만으로도 상당 부분 기능 구현은 쉽게 되어있다.
필자가 본 블로그의 실험실에서 진행했던 PhotoRoll 프로젝트에서도 이런 패키지를 이용하여 해당 기능을 적용하였다.
1.1. 관련 패키지
권한/퍼미션(Permission) 처리 관련하여 가장 대중적으로 많이 사용되고 있는 패키지(Package)는 아래와 같다.
많은 개발자들이 주로 Permission handler와 Permission 패키지를 사용하고 있는 것으로 보이며, 필자의 경우에는 개발 소스 적합성과 테스트를 통해 세번째 패키지인 Permissions_plugin을 이용하여 권한 관련 기능을 구현하였다.
1.2. 문제점
1.2.1. 권한 획득 코드 실행 시점
보통의 경우 아래와 같이 앱이 실행되면 메인 화면(Main route)이 실행되는 것이 일반적인 앱 실행과 화면 구조가 될 것이다.
이 경우 권한 획득과 관련한 실행코드는 아래 그림과 같이 메인 화면에서 실행이 된다. 이 경우 사용자가 앱에서의 권한 사용을 승인했는지 거절했는지 여부와 상관없이 메인 화면이 출력되거나 메인 화면이 출력되고 나서 권한을 거절했을 때 어떻게 처리할지 등의 시나리오가 굉장히 복잡해질 수 밖에 없다.
특히 iOS에서는 사용자가 앱에서의 권한 사용을 거절하고 나면 다음 번에 앱을 종료 후에 다시 실행해도 권한 사용 요청을 앱에서 할 수 없다는 것은 이러한 시나리오 처리 상의 치명적 문제를 야기할 가능성이 높아진다. 반면 안드로이드에서는 사용자가 권한 사용을 거절한 경우라도 다음 번 앱을 실행하는 과정에서 해당 권한에 대한 사용 승인을 이전에 받은 상태인지 여부를 체크해서 해당 권한에 대한 사용 요청을 다시 할 수 있다는 점에서 시나리오 설계 상의 차이는 있을 수 있다.
정리하면 iOS에서는 이전 앱 실행 시, 권한 사용 승인 상태를 체크를 해서 권한이 없는 상태라고 하더라도 한번 사용자가 거절한 권한은 사용자가 직접 OS 설정화면으로 이동하여 직접 설정하지 않는 이상 해당 앱에서 권한 승인 요청을 반복할 수 없도록 되어 있다.
이러한 이유로 필자는 다음과 같은 방식의 설계가 가장 타당한 방식이라고 생각했다. 우선 앱이 실행되면 스플래시(Splash) 화면(앱 로딩 시 출력되는 덤프 화면으로 ‘카카오톡’을 실행하면 처음 출력되는 카카오톡 로고 화면이 대표적이다.)을 출력하고, 여기에서 해당 권한 사용에 대한 승인 요청을 하고, 권한 사용을 승인하면 메인 화면(Main route)으로 분기하고, 권한 사용을 거절하면 앱을 종료하는 시나리오로 설계하였다.
이런 시나리오를 채택한 이유는 우선 대부분의 사용자가 권한 설정에 대한 이해도가 낮다고 생각했기 때문에, 스플래시(Splash) 화면에서 권한 획득 상태 여부를 체크하여 권한이 획득되지 않았다면 앱을 종료시키는 시나리오가 가장 단순하고 쉬운 방법이라고 판단했다.
예를 들어, iOS 같은 경우에는 권한 획득 상태 여부를 체크해도 다시 권한 사용에 대한 요청을 할 수 없기 때문에 메인 화면으로 이동을 시켜버리고 나면 사용자에게 권한 설정을 위한 안내를 매우 복잡하게 안내를 하는 방법 밖에 없다. 게다가 iOS의 경우에는 이러한 권한 설정을 위한 페이지 이동도 사용자가 직접 해야 되는 심각한 문제가 발생한다.
그것보다는 권한이 획득되지 않아 앱을 종료한다는 메시지와 함께 앱을 다시 설치하고 시도하라는 안내 메시지를 출력하는 것이 사용자가 문제를 해결하는 더 간단하고 단순한 방법이라고 생각했기 때문이다.
1.3. 설계구조
코드 설계 구조는 아래와 같이 적용하였다. 설계 내용을 간단히 설명하면 권한이 획득된 상태(이전에 권한을 승인하고 재실행한 상태)라면 바로 메인화면으로 이동하도록 하였다. 이 외에 앱을 처음 실행했거나 이전 실행에서 권한을 거절한 상태로 앱을 실행한 거라면 권한 요청을 다시 하여 승인을 하면 메인화면으로 이동하고, 거절하면 앱을 종료하도록 처리하였다. 이렇게 되면 iOS에서 사용자가 한번 거절한 권한을 앱에서 다음번 실행에서 다시 요청할 수 없더라도 앱을 종료처리할 수 있는 분기처리가 가능해진다.
추가적으로 검토한 부분은 메인 화면이 실행한 상태에서도 권한 상태를 체크해서 권한이 없는 상태라면 앱을 종료하는 시나리오를 적용하였다. 이 경우 사용자가 앱을 실행하는 과정에서 권한을 강제로 회수하는 경우를 대비하기 위한 예외 시나리오로써 실시간으로 권한을 체크하는 것은 아니지만 메인 화면이 출력되는 과정에서라도 권한 체크를 할 수 있도록 하였다.
2. 추가논의
2.1. 여러 권한에 대한 부분 승인 및 처리 시나리오
다행스럽게도 이러한 부분들은 위에서 설명한 패키지들에서 map 구조로 여러가지 권한에 대한 부분 승인 등의 예외 처리는 권한 check와 request하는 과정에서 간단하게 처리할 수 있도록 설계가 되어 있기 때문에 크게 고려하지 않아도 된다.
2.2. 앱 종료
앱을 종료시키는 코드 및 방식이 OS 버전이 업데이트 됨에 따라 변경된 부분이 있다고 한다. 플러터(Flutter)에서 공식적으로 권장하는 방식은 해당 링크를 참조하도록 한다.
2.3. 기타 화면 이동 및 앱 종료 관련 피드백 처리
해당 시나리오를 적용하는 과정에서 스플래시(Splash) 화면 이동 및 처리 등의 방식이 생각처럼 해당 패키지를 사용하는 것으로 단순하게 처리되지 않는 것이 확인되었다. 해당 요소는 다음 챕터에서 별도 주제로 다룰 예정이다.
댓글
댓글 쓰기