/Technology/Mobile Programming

모바일 앱 개발자라면 꼭 알아야 할 권한 요청 흐름

MobileProgramming

By Noah
||5
광고

사용자가 앱을 처음 깔았을 때, "앨범 접근 허용할까요?" 이런 팝업이 나타나죠? 이게 그냥 뜨는 게 아니에요. 개발자가 정교하게 설계한 흐름이 있어요. 오늘은 그 뒤에 숨은 "권한 요청" 로직을 풀어볼게요.


권한 상태값(PermissionStatus)이란?

앱이 특정 권한(카메라, 마이크, 위치, 사진첩 등)에 대해 요청할 때마다 상태값이 존재해요. 이 상태값에 따라 다음 액션이 결정되는 거죠.

안드로이드와 iOS, 왜 달라?

먼저 중요한 포인트: 안드로이드와 iOS는 권한 시스템이 완전히 다르다는 거예요.

🍎 iOS에만 있는 상태들

iOS는 권한의 세부 상태를 더 자세하게 분류해요.

상태

의미

예시

granted

권한 허용됨

사용자가 "허용" 탭함

denied

권한 거부됨

사용자가 "거부" 탭함

undetermined

아직 요청 전

팝업이 한 번도 안 뜬 상태

restricted

시스템 차원에서 차단

자녀보호 설정, MDM(회사 기기) 정책

limited

일부만 허용

사진첩에서 특정 사진만 선택해서 허용

🤖 안드로이드는 단순해요

안드로이드는 기술적 특성상, 앱이 권한을 요청한 적 없으면 그냥 denied로 취급해요. undeterminedrestricted 같은 상태는 없어요.

상태

의미

granted

권한 허용됨

denied

권한 거부됨 (또는 아직 요청 전)

정리하면: iOS는 섬세하고, 안드로이드는 심플하다!


canAskAgain — 재요청이 가능한가?

사용자가 권한을 거부했을 때(denied), 바로 다시 물어볼 수 있을까요? 여기서 canAskAgain 플래그가 나타나요.

canAskAgain = true  →  시스템 팝업 재요청 가능 (아직 기회 남음)
canAskAgain = false →  시스템 팝업 못 띄움 (사용자가 "다시 묻지 말기" 선택)

사용자가 팝업을 거부하고 "다시 묻지 마세요"를 눌렀을 때 canAskAgainfalse로 바뀌어요. 이때는 시스템 팝업을 다시 띄울 수 없고, 대신 설정 앱으로 유도해야 해요.


실전: 권한 요청 흐름도

권한 요청 시작
    ↓
권한 상태 확인 getPermissionAsync()
    ├─→ status = 'granted'  →  ✅ 기능 실행
    │
    ├─→ status = 'denied'
    │   ├─→ canAskAgain = true   →  🔄 재요청 팝업 띄우기
    │   └─→ canAskAgain = false  →  ⚙️  설정 앱으로 유도
    │
    ├─→ status = 'undetermined'  →  (iOS만) 커스텀 Alert 후 요청
    │
    └─→ status = 'limited'       →  (iOS만) 기능 부분 실행

실제 코드로 구현하면 이래요:

const { status, canAskAgain } = await requestPermissionsAsync();

if (status === 'granted') {
  // ✅ 권한 있음 → 기능 실행
} else if (canAskAgain) {
  // 🔄 재요청 가능 → 다시 한 번 물어보기
} else {
  // ⚙️  재요청 불가 → 설정 앱 열기
  Linking.openSettings();
}

권한을 요청하는 베스트 타이밍

"언제 권한 요청 팝업을 띄울까?" 이것도 중요한 결정이에요.

❌ 앱 시작할 때 바로 요청

앱을 깔자마자 "카메라 접근 허용?", "마이크 접근 허용?" 이렇게 터져 나오면?

  • 사용자는 맥락이 없어서 일단 거부해요

  • 거부율이 엄청 높아요

  • 첫인상이 별로예요

✅ 기능을 사용하려는 순간에 요청

사용자가 "사진 올리기" 버튼을 눌렀을 때:

  • 사용자가 왜 권한이 필요한지 이해해요

  • 심리적 저항감이 훨씬 낮아요

  • 승인율이 훨씬 높아요

