들어가며
3주간 7번의 리젝 끝에 앱을 출시했다.

이번 글에서는 앱스토어에 앱을 출시한 과정을 이야기한다. 특히 7번이나 리젝당하면서 배운 것들을.
7번의 리젝
애플 앱의 공식 심사 지침은 App Store Review Guidelines에서 확인할 수 있다.
- 1차 리젝 (2025.09.12)
- 2.1.0 - 앱 완성도: Sign in with Apple 로그인 불가 버그
- 2.1.0 - 정보 필요: 제공된 데모 계정으로 로그인 불가
- 2.3.8 - 정확한 메타데이터: 마켓플레이스 앱 이름(봄봄)과 기기 표시 이름(app)이 일치하지 않음
- 2차 리젝 (2025.09.16)
- 2.3.8 - 정확한 메타데이터: 앱 이름 불일치 문제 여전히 존재
- 5.1.1 - 개인정보 수집: 생년월일과 성별을 필수로 요구하는데, 이는 앱의 핵심 기능과 무관함
- 3차 리젝 (2025.09.18)
- 4.0.0 - 디자인: Sign in with Apple 사용 후 이메일 주소를 추가로 요구함 (Authentication Services framework에서 이미 제공됨)
- 4차 리젝 (2025.09.23)
- 4.0.0 - 디자인: Sign in with Apple 사용 후 이름/이메일을 여전히 요구함
- 5차 리젝 (2025.09.24)
- 2.1.0 - 앱 완성도: 채팅 기능에서 "사진/비디오 촬영" 옵션 선택 시 앱 크래시 (ChannelTalk 관련 미완성 기능)
- 6차 리젝 (2025.09.25)
- 2.1.0 - 앱 완성도: Sign in with Apple 로그인 후 초기 로그인 페이지로 되돌아가는 버그 (iPad Air 5세대, iPadOS 26.0)
- 7차 리젝 (2025.09.26)
- 4.0.0 - 디자인: Sign in with Apple 사용 후 이름/이메일을 요구하는 문제 재발
7번의 리젝 중 6번(1,2,3,4,6,7)이 소셜 로그인과 관련된 사유였다. 소셜 로그인 구현이 생각보다 까다로웠는데, 특히 애플의 Sign in with Apple과 관련된 정책이 엄격했다.
주요 리젝 사유와 해결 방법
Sign in with Apple 이후 이름·이메일을 다시 요구하지 않기
7번의 리젝 중 무려 6번이 소셜 로그인, 그중에서도 대부분이 이 문제였다. 애플은 Sign in with Apple로 로그인하면 사용자의 이름과 이메일을 Authentication Services를 통해 앱에 이미 넘겨준다. 그런데 우리 회원가입 폼은 소셜 로그인을 마친 뒤에도 이름과 이메일을 사용자에게 또 입력받고 있었다. 애플 입장에서는 ‘이미 준 정보를 왜 또 받느냐’는 거였고, 이게 4.0.0 디자인 사유로 계속 리젝됐다.
애플이 준 값이 있으면 그걸로 폼을 채우고, 사용자에게 다시 묻지 않으면 된다. 로그인 응답으로 받은 fullName, email을 회원가입 폼의 초기값으로 넣고, 값이 이미 채워진 경우에는 해당 입력 필드를 노출하지 않거나 수정 불가로 처리했다. 아래에서 이야기할 생년월일·성별의 disabled 처리와 같은 맥락이다. ‘애플이 준 걸 그대로 썼다’는 상태를 만들어주면 된다.
"생년월일과 성별을 필수로 요구하는데, 이는 앱의 핵심 기능과 무관함"
소셜 로그인 이후, 생년월일과 성별을 입력받았다. 그런데 이는 앱의 핵심 기능과 무관한 정보임에도 필수로 입력받는 것이 문제였다. 애플은 개인정보 수집에 대해 상당히 엄격한데, 특히 앱의 핵심 기능과 직접적으로 관련 없는 정보를 필수로 요구하는 걸 허용하지 않는다. 데이팅 앱이나 건강 앱처럼 생년월일과 성별이 필수적인 경우가 아니라면, 선택 사항으로 만들거나 명확한 사용 목적을 제시해야 한다.
해결 방법은 애플 provider에서 제공받은 생년월일과 성별을 회원가입 입력폼에 자동 기입하고, disabled 속성을 추가해 수정할 수 없도록 처리했다. 애플이 준 정보를 그대로 썼을 뿐이라고 설명한 셈이다.
// 예시 코드
<Input
value={appleUserData.birthDate}
disabled={true}
placeholder="생년월일"
/>
<Input
value={appleUserData.gender}
disabled={true}
placeholder="성별"
/>
만약 추가 정보가 정말 필요하다면 나중에 선택적으로 입력받는 방식으로 변경하는 것도 방법이다. 예를 들어 "프로필 완성도 높이기" 같은 옵션으로 제공하면 된다.
앱 이름 불일치 문제
기본 설정인 app이 기기 표시 이름으로 설정되고 있었다. 앱스토어에는 "봄봄"으로 등록했는데, 사용자 기기에서는 "app"으로 표시되는 황당한 상황이었다.
해결 방법은 app.json에서 우리 앱 이름으로 수정했다.
{
"expo": {
"name": "봄봄",
"slug": "bombom",
...
}
}
채팅 기능에서 "사진/비디오 촬영" 옵션 선택 시 앱 크래시
웹에서 추가한 채널톡에서 발생한 문제였다. 우리 서비스가 아닌 채널톡을 테스트해볼 거라고는 생각을 못했었다. 심사팀은 우리가 신경도 안 쓴 기능까지 다 눌러본다.
급한 대로 택한 해결 방법은 앱 심사 기간 동안 웹에서 채널톡을 임시로 제거하는 것이었다. 심사를 통과한 후 다시 붙일 생각이었다. 근데 이건 심사 때마다 넣었다 뺐다 해야 해서 번거롭다. 더 나은 방법은 채널톡 자체에서 카메라 기능을 꺼버리는 것이다.
여기서 한 가지 걸렸던 게 있다. 이 카메라 비활성화는 코드로 켜고 끄는 옵션이 아니라, 채널톡 관리자 콘솔에서 설정하는 항목이다. 채널톡 관리자 페이지의 상담 설정에서 파일/미디어 업로드 관련 옵션을 찾아 ‘카메라(사진·비디오 촬영)’만 끄고 파일 업로드는 남겨두면 된다. 이렇게 해두면 심사팀이 채널톡을 눌러봐도 카메라로 넘어가는 경로 자체가 없어서 크래시가 나지 않고, 심사 때마다 채널톡을 통째로 떼어낼 필요도 없다.
(ChannelIO.boot의 hidePopup 같은 옵션은 채팅 팝업 노출 여부를 다루는 것이지 카메라 기능과는 무관하다. 이걸로는 이 문제를 해결할 수 없다.)
처음부터 고려했다면 좋았을 것들
아래는 이번 경험을 하며 만든 체크리스트다. 처음부터 이것들을 고려했다면 훨씬 빠르게 심사를 통과할 수 있었을 것이다.
- 소셜 로그인 관련
- Sign in with Apple 사용 시, 애플이 제공하는 정보(이름, 이메일) 외에 추가 정보를 요구하지 않기
- 추가 정보가 필요하다면 반드시 선택 사항으로 만들고, 왜 필요한지 명확히 설명하기
- 앱의 핵심 기능과 무관한 개인정보는 필수로 요구하지 않기
- 기본 설정 확인
- 앱 이름이 모든 곳(app.json, Info.plist, 앱스토어 등록 정보)에서 일치하는지 확인
- 데모 계정이 정상적으로 작동하는지 테스트 (심사팀이 제일 먼저 사용하는 계정)
- 써드파티 서비스
- 채널톡, 인터콤 같은 고객 지원 도구의 모든 기능이 정상 작동하는지 확인
- 특히 카메라, 파일 업로드 같은 권한이 필요한 기능은 반드시 테스트
- 필요없는 기능은 비활성화하기
- 테스트 기기
- 다양한 기기(iPhone, iPad)와 OS 버전에서 테스트하기
- 심사팀이 사용하는 기기 스펙도 다양하므로, 최소한 최신 버전과 이전 버전 2개 정도는 확인
배포 방법
로컬에서 XCode를 활용한 빌드
npx expo prebuild --platform ios로 네이티브 프로젝트 생성- XCode실행
- 상단의 product > archive 클릭
- Distribute
로컬 빌드의 장점은 즉각적인 피드백을 받을 수 있다는 것이다. 빌드 중 에러가 발생하면 바로 확인하고 수정할 수 있다. 다만 Mac이 필요하고, XCode 설정이 번거로울 수 있다.
로컬에서 CLI를 활용한 빌드
npx expo prebuild --platform ios로 네이티브 프로젝트 생성- 아래 명령어 입력
xcodebuild -workspace AppName.xcworkspace \
-scheme AppName \
-configuration Release \
-archivePath ./build/AppName.xcarchive \
archive
여기서 AppName에는 프로젝트의 실제 Scheme를 입력해야 하며, 이는 app.json에 설정한 scheme에 해당한다.
EAS를 활용한 빌드
eas build --platform ios --profile productioneas submit --platform ios
EAS(Expo Application Services)를 사용하면 Mac 없이도 클라우드에서 빌드할 수 있다. 특히 CI/CD 파이프라인을 구축할 때 유용하다. 다만 무료 플랜에서는 빌드 시간이 제한되어 있으니 참고하자.
처음에는 로컬 빌드로 시작해서 익숙해진 후, EAS로 전환하는 걸 추천한다. EAS는 설정이 간단하고, 빌드 로그도 깔끔하게 제공된다. 또한, 빌드 결과물을 팀원들과 공유할 수 있다.
EAS 기능과 설정을 사용하고 싶지만 무료 플랜이라 빌드 횟수 제한이 있거나, 대기열에 걸린다면 --local 옵션으로 로컬에서 EAS빌드를 할 수도 있다. 대신, 클라우드 기능을 사용하지 못한다.
심사 제출
위 빌드 과정을 마치면 App Store Connect의 TestFlight 탭에 빌드된 앱이 올라와 있다.
이제 이 앱은 TestFlight 앱에서 실행해서 테스트해보면 된다. TestFlight로 내부 테스터에게 배포해서 마지막 확인을 하는 것도 좋은 방법이다. 실제 기기에서 발생할 수 있는 문제를 미리 발견할 수 있다.
이제 진짜 배포를 하기 위해서는 "배포" 탭으로 이동해서 정보를 입력한 후, "심사에 추가"를 해서 제출하면 된다.
신경 써야 할 것
버전 관리: 이전 버전과 중복되면 안 된다
iOS에 대한 정보는 ios/[앱이름]/Info.plist 파일에 담겨있다. 여기서 CFBundleShortVersionString는 앱의 버전(예: 1.0.0), CFBundleVersion은 빌드 버전(예: 1)을 말한다. 업데이트할 때는 앱의 버전이 중복되면 안 되고, 빌드해서 테스트 플라이트에 업로드할 때는 동일한 앱의 버전에서 빌드 버전이 중복되면 안 된다. 또한, 두 버전은 모두 이전보다 높아야 한다.
<!-- ios/app/Info.plist -->
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleVersion</key>
<string>1</string>
여기서 직접 설정해도 되고, 만약 expo를 사용 중이라면 app.json에서 각각 version, ios.buildNumber로 설정할 수 있다. 대신 app.json으로 설정하면 다시 빌드를 해야 한다는 번거로움이 있다.
혹은 XCode에서 변경하는 방법도 있다. Targets > Info 에서 각각 Bundle Version string과 Bundle Version이 해당한다.
맺으며
앱 스토어에 제출하고, 기다리고, 피드백을 받아 수정하고... 과정은 고됐는데 지나고 보니 별거 아니었다. 리젝 메일 일곱 통 받은 것치고는.
이번 앱 스토어 배포를 하면서, 다음 앱을 배포할 때는 훨씬 빠르게 통과할 수 있을 거라는 확신이 든다. 이미 해봤으니깐.
다음에 이 글을 볼 사람은 아마 미래의 나일 것 같다.