앱 권한은 사용자가 특정 화면에서 이용할 수 있는 서비스에 대한 권한을 의미한다. 앱 권한은 사용자가 앱에 정보를 입력하면서 모든 권한에 대한 허용 메세지를 띄우거나, 특정 서비스를 직접 접근했을 때 메세지를 띄우기도 한다. 필자가 보기에는 카메라/앨범/위치 추적 관련 서비스를 이용하기 직전에 권한 허용 메세지를 띄우는 것이 합리적으로 보이나 최근에 살펴본 여러 앱에서는 회원가입할 때 모든 권한에 대한 메세지를 연달아 띄우는 것도 보았다. 어느 것이 더 효율적이냐는 사용자 입장에서 굉장히 세부적인 차이로 어느게 더 편리하고 접근성이 좋은지에 따라 결정하면 된다.
앱 권한에 대한 구현을 다루기 앞서, 사용자의 대응 방식에 대해서도 생각해볼 필요가 있다. 위 패턴은 사용자가 앱 권한에 대해 허용하지 않거나, 허용한 이후에 디바이스 설정에서 권한을 취소했을 시에 발생하는 패턴이다. 앱 권한 우리 앱 외부에서의 설정을 위해 사용자를 '디바이스 설정'으로 유도해야하며, 이 경우 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'을 적용했다.
Installation
$ npm install --save react-native-permissions
# --- or ---
$ yarn add react-native-permissions
설치를 마치고 생각해봐야할 것은 권한을 서비스 이용이 직접적으로 필요할 시 메세지를 띄울 것인지, 아니면 회원가입시 모든 권한에 대한 메세지를 한꺼번에 꺼낼 것인지이다. 후자의 경우 더 디벨롭된 케이스로는 메세지를 띄우지 않고 사용자가 버튼만 눌렀을 때, 모든 권한이 자동으로 업로드되는 것이다.(스푼 라디오가 이와 같이 구현되어있는 상태) 필자는 우선 앱 권한에 대한 설명과 버튼을 담은 UI부터 작성했다.
Code.
너무나도 다양한 권한들이 존재하는데 이 중에서 연락처 접근, 마이크 접근, 갤러리/카메라 접근을 적용했다. 적용 방식은 생각보다 간단하다. 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을 해야할 것 같고, 해제된 권한이 확인될 시 메세지를 다시 띄워야 할 것 같다. 추가로, 메세지를 띄우지 않고 모든 권한을 허용하는 방식도 추후 적용해볼 예정이다.
'Frontend > Auth' 카테고리의 다른 글
휴대폰 본인인증 구현 (0) | 2022.01.20 |
---|---|
사용자 유입에 대한 플로우 정리 (0) | 2022.01.19 |
애플 소셜 로그인(1) / @invertase/react-native-apple-authentication (0) | 2022.01.19 |
구글 소셜 로그인(2) / @react-native-google-signin/google-signin (0) | 2021.12.24 |
구글 소셜 로그인(1) / @react-native-google-signin/google-signin (2) | 2021.12.24 |