TestFlight에 IPA를 업로드하고 몇 분 후 App Store Connect에서 메일이 온다.

ITMS-90683: Missing purpose string in Info.plist
The app's Info.plist file is missing a required purpose string for
one or more of the following API categories: NSPhotoLibraryUsageDescription

업로드 자체는 성공했지만 앱 배포 전 Apple이 자동으로 검사해서 이 메일을 보낸다. 수정하지 않으면 App Store 심사 제출 시 거절된다.


왜 이 오류가 발생하는가

iOS는 카메라, 사진 라이브러리, 마이크 등 민감한 API에 접근할 때 사용자에게 권한 팝업을 보여준다. 이 팝업에 표시되는 설명 문구가 Info.plist에 없으면 Apple이 오류로 처리한다.

앱에서 직접 권한을 요청하지 않더라도 의존 패키지가 해당 API를 사용하면 purpose string이 필요하다. file_picker, image_picker, photo_view 같은 패키지를 쓰면 실제 호출 여부와 무관하게 선언이 필요하다.


수정: Info.plist에 purpose string 추가

ios/Runner/Info.plist에 해당 키와 설명 문자열을 추가한다.

<!-- ios/Runner/Info.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
    <!-- 기존 설정들 ... -->

    <!-- 사진 라이브러리 읽기 권한 -->
    <key>NSPhotoLibraryUsageDescription</key>
    <string>서류 제출 및 프로필 사진 업로드를 위해 사진 라이브러리에 접근합니다.</string>

    <!-- 사진 라이브러리 저장 권한 (다운로드 기능이 있을 때) -->
    <key>NSPhotoLibraryAddUsageDescription</key>
    <string>다운로드한 파일을 사진 라이브러리에 저장하기 위해 접근합니다.</string>

    <!-- 카메라 권한 -->
    <key>NSCameraUsageDescription</key>
    <string>사진 촬영 및 파일 업로드를 위해 카메라에 접근합니다.</string>

</dict>
</plist>

자주 나오는 purpose string 목록

설명관련 패키지
NSPhotoLibraryUsageDescription사진 라이브러리 읽기image_picker, file_picker, photo_view
NSPhotoLibraryAddUsageDescription사진 라이브러리 저장image_gallery_saver 등
NSCameraUsageDescription카메라image_picker, camera
NSMicrophoneUsageDescription마이크audio_recorder, video 촬영
NSLocationWhenInUseUsageDescription위치 (앱 사용 중)geolocator, google_maps
NSLocationAlwaysUsageDescription위치 (백그라운드)background_location
NSContactsUsageDescription연락처contacts_service
NSCalendarsUsageDescription캘린더add_2_calendar 등
NSFaceIDUsageDescriptionFace IDlocal_auth
NSBluetoothAlwaysUsageDescription블루투스flutter_blue 등

어떤 권한이 필요한지 확인하는 방법

패키지 README나 pub.dev 페이지의 “iOS permissions” 섹션을 확인하는 게 가장 빠르다. 아니면 빌드 후 나오는 경고로 파악할 수 있다.

# Xcode 빌드 로그에서 권한 관련 경고 검색
xcodebuild ... 2>&1 | grep -i "usage description"

또는 Info.plist를 열어 이미 추가된 키 목록과 비교하는 방법도 있다.

# 현재 Info.plist에 있는 권한 키 확인
/usr/libexec/PlistBuddy -c "Print" ios/Runner/Info.plist | grep "UsageDescription"

업로드 후 경고 확인 방법

TestFlight 업로드 성공 후 App Store Connect → 앱 → TestFlight → 빌드 목록에서 “Missing Compliance” 또는 경고 아이콘이 있는지 확인한다.

메일로도 오지만 App Store Connect 웹에서 더 자세한 정보를 확인할 수 있다.


주의: 앱에서 실제로 사용하지 않는 권한

purpose string만 추가하고 앱에서 실제로 해당 권한을 요청하지 않으면 심사에서 거절될 수 있다. Apple 가이드라인 5.1.1에 따르면 실제로 사용하는 권한만 선언해야 한다.

파일 업로드 기능을 file_picker로 구현하면 내부적으로 사진 라이브러리에 접근하므로 NSPhotoLibraryUsageDescription은 정당하게 필요하다. 반면 앱 어디에도 카메라를 쓰지 않는데 NSCameraUsageDescription만 추가하면 심사에서 걸릴 수 있다.


수정 → 재업로드 흐름

Info.plist 권한 키 추가
        ↓
make testflight  (또는 flutter build ipa → xcrun altool)
        ↓
UPLOAD SUCCEEDED
        ↓
App Store Connect에서 메일 없으면 정상

권한 문자열만 바꾸는 경우라면 빌드 번호를 올릴 필요 없이 바로 재업로드한다. 단, 동일 빌드 번호로 재업로드하면 기존 빌드를 교체하는 게 아니라 거절된다. 빌드 번호를 올려야 한다.