Frontend/Auth

앱 권한에 대한 것 / react-native-permissions

0BigLife 2022. 1. 19. 20:25
728x90

앱 권한 정리 화이팅
출처 : https://ichi.pro/assets/images/max/724/1*eUWhCErkv35_fl3HdJiZRw.png 

 앱 권한은 사용자가 특정 화면에서 이용할 수 있는 서비스에 대한 권한을 의미한다. 앱 권한은 사용자가 앱에 정보를 입력하면서 모든 권한에 대한 허용 메세지를 띄우거나, 특정 서비스를 직접 접근했을 때 메세지를 띄우기도 한다. 필자가 보기에는 카메라/앨범/위치 추적 관련 서비스를 이용하기 직전에 권한 허용 메세지를 띄우는 것이 합리적으로 보이나 최근에 살펴본 여러 앱에서는 회원가입할 때 모든 권한에 대한 메세지를 연달아 띄우는 것도 보았다. 어느 것이 더 효율적이냐는 사용자 입장에서 굉장히 세부적인 차이로 어느게 더 편리하고 접근성이 좋은지에 따라 결정하면 된다.

출처 : https://ichi.pro/assets/images/max/724/1*AMWm4LSY0XXx1N1tFXXEIA.png

 앱 권한에 대한 구현을 다루기 앞서, 사용자의 대응 방식에 대해서도 생각해볼 필요가 있다. 위 패턴은 사용자가 앱 권한에 대해 허용하지 않거나, 허용한 이후에 디바이스 설정에서 권한을 취소했을 시에 발생하는 패턴이다. 앱 권한 우리 앱 외부에서의 설정을 위해 사용자를 '디바이스 설정'으로 유도해야하며, 이 경우 Linking API 를 활용하여 하단 코드처럼 작성할 수 있다. 

import { TouchableOpacity, Linking } from 'react-native'
const Component = props => {
return (
    <TouchableOpacity
      activeOpacity={0.8}
      onPress={() => Linking.openURL('app-settings:')}
    >
      <SettingsIcon />
   </TouchableOpacity>
  );
}

 

이젠 실제 권한들을 어떻게 제어할지 구현해보자.

앱 권한을 다루기 위해 permission 관련 다운로드수가 가장 많은 'react-native-permissions'을 적용했다.

 

GitHub - zoontek/react-native-permissions: An unified permissions API for React Native on iOS and Android

An unified permissions API for React Native on iOS and Android - GitHub - zoontek/react-native-permissions: An unified permissions API for React Native on iOS and Android

github.com

 

Installation

$ npm install --save react-native-permissions
# --- or ---
$ yarn add react-native-permissions

설치를 마치고 생각해봐야할 것은 권한을 서비스 이용이 직접적으로 필요할 시 메세지를 띄울 것인지, 아니면 회원가입시 모든 권한에 대한 메세지를 한꺼번에 꺼낼 것인지이다. 후자의 경우 더 디벨롭된 케이스로는 메세지를 띄우지 않고 사용자가 버튼만 눌렀을 때, 모든 권한이 자동으로 업로드되는 것이다.(스푼 라디오가 이와 같이 구현되어있는 상태) 필자는 우선 앱 권한에 대한 설명과 버튼을 담은 UI부터 작성했다.

Code.

https://github.com/zoontek/react-native-permissions&nbsp;

너무나도 다양한 권한들이 존재하는데 이 중에서 연락처 접근, 마이크 접근, 갤러리/카메라 접근을 적용했다. 적용 방식은 생각보다 간단하다. request와 check 두 방식으로 분류되는데 요청의 경우에는 메세지를 띄우는 기능이고, check는 특정 권한의 상태를 확인하여 리턴한다. check의 경우에는 useEffect()를 활용하여 특정 화면이 켜지자마자 서비스를 위한 필요한 권한들이 잘 업로드되었는지 확인하는 용도로 쓰이면 유용해보인다. 

//권한 요청
const requestPermission = () => {
    request(PERMISSIONS.IOS.CAMERA).then(response => {
      console.log(response);
    });
  };

