# ITMS-90683 Expo 해결 방법

> Info.plist에 빠진 purpose string 키를 app.json의 ios.infoPlist에 추가하고 다시 빌드하면 돼요.

원본 페이지: [ITMS-90683 Expo 해결 방법](https://devoria.fr/ko/blog/itms-90683-missing-purpose-string-expo)
작성자: [Mehdi Azizi](https://devoria.fr/ko/mehdi-azizi)
게시일: 2026-10-09
최종 내용 수정: 2026-10-09


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은 [보호된 리소스 접근](https://developer.apple.com/documentation/uikit/requesting-access-to-protected-resources) 문서에 이렇게 적어 뒀어요. 코드가 이런 리소스에 접근하는데 purpose string이 없으면 App Review가 앱을 거절한다고요.

리뷰어가 거절한 게 아니에요. 개인정보 매니페스트 관련 [ITMS-91053](https://devoria.fr/ko/blog/itms-91053-missing-api-declaration-expo)처럼, 빌드가 전달될 때 심사 전에 자동으로 걸리는 검사예요. 빌드는 제외되고, 새 빌드를 다시 보내야 해요.

## 앱이 그 데이터를 안 쓰는데도 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](https://devoria.fr/ko/blog/guideline-5-1-2-third-party-ai-att-data-sharing)).

Apple은 문서에서 키마다 설명해 둬요. 예를 들어 [NSPhotoLibraryUsageDescription](https://developer.apple.com/documentation/bundleresources/information-property-list/nsphotolibraryusagedescription) 문서를 보면, 앱이 사진 보관함을 읽거나 쓰는 API를 쓰는 순간 이 키가 필요하다고 나와요.

## Expo 앱에서 ITMS-90683 고치기

1. **Apple 이메일에 나온 키를 확인하세요.** 메시지에 정확한 이름이 있어요.
2. **설정에 추가하세요.** [Expo 권한 문서](https://docs.expo.dev/guides/permissions/)에 나온 대로 `ios.infoPlist` 아래에 넣으면 돼요.

```json
{
  "expo": {
    "ios": {
      "infoPlist": {
        "NSPhotoLibraryUsageDescription": "Solys는 사진에 접근하지 않아요. 이 권한은 절대 요청되지 않아요."
      }
    }
  }
}
```

3. **빌드를 다시 하세요.** Expo 문서에도 나와 있어요. Info.plist 변경은 원격 업데이트로 반영되지 않고, 새 바이너리가 필요해요.
4. **빌드를 Apple에 다시 보내고**, 버전에서 그 빌드를 선택하세요.

앱을 현지화했다면 주의할 점이 있어요. 언어 파일은 키를 번역할 뿐, 키를 선언하지는 않아요. 키는 먼저 `ios.infoPlist`(또는 해당 플러그인 설정)에 있어야 해요. 그렇지 않으면 처음 호출할 때 앱이 크래시 날 수 있어요.

## 앱이 그 데이터를 안 쓴다면 어떤 문장을 써야 할까요?

Apple은 정확하고 유용하고 구체적인 설명을 요구해요. 앱이 실제로 그 데이터를 쓴다면, 어디에 쓰는지 한 문장으로 말하세요. "티켓 바코드를 스캔하려고 카메라를 사용해요."

키가 라이브러리 때문에만 필요한 경우, Apple이 주는 해결책은 두 가지예요. 문장을 쓰거나, 데이터에 접근하는 코드를 제거하거나요. 그 코드가 라이브러리 안에 있으면 쉽게 제거할 수 없어요. 그래서 Solys에서는 사실대로 썼어요. "Solys는 사진에 접근하지 않아요. 이 권한은 절대 요청되지 않아요." 실용적인 선택이에요. 다음 빌드는 전달 단계를 통과했지만, Apple이 이 문장을 항상 받아준다고 장담할 수는 없어요.

## 업로드 전에 빠진 키 찾기

프로젝트 루트에서 이 명령어를 실행하면, iOS 코드가 가장 많이 감시되는 API를 참조하는 라이브러리 파일 목록이 나와요.

```bash
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에 거절된 앱](https://devoria.fr/ko/expertise/app-rejected-by-apple) 페이지에 있고, 가장 흔한 사유는 [Apple이 앱을 거절하는 이유](https://devoria.fr/ko/blog/app-store-rejection-reasons-real-cases)에 정리해 뒀어요.

업로드 전에 점검하고 싶다면, [Apple Review Kit](https://devoria.fr/ko/kits/review-apple)에 제 체크리스트와 프로젝트를 검토해 주는 Claude Code skills를 담아 뒀어요. 업로드가 막혀서 사람의 눈이 필요하다면 [저와 1시간 예약하세요](https://devoria.fr/ko/coaching). 화상으로 화면을 보면서 프로젝트를 함께 살펴봐요. 첫 출시를 준비 중이라면 [무료 진단을 받아 보세요](https://devoria.fr/ko/diagnostic). 단계를 순서대로 정리해 주고, 제 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 이름을 검색해 보세요.


## 내 프로젝트

[Apple Review Kit](https://devoria.fr/ko/kits/review-apple): 제가 쓰는 App Store 심사 체크리스트, 수정한 Apple 리젝 사례, 심사자용 메모, 앱을 검토하는 Claude Code skill 두 개. 29 €.

[iOS Kit](https://devoria.fr/ko/kits/ios): Claude Code로 iPhone 앱을 만드세요. 제 앱들의 Starter Code, 작업을 검사하는 skill, Apple Review Kit, App Store Screenshots Kit, ASO Kit 포함. 129,99 €.
