iOS 15에서 앱 실행 시 Firebase 초기화 크래시
iOS 15에서 앱 실행 후 FCM 초기화 타이밍에 앱이 크래시하는 현상이 생겼다.
관련 이슈: https://github.com/firebase/firebase-unity-sdk/issues/1268
버그가 고쳐진 Firebase Unity SDK 버전으로 올려 해결했다(v12.10.0 → v12.10.1).
SDK 변경점
섹션 제목: “SDK 변경점”Firebase 쪽 변경은 “스위즐링 방식 변경”과 “AppDelegate 직접 지정 옵션 추가” 두 가지다.
스위즐링 로직 변경
섹션 제목: “스위즐링 로직 변경”- 기존에는
firebase::util::ForEachAppDelegateClass안에서objc_copyClassList로 모든 클래스를 스캔해 AppDelegate 후보를 찾았다. - 12.10.1에서는 이 방식을 바꿔
objc_copyClassList에 의존하지 않고 AppDelegate를 찾는다. iOS 15에서 ARKit·AppLovin 등과 함께 쓸 때 나던 크래시를 피한다. 이 앱도 AppLovin을 쓰고 있었다.
AppDelegate 명시 설정 지원
섹션 제목: “AppDelegate 명시 설정 지원”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를 쓰지 말라고 권한다. 이슈는 아직 열려 있다.
발생 조건
섹션 제목: “발생 조건”아래 세 조건이 모두 맞을 때 발생한다.
- 타깃 OS: iOS 15 기기
- 빌드 환경: 앱이 iOS 16+ 전용 심볼(예:
RoomCaptureSessionView)을 포함해 빌드됨 - 라이브러리: Firebase(구 버전 C++ 구현체)가 포함되어 있고 AppDelegate 스위즐링이 켜져 있음
근본 원인
섹션 제목: “근본 원인”Firebase의 libFirebaseCppApp.a는 내부에서 firebase::util::ForEachAppDelegateClass를 실행해 AppDelegate를 찾고 스위즐링을 시도한다. 이 과정에서 objc_copyClassList를 호출해 앱 안의 모든 Objective-C·Swift 클래스 목록을 조회한다.
크래시 메커니즘
섹션 제목: “크래시 메커니즘”- 앱이 실행되면 Firebase가 전체 클래스 스캔을 위해
objc_copyClassList를 호출한다. - 목록에는 iOS 16에서만 쓸 수 있는 클래스(
RoomCaptureSessionView등)도 들어 있다. 이 클래스들은 weak linking 상태다. - 런타임은 목록을 만드는 과정에서 모든 클래스를 초기화(realization)한다. Firebase 이슈의 스택 트레이스에도
realizeAllClasses다음에 Swift 타입 메타데이터 초기화에서 실패하는 프레임이 찍혀 있다. - 해당 클래스의 부모 클래스나 프로토콜 정보를 찾으려 하지만 iOS 15 기기에는 그 프레임워크(RoomPlan 등)가 없다.
- Swift 런타임이 존재하지 않는 주소나 널 포인터에 접근해 크래시(
SIGABRT또는EXC_BAD_ACCESS)가 난다.
발생하는 iOS 버전
섹션 제목: “발생하는 iOS 버전”- iOS 15: Firebase 이슈의 보고는 모두 iOS 15.x(15.5, 15.8.4 등)다.
- iOS 14: 같은 이슈에서 크래시가 나지 않는다는 보고가 있다. 왜 다른지는 공개 자료에 설명이 없다.
- iOS 16 이상: 기기에 해당 프레임워크가 있으므로 클래스를 정상적으로 초기화해 문제가 없다.