ITMS-90683 Expo 해결 방법
글: Mehdi Azizi
게시, 6분
Info.plist에 빠진 purpose string 키를 app.json의 ios.infoPlist에 추가하고 다시 빌드하면 돼요.
ITMS-90683은 Apple의 자동 거절이에요. 빌드를 올리고 얼마 안 돼서, 사람이 심사하기도 전에 이메일로 날아와요. 앱이 민감한 데이터에 접근하는 이유를 설명하는 문장이 Info.plist 파일에 없다는 뜻이에요. 고치는 방법은 두 단계예요. 메시지에 나온 키를 ios.infoPlist에 추가하고, 빌드를 다시 하면 돼요.
저는 미니게임 알람 앱 Solys에서 이 거절을 받았어요. 그것도 앱이 쓰지도 않는 데이터 때문에요. 이 메시지가 무슨 뜻인지, 왜 뜨는지, 어떻게 피하는지 정리해 볼게요.
ITMS-90683 오류는 무슨 뜻인가요?
메시지 제목은 "ITMS-90683: Missing purpose string in Info.plist"예요. 앱 코드가 민감한 데이터(사진, 카메라, 마이크, 위치, 연락처)를 다루는 API를 참조하는데, Info.plist에 그에 맞는 설명 키가 없다는 내용이에요. 메시지에는 키 이름이 나와요. 예를 들면 NSPhotoLibraryUsageDescription 같은 거요.
이 설명 문장을 "purpose string"이라고 해요. 권한 요청 창에 iOS가 띄우는 텍스트예요. Apple은 보호된 리소스 접근 문서에 이렇게 적어 뒀어요. 코드가 이런 리소스에 접근하는데 purpose string이 없으면 App Review가 앱을 거절한다고요.
리뷰어가 거절한 게 아니에요. 개인정보 매니페스트 관련 ITMS-91053처럼, 빌드가 전달될 때 심사 전에 자동으로 걸리는 검사예요. 빌드는 제외되고, 새 빌드를 다시 보내야 해요.
앱이 그 데이터를 안 쓰는데도 Apple이 거절하는 이유
다들 여기서 놀라요. Apple은 앱이 실제로 하는 동작이 아니라, 빌드에 들어 있는 코드를 분석해요. 포함된 라이브러리 하나가 사진 보관함을 참조하면, 사진 접근을 요청하는 화면이 하나도 없어도 키가 필요해요. Apple 메시지에도 직접 나와 있어요. 외부 라이브러리나 SDK가 이런 API를 참조할 수 있고, 그래도 purpose string은 필수라고요.
제 경우는 2026년 9월 26일이었어요. Solys 설정을 정리하면서 NSPhotoLibraryUsageDescription 키를 지웠어요. 앱이 사진을 전혀 안 건드리니까요. 다음 빌드가 ITMS-90683으로 거절됐어요. 원인은 앱이 쓰는 Expo 라이브러리 두 개, expo-image와 expo-file-system이었어요. 둘 다 사진 보관함을 참조하는 코드가 들어 있어요. 이전 빌드는 키가 아직 있어서 통과했던 거예요.
교훈: 설명 키는 "안 쓰니까" 지우면 안 돼요. 빌드 안의 어떤 라이브러리도 그 API를 참조하지 않을 때만 지울 수 있어요.
가장 흔한 키
NSPhotoLibraryUsageDescription: 사진 읽기 또는 쓰기.NSPhotoLibraryAddUsageDescription: 읽기 없이 사진 추가만.NSCameraUsageDescription: 카메라.NSMicrophoneUsageDescription: 마이크.NSLocationWhenInUseUsageDescription: 사용 중 위치.NSContactsUsageDescription: 연락처.NSUserTrackingUsageDescription: 광고 추적(App Tracking Transparency).
Apple은 문서에서 키마다 설명해 둬요. 예를 들어 NSPhotoLibraryUsageDescription 문서를 보면, 앱이 사진 보관함을 읽거나 쓰는 API를 쓰는 순간 이 키가 필요하다고 나와요.
Expo 앱에서 ITMS-90683 고치기
- Apple 이메일에 나온 키를 확인하세요. 메시지에 정확한 이름이 있어요.
- 설정에 추가하세요. Expo 권한 문서에 나온 대로
ios.infoPlist아래에 넣으면 돼요.
{
"expo": {
"ios": {
"infoPlist": {
"NSPhotoLibraryUsageDescription": "Solys는 사진에 접근하지 않아요. 이 권한은 절대 요청되지 않아요."
}
}
}
}
- 빌드를 다시 하세요. Expo 문서에도 나와 있어요. Info.plist 변경은 원격 업데이트로 반영되지 않고, 새 바이너리가 필요해요.
- 빌드를 Apple에 다시 보내고, 버전에서 그 빌드를 선택하세요.
앱을 현지화했다면 주의할 점이 있어요. 언어 파일은 키를 번역할 뿐, 키를 선언하지는 않아요. 키는 먼저 ios.infoPlist(또는 해당 플러그인 설정)에 있어야 해요. 그렇지 않으면 처음 호출할 때 앱이 크래시 날 수 있어요.
앱이 그 데이터를 안 쓴다면 어떤 문장을 써야 할까요?
Apple은 정확하고 유용하고 구체적인 설명을 요구해요. 앱이 실제로 그 데이터를 쓴다면, 어디에 쓰는지 한 문장으로 말하세요. "티켓 바코드를 스캔하려고 카메라를 사용해요."
키가 라이브러리 때문에만 필요한 경우, Apple이 주는 해결책은 두 가지예요. 문장을 쓰거나, 데이터에 접근하는 코드를 제거하거나요. 그 코드가 라이브러리 안에 있으면 쉽게 제거할 수 없어요. 그래서 Solys에서는 사실대로 썼어요. "Solys는 사진에 접근하지 않아요. 이 권한은 절대 요청되지 않아요." 실용적인 선택이에요. 다음 빌드는 전달 단계를 통과했지만, Apple이 이 문장을 항상 받아준다고 장담할 수는 없어요.
업로드 전에 빠진 키 찾기
프로젝트 루트에서 이 명령어를 실행하면, iOS 코드가 가장 많이 감시되는 API를 참조하는 라이브러리 파일 목록이 나와요.
grep -rlE "PHPhotoLibrary|AVCaptureDevice|CLLocationManager|CNContactStore|EKEventStore|ATTrackingManager" \
node_modules/*/ios node_modules/@*/*/ios
이름마다 대응하는 데이터가 있어요. PHPhotoLibrary는 사진, AVCaptureDevice는 카메라와 마이크, CLLocationManager는 위치, CNContactStore는 연락처, EKEventStore는 캘린더, ATTrackingManager는 추적이에요. 결과마다 해당 설명 키가 설정에 있는지 확인하세요.
이 방법으로 제가 겪은 경우들은 잡혀요. 그래도 Apple 이메일을 읽는 걸 대신하지는 못해요. ITMS-90338의 비공개 API처럼, 확실한 목록은 이메일뿐이에요. 이 거절 이후로 저는 빌드마다 이 확인을 먼저 해요. 몇 초면 끝나지만, ITMS-90683 거절을 받으면 빌드 하나와 다시 만드는 시간이 날아가요.
깜짝 놀랄 일 없이 빌드 보내기
ITMS-90683은 읽는 법만 알면 금방 고쳐요. Xcode 버전 문제인 ITMS-90725도 마찬가지예요. 그다음에 오는 리뷰어의 거절은 좀 더 차분히 봐야 해요. 대응 방법은 Apple에 거절된 앱 페이지에 있고, 가장 흔한 사유는 Apple이 앱을 거절하는 이유에 정리해 뒀어요.
업로드 전에 점검하고 싶다면, Apple Review Kit에 제 체크리스트와 프로젝트를 검토해 주는 Claude Code skills를 담아 뒀어요. 업로드가 막혀서 사람의 눈이 필요하다면 저와 1시간 예약하세요. 화상으로 화면을 보면서 프로젝트를 함께 살펴봐요. 첫 출시를 준비 중이라면 무료 진단을 받아 보세요. 단계를 순서대로 정리해 주고, 제 Apple 거절 방지 체크리스트도 보내 드려요.
자주 묻는 질문
ITMS-90683은 App Review 거절인가요?
사람 리뷰어의 거절이라는 의미에서는 아니에요. 아이콘 관련 ITMS-90717처럼, 빌드가 전달될 때 심사 전에 하는 자동 검사예요. 아무도 앱을 열어보지 않았어요. 빌드는 제외되니까 Info.plist를 고치고 새 빌드를 보내야 해요.
앱이 쓰지 않는 데이터인데 왜 Apple이 키를 요구하나요?
Apple은 앱의 동작이 아니라 빌드에 있는 코드를 분석하기 때문이에요. 포함된 라이브러리가 사진 보관함이나 카메라를 참조하면, 그 접근을 요청하는 화면이 없어도 설명 키가 필요해요.
원격 업데이트로 ITMS-90683을 고칠 수 있나요?
아니요. 빠진 키는 바이너리의 일부인 Info.plist에 있어요. 원격 업데이트는 이 파일을 바꾸지 못해요. 빌드를 다시 해서 Apple에 보내야 해요.
Expo 프로젝트에서 NSPhotoLibraryUsageDescription은 어디에 추가하나요?
앱 설정의 ios.infoPlist 아래에, 용도를 설명하는 문장과 함께 넣으면 돼요. 일부 라이브러리는 플러그인에 전용 설정을 제공하기도 하는데, 이 설정이 백그라운드 모드 같은 다른 키를 추가할 수도 있어요. 어느 쪽이든 키는 번역 파일만이 아니라 기본 설정에 있어야 해요.
안 쓰는 설명 키는 지워야 하나요?
빌드 안의 어떤 라이브러리도 해당 API를 참조하지 않을 때만 지우세요. 그렇지 않으면 다음 업로드가 ITMS-90683으로 거절돼요. 키를 지우기 전에 의존성의 iOS 코드에서 API 이름을 검색해 보세요.