앱 심사를 하고나서 처음으로 리젝을 받아봤습니다.. 수 많은 리젝 사유들이 존재하지만 내가 받은 사유는 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 파일이 나오는데 그 파일을 오른쪽 클릭하고 패키지 내용 보기를 클릭해주세요. 자 이제 여기서 필요한 준비물들을 찾아서 준비해야합니다.
이 친구들을 따로 복사해서 한 폴더에 넣어줍니다.
이렇게요. 저는 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 을 제대로 했나?" 라고 물어보면 "그렇다" 라고 자신있게 말을 못할 것 같습니다.. 저 터미널에서 나온 값들이 제대로 나온 값들인지도 잘 모르겠구요.. 그래도 이런 경험들이 쌓이고 쌓이면 더 발전하리라 생각합니다. 그리고 저랑 비슷한 리젝을 받으신 분이 제 글을 보고 리젝을 꼭 해결하셨으면 좋겠습니다 !