콘텐츠로 이동

iOS 15에서 앱 실행 시 Firebase 초기화 크래시

iOS 15에서 앱 실행 후 FCM 초기화 타이밍에 앱이 크래시하는 현상이 생겼다.

관련 이슈: https://github.com/firebase/firebase-unity-sdk/issues/1268

버그가 고쳐진 Firebase Unity SDK 버전으로 올려 해결했다(v12.10.0 → v12.10.1).

Firebase 쪽 변경은 “스위즐링 방식 변경”과 “AppDelegate 직접 지정 옵션 추가” 두 가지다.

  • 기존에는 firebase::util::ForEachAppDelegateClass 안에서 objc_copyClassList로 모든 클래스를 스캔해 AppDelegate 후보를 찾았다.
  • 12.10.1에서는 이 방식을 바꿔 objc_copyClassList에 의존하지 않고 AppDelegate를 찾는다. iOS 15에서 ARKit·AppLovin 등과 함께 쓸 때 나던 크래시를 피한다. 이 앱도 AppLovin을 쓰고 있었다.
  • Info.plist에 FirebaseAppDelegateClassName 키를 추가하고 값으로 앱의 AppDelegate 클래스 이름(예: UnityAppController 또는 커스텀 델리게이트)을 넣으면, Firebase가 그 클래스만 찾아 스위즐링한다.
  • 지정한 클래스가 없으면 이 값은 무시되고 새 스위즐링 로직으로 폴백한다.

상세 분석: Firebase 클래스 스캔과 weak linking 충돌

섹션 제목: “상세 분석: Firebase 클래스 스캔과 weak linking 충돌”

앱이 iOS 16 이상 SDK(예: RoomPlan 프레임워크)를 포함해 빌드됐는데 iOS 15 기기에서 실행되면, Firebase의 초기화 로직이 Objective-C 런타임의 알려진 제약에 걸려 크래시가 난다.

이 제약은 Swift 저장소 이슈로 공개돼 있다. @available(iOS 16, *)이 붙은 NSObject 하위 클래스가 iOS 16 전용 타입을 참조하면, iOS 16 미만에서 objc_getClassList나 objc_copyClassList를 부를 때 크래시가 난다. Swift 기여자는 ObjC 런타임이 사용 가능 버전 제한을 모르기 때문에 구버전 OS에서 동작하지 않는 클래스까지 초기화하려 한다고 설명하고, 두 API를 쓰지 말라고 권한다. 이슈는 아직 열려 있다.

아래 세 조건이 모두 맞을 때 발생한다.

  1. 타깃 OS: iOS 15 기기
  2. 빌드 환경: 앱이 iOS 16+ 전용 심볼(예: RoomCaptureSessionView)을 포함해 빌드됨
  3. 라이브러리: Firebase(구 버전 C++ 구현체)가 포함되어 있고 AppDelegate 스위즐링이 켜져 있음

Firebase의 libFirebaseCppApp.a는 내부에서 firebase::util::ForEachAppDelegateClass를 실행해 AppDelegate를 찾고 스위즐링을 시도한다. 이 과정에서 objc_copyClassList를 호출해 앱 안의 모든 Objective-C·Swift 클래스 목록을 조회한다.

  1. 앱이 실행되면 Firebase가 전체 클래스 스캔을 위해 objc_copyClassList를 호출한다.
  2. 목록에는 iOS 16에서만 쓸 수 있는 클래스(RoomCaptureSessionView 등)도 들어 있다. 이 클래스들은 weak linking 상태다.
  3. 런타임은 목록을 만드는 과정에서 모든 클래스를 초기화(realization)한다. Firebase 이슈의 스택 트레이스에도 realizeAllClasses 다음에 Swift 타입 메타데이터 초기화에서 실패하는 프레임이 찍혀 있다.
  4. 해당 클래스의 부모 클래스나 프로토콜 정보를 찾으려 하지만 iOS 15 기기에는 그 프레임워크(RoomPlan 등)가 없다.
  5. Swift 런타임이 존재하지 않는 주소나 널 포인터에 접근해 크래시(SIGABRT 또는 EXC_BAD_ACCESS)가 난다.
  • iOS 15: Firebase 이슈의 보고는 모두 iOS 15.x(15.5, 15.8.4 등)다.
  • iOS 14: 같은 이슈에서 크래시가 나지 않는다는 보고가 있다. 왜 다른지는 공개 자료에 설명이 없다.
  • iOS 16 이상: 기기에 해당 프레임워크가 있으므로 클래스를 정상적으로 초기화해 문제가 없다.