//허용된 권한에 대한 체킹 + logging
  const checkPermission = () => {//checkMultiple을 쓸거면 이 부분 생략 가능
    check(PERMISSIONS.IOS.CAMERA)
      .then(result => {
        switch (result) {
          case RESULTS.UNAVAILABLE:
            console.log(
              'This feature is not available (on this device / in this context)',
            );
            break;
          case RESULTS.DENIED:
            console.log(
              'The permission has not been requested / is denied but requestable',
            );
            break;
          case RESULTS.LIMITED:
            console.log('The permission is limited: some actions are possible');
            break;
          case RESULTS.GRANTED:
            console.log('The permission is granted');
            break;
          case RESULTS.BLOCKED:
            console.log('The permission is denied and not requestable anymore');
            break;
        }
      })
      .catch(error => {
        console.log('PERMISSION ERROR : ', error);
      });
  };

권한이 여러 개 필요하지 않는다면 각각 함수를 만들어 개별 코드로 제어할 수 있으나, 필자는 requestMultiple을 활용하여 한꺼번에 요청할 계획이다. 최종 코드는 다음과 같다.

const requestMultiplePermissions = () => {
    requestMultiple([
      PERMISSIONS.IOS.CONTACTS,
      PERMISSIONS.IOS.CAMERA,
      PERMISSIONS.IOS.PHOTO_LIBRARY,
      PERMISSIONS.IOS.PHOTO_LIBRARY_ADD_ONLY,
      PERMISSIONS.IOS.MICROPHONE,
    ]).then(response => {
      console.log('MULTIPLE REQUEST RESPONSE : ', response);
    });
  };

  const checkMultiplePermissions = () => {
    checkMultiple([
      PERMISSIONS.IOS.CONTACTS,
      PERMISSIONS.IOS.CAMERA,
      PERMISSIONS.IOS.PHOTO_LIBRARY,
      PERMISSIONS.IOS.PHOTO_LIBRARY_ADD_ONLY,
      PERMISSIONS.IOS.MICROPHONE,
    ]).then(response => {
      console.log('MULTIPLE CHECK RESPONSE : ', response);
    });
  };

  return (
    <Container>
      <TitleContainer>
        <Title>접근 권한 승인</Title>
        <SubTitle>해당 서비스 이용을 위한 접근 권한을 허용합니다.</SubTitle>
        <SubscriptionWrapper>
          <SubscriptionView>
            <IonIcon name="phone-portrait" size={22} color="gray" />
            <SubScriptionText>연락처 접근 권한을 허용합니다.</SubScriptionText>
          </SubscriptionView>
          <SubscriptionView>
            <IonIcon name="camera" size={22} color="gray" />
            <SubScriptionText>카메라 접근 권한을 허용합니다.</SubScriptionText>
          </SubscriptionView>
          <SubscriptionView>
            <IonIcon name="book" size={22} color="gray" />
            <SubScriptionText>갤러리 접근 권한을 허용합니다.</SubScriptionText>
          </SubscriptionView>
          <SubscriptionView>
            <IonIcon name="mic" size={22} color="gray" />
            <SubScriptionText>마이크 접근 권한을 허용합니다.</SubScriptionText>
          </SubscriptionView>
          <ButtonContainer onPress={() => requestMultiplePermissions()}> //권한 요청
            <ButtonText>권한 허용</ButtonText>
          </ButtonContainer>
        </SubscriptionWrapper>
      </TitleContainer>
    </Container>
  );

결과물 !


음.. 사용자가 만약에 '설정'에 들어가서 앱 권한을 직접 해제했을 때를 대비하여, 권한에 대한 서비스 이용이 필요할 때 위에서 말한 것과 같이 useEffect()를 활용한 라이프사이클 안에서 권한에 대한 checking을 해야할 것 같고, 해제된 권한이 확인될 시 메세지를 다시 띄워야 할 것 같다. 추가로, 메세지를 띄우지 않고 모든 권한을 허용하는 방식도 추후 적용해볼 예정이다.

728x90