일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Complication
- Sendbird
- coreml
- Flutter
- github
- backend
- UIDatePicker
- Project
- spring
- app intents
- Swift
- WWDC22
- watchkit
- SwiftUI
- UITableView
- UIStackView
- Apple Developer Academy
- 코테
- createml
- swift concurrency
- Firebase
- Tuist
- task.yield()
- ios
- Delegate Pattern
- cloud functions
- Coding Test
- widgetkit
- tabman
- fcm
- Today
- Total
azhy의 iOS 이야기
[iOS] 앱 심사 리젝 해결 - App Crash, Report 확인 본문
2022년 7월 27일에 작성됨
앱 심사를 하고 나서 처음으로 리젝을 받아봤습니다.. 수많은 리젝 사유들이 존재하지만 제가 받은 사유는 App Completeness
제가 받은 리젝 사유입니다. 사실 리젝을 받을 거라고는 예상을 못했습니다.. 그래서 더욱 당황했고 또 알아보니 저의 케이스가 해결하기 쉬운 케이스가 아니었습니다..
"앱 어딘가에서 crash가 났다 - 불완전한 앱은 심사를 통과할 수 없다." 였는데 내가 몇 번을 테스트했을 때도 앱 어딘가에서 에러가 난 적이 없었습니다.
그래서 혹시나 싶어 시뮬레이터, 실기기 다시 한번 더 쭉 테스트해봤는데도 그 어디에서도 에러가 없는데.. 그래도 애플 쪽에서 crash가 났다고 하니 천천히 하나씩 진행해 보겠습니다.
음.. 저 4개의 파일 중 하나인데, 이걸 보고 어디가 문제인지 찾을 수 있는 사람이 있을까..? 싶기도 하지만 잘 찾아보면 꽤나 많은 정보가 있습니다. 그래서 이 파일만 가지고 어디가 문제인지 찾아내면 제일 좋겠지만, 사실 거의 힘들 거라고 생각합니다. 그래서 사람이 해독할 수 있게 바꾸는 작업을 해야 하는데 이 작업을 애플은 "Symbolicating"이라고 표현한다고 하네요.
이 작업을 하는 방법은 여러 가지고 존재하는데, 가장 쉬운 방법은 Xcode를 이용하는 거라고 합니다. 실제로 이번에 나도 Xcode를 이용해서 Symbolicating 작업을 진행했습니다.
우선 저 4개의 파일을 모두 다 다운을 받아주세요. 다운로드한 .txt 파일을 .crash 파일로 변경을 하고
실기기 연결 - Xcode - Window - View Device Logs - all logs에 들어가서 방금 따로 저장해 놓은 .crash 파일들을 전부 다 넣어줍니다.
그럼 이렇게 쭉 해석이 된 형태가 나옵니다.
애플 문서에 따르면 특정 패턴을 찾고 이 패턴을 인식하고 분석하려면 모든 충돌 보고서에서 사용할 수 있는 두 섹션을 참조하라고 적혀있습니다.
Exception Information 섹션은 앱이 충돌한 구체적인 방법을 식별하고 Backtraces 섹션은 충돌 당시 스레드가 실행하고 있던 코드를 보여줍니다. Exception Type을 보면 대충 crash 난 이유를 알 수 있습니다. 그리고 그 Type의 종류가 엄청 많습니다.. 자세한 Type의 종류는 애플 문서 하단에 정리되어 있으니 꼭 확인을 해보세요.
저의 crash 타입은 총 2개였는데 EXC_CRASH (SIGABRT) EXC_BAD_ACCESS (SIGSEGV)였습니다. 이제 대충 타입도 알았겠다, 정확히 어디에서 crash가 발생했는지 찾아내서 수정하면 됩니다.
이제 2가지의 준비물이 필요합니다. 우선 Archives 폴더에 들어가자. 들어가면 본인이 앱 등록을 위해 Archives에 업로드시킨 날짜가 쭉 나옵니다.
리젝 먹은 앱을 올린 날짜 폴더에 들어가면 .xcarchive 파일이 나오는데 그 파일을 오른쪽 클릭하고 패키지 내용 보기를 클릭해 주세요. 자 이제 여기서 필요한 준비물들을 찾아서 준비해야 합니다.
- Products 폴더 - Applications 폴더 - 앱 파일
- dSYMs 폴더 - dSYM 파일
이 친구들을 따로 복사해서 한 폴더에 넣어줍니다.
이렇게요. 저는 Widget, Watch 파일을 포함해서 dSYM 파일이 3개입니다. 이렇게 준비가 끝났으면 터미널을 켜주세요.
명령어 형식은 'atos -arch arm64 -o appName.app.dSYM/Contents/Resources/DWARF/appName -l 주소 1 주소 2' 이렇게 생겼습니다.
appName에는 본인의 appName을 적어주시면 되고 주소 1,2 에는 위에 Xcode에서 all logs의 crash 파일들 기억하시죠? 거기서 backtraces의 appName 옆 주소 2개를 적어주시면 되는데 예를 들면
제 crash 파일 중 하나입니다. Thread 0 Crashed에서 자신의 앱 이름이 보이는 부분을 찾습니다. 저의 appName인 coupleDayProject 가 총 3개 보이네요.
그 옆에 주소 2개 보이시죠? 이 주소 2개가 위에 제가 언급한 주소 1,2입니다. 참고로 저는 앞의 주소를 주소 2에 뒤의 주소를 주소 1에 넣어야 정상적으로 나왔습니다.
저는 파일이 총 4개였고 각 파일 안에 확인해야 하는 appName의 주소들이 많았습니다. 이걸 다 확인하는 게 맞는 건지 잘 모르겠어서 저는 그냥 다 확인을 했습니다..
그중 의미 있다고 생각한 결과들을 몇 개 캡처했습니다.
직접적으로 눈에 보이는 @objc BeginViewController.startBtnTap 부분을 가보니 실제로 이상한 부분이 있어서 고치고 Widget 쪽에 Realm 예외처리를 해주었습니다. 그리고 다시 Archive 올리고 리젝 메일에 회신하고 심사를 올렸더니
이렇게 성공적으로 심사를 마쳤습니다!
이번이 리젝이 처음이라 구글링과 블로그들을 참고해서 했는데 다른 사람들과 과정이랑 결과가 같은 부분도 있지만 다른 부분도 있어서 "Symbolicating을 제대로 했나?"라고 물어보면 "그렇다"라고 자신 있게 말을 못 할 것 같습니다.. 저 터미널에서 나온 값들이 제대로 나온 값들 인지도 잘 모르겠고요.. 그래도 이런 경험들이 쌓이고 쌓이면 더 발전하리라 생각합니다. 그리고 저랑 비슷한 리젝을 받으신 분이 제 글을 보고 리젝을 꼭 해결하셨으면 좋겠습니다!
'iOS' 카테고리의 다른 글
[iOS] WatchKit[2] - Watch Connectivity, 앱이랑 데이터 주고받기 (3) | 2024.11.13 |
---|---|
[iOS] WatchKit[1] - watch 프로젝트 시작, 살펴보기 (1) | 2024.11.13 |
[iOS] 두 번째 앱 출시 후기 (0) | 2024.11.12 |
[iOS] Google AdMob 앱에 애드몹 광고 달기 (3) | 2024.11.12 |
[iOS] WidgetKit[4] - Widget View 바로 업데이트 시키기 (0) | 2024.11.12 |