당신이 유튜브를 깔았을 때, 바로 카메라를 달라고 하지 않죠? 라이브 방송을 하려고 탭했을 때 물어본다는 거예요.


iOS 특별 전략: Pre-permission 패턴

여기가 중요해요. iOS의 시스템 팝업은 한 번만 뜬다는 게 핵심이에요.

사용자가 처음 팝업에서 "거부"를 탭하면? 다시는 그 팝업이 안 떠요. 개발자가 어떻게 해도 못 띄워요. 시스템이 보호하는 거죠.

그래서 앱 개발자들은 이런 전략을 써요:

[Step 1] 커스텀 Alert 띄우기
  "앨범 접근이 필요합니다"
  
  사용자 선택 ↓
  
[Step 2-A] "허용할게요" 탭
  → 시스템 팝업 표시
  
[Step 2-B] "괜찮아요" 탭
  → 아무것도 안 함 (팝업 기회 보존!)

핵심: 커스텀 Alert에서 거부했으면, 시스템 팝업을 띄우지 않는다! 그럼 다음번에 또 물어볼 기회가 남잖아요.

코드로 보면

// iOS에서 상태가 'undetermined' (= 팝업 미표시 상태)라면
if (Platform.OS === 'ios' && status === 'undetermined') {
  // 커스텀 Alert를 먼저 띄운다
  await new Promise<void>((resolve) => {
    Alert.alert(
      '사진 접근 안내',
      '게시물에 사진을 첨부하려면 앨범 접근이 필요합니다.',
      [
        { 
          text: '괜찮아요', 
          style: 'cancel', 
          onPress: () => resolve()  // 아무것도 안 하고 종료
        },
        {
          text: '허용할게요',
          onPress: async () => {
            // 여기서만 시스템 팝업 띄운다
            await ImagePicker.requestMediaLibraryPermissionsAsync();
            resolve();
          },
        },
      ],
    );
  });
  return;  // 함수 끝
}

이게 왜 중요한가?

  • 첫 번째 기회를 낭비하지 않아요

  • 사용자가 거부했을 때 다시 물어볼 수 있어요

  • 승인율을 높일 수 있어요


안드로이드는 어떻게?

안드로이드는 iOS와 다르게 권한을 여러 번 요청할 수 있어요. 그래서 iOS처럼 복잡한 전략이 필요 없어요.

대신 안드로이드는 이런 특성이 있어요:

  1. 사용자가 거부하고 "다시 묻지 말기" 선택 → canAskAgain = false

  2. 이때는 설정 앱으로 유도

  3. 근데 여러 번 요청할 수 있으니까, "지금은 필요 없나?"라고 물어보고 나중에 다시 물어볼 수도 있어요


권한 요청 플로우: 실전 체크리스트

앱에 권한 요청 로직을 추가할 때 이 순서로 확인하세요:

  • [ ] Step 1 — 사용자가 기능을 실제로 사용하려고 탭했는가? (앱 시작 시 아님)

  • [ ] Step 2 — 현재 권한 상태를 확인했는가? (granted, denied, undetermined 등)

  • [ ] Step 3 — iOS인가? 그럼 undetermined 상태에서 커스텀 Alert를 먼저 띄웠는가?

  • [ ] Step 4status === 'granted'라면 기능을 실행했는가?

  • [ ] Step 5canAskAgain === true라면 재요청 팝업을 띄웠는가?

  • [ ] Step 6canAskAgain === false라면 설정 앱으로 유도했는가? (Linking.openSettings())


마치며

권한 요청 흐름이 복잡하게 보이는 이유는, iOS와 안드로이드가 완전히 다른 철학을 갖고 있기 때문이에요.

  • iOS: 사용자 보호를 최우선 → 팝업 한 번만, 신중하게

  • 안드로이드: 사용자 선택권 → 여러 번 물어볼 수 있어, 유연하게

둘 다 이해하고 대응할 수 있으면, 사용자 경험도 좋고 권한 승인율도 높은 앱을 만들 수 있어요.

다음 편에서는 권한 거부 후 사용자 재참여 전략을 다뤄볼게요! 👋

저자 소개

DevOps Engineer. 금융과 여행에 관심이 많습니다.

독자 의견

Comments (0)