안녕하세요. 오늘은 Tuist(4.x ver)에서 SPM으로 Firebase Crashlytics의 RunScript를 추가하는 방법에 대해서 소개하려구 합니다.
Firebase 회원가입, GoogleService-Info.plist 등록 방법은 생략하겠습니다.
RunScript에선 뭘 실행할까?
가장 중요한 것은
이 Crashyltics 패키지의 run 파일을 찾아서, 내부적으로 실행해
Crashlytics/upload-symbols 바이너리를 호출해주는 것입니다. (내부적으로 dSYM파일을 Firebase Crashlytics 서버에 업로드 해서 크래시 리포트를 우리가 읽을 수 있는 형식으로 심볼화 해주는것 입니다 런타임 때 크래시가 날 때 어느 클래스의 어느 함수를 실행할 때 앱이 튕긴다거나를 알 수 있게 됩니다.)
그렇기에 우리가 의존하는 SPM 패키지 또는 pod이던, 결국에 Build시점에 RunScript에서 Crashlytics/run을 찾아 실행하고, upload-symbols바이너리가 실행되게 됩니다.
1. run파일은 내부적으로 upload-symbols 경로를 Crashlytics 내부 디렉터리에서 찾아
2. 심볼 정보를 Firebase에 등록함
3. 런 타임때 앱이 동작되다가 의도치 않게 크래시가 날 경우!
어느 클래스의 어느 함수의 몇 번째 줄에서 발생했는지 알 수 있게 됨
가장 중요한 것은 저 경로!를 찾는 것입니다. Crashlytics가 위치한 곳에서 run을 찾는게 핵심입니다.
Pods의 경우
"${PODS_ROOT}/FirebaseCrashlytics/run"
이렇게 "${PODS_ROOT}" 환경 변수 사용하면 되는데 이것은 Pods 디렉터리의 절대 경로를 의미합니다. 여기에서 이제 설치된 Firebase Crashlytics 프레임워크의 run을 실행하면 내부적으로 upload-symbols를 해당 프레임워크에서 찾아 실행하게 됩니다.
Tuist를 사용하지 않는 Xcode에서 SPM사용시 RunScript에 firebase Crashlytics/run 실행되는 경우
"${BUILD_DIR%/Build/*}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run"
SPM은 내부적으로 Xcode 빌드 시스템에 통합됩니다.
그래서 Xcode가 프로젝트를 빌드하거나 실행할 때 SPM에서의 의존성들은 Xcode/DerivedData/MyApp-asdfw... 이 경로의 sourcePackages에 저장됩니다.
-> SPM의 패키지들은 SourcePackages 이 디렉터리에 Git에서 클론한 그 외부 패키지들이 있습니다. 마찬가지로 Crashlytics의 run 경로를 찾아서 upload-symbolds 바이너리를 실행합니다.
Tuist를 사용하는 Xcode에서 SPM사용시 RunScript에 firebase Crashlytics/run 경로 찾는 방법
Tuist가 버전이 바뀜에 따라, 다르지만 가장 중요한 것은 Crashlytics/run 경로를 찾는 것입니다.
4.x버전에서 SPM은 Package.swift에 선언을 해주시면 되는데,
저 같은 경우엔
-프로젝트/Tuist
-프로젝트/Projects
이렇게 Tuist디렉터리 안에 Package.swift 파일을 추가했습니다.
이 Package.swift파일 추가한 곳에서 Package.swift가 빌드될 때(tuist init - tuist generate) Tuist는 내부 빌드 수행하고 디렉터리에 .build파일을 만듭니다.
그래서 이렇게 checkouts에 보면 SPM으로 추가한 의존성들 그 의존성들이 내부적으로 의존하는 dependency가 클론됩니다. 그래서 firebase-ios-sdk/Crashlytics 디렉터리에서 run을 찾도록 script를 작성해주면 됩니다.
요약: Tuist기반이면 프로젝트에서 .build/checkouts/firebase-ios-dsk/Crashlytics/run 경로를 찾아서 실행하기!
저 같은 경우엔 프로젝트/Tuist/.build/checkouts ... 이렇게 프로젝트로부터 Tuist디렉터리 안에 존재하기 때문이 이 경로를 찾아서 runscript가 실행할 수 있도록 지정해주었습니다.
extension TargetScript {
public static let firebaseCrashlytics: TargetScript = .post(
script: """
echo "📦 Uploading dSYM to Firebase Crashlytics ... 경로를 꼭 찾아야 대쉬보드가 보임!!"
ROOT_PATH="$SRCROOT"
while [ "$ROOT_PATH" != "/" ]; do
if [ -d "$ROOT_PATH/Tuist" ]; then
echo "Found Tuist directory: $ROOT_PATH/Tuist"
break
fi
ROOT_PATH=$(dirname "$ROOT_PATH")
done
"${ROOT_PATH}/Tuist/.build/checkouts/firebase-ios-sdk/Crashlytics/run"
""",
name: "FirebaseCrashlytics",
inputPaths: [
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}",
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${PRODUCT_NAME}",
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist",
"$(TARGET_BUILD_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/GoogleService-Info.plist",
"$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)"
],
basedOnDependencyAnalysis: false
)
}
Firebase Crashlytics의 가이드대로 잘 따라 했고 여전히 Firebase Crashlytics에서는 crash를 기다리고 있다면 위에처럼 Crashlytics/run ( upload-symbols )경로를 찾지 못하는 경우도 이유 중 하나일 수 있습니다.
또는
이 경우대로 해야합니다.
1. 시뮬 or 앱을 지운다.
2. 프로젝트를 실행한다.(build and run in xcode)
3. 프로젝트가 실행되면 Xcode에서 프로젝트를 중지한다!
4. 설치된 앱을 프로젝트 실행하지 않고 들어가서 crash를 두 세번 낸다(crash할 수 있는 버튼을 눌러서 앱이 튕기도록)
5. 다시 프로젝트를 실행하면 (build and run in xcode) 보고가 올라간다.
(5~30분 기다린다)
제가 해맸던 경우입니다.
그럼에도 대쉬보드가 보이지 않는다면 Firebase의 버전이 너무 높지는 않은지, 버전 한 단계만 맞춰보세요.
파이어베이스 디버그 로깅을 활성화 하고 이렇게 에러가 성공적으로 보고됬다고 저 사진 처럼 몇줄?의 [FirebaseCrashylytics]로그가 콘솔창에 뜨지만 여전히 대쉬보드가 보이지 않았습니다.
이때 상황은 github에서 firebase 태그에서 릴리즈 된 최신 버전을 의존성으로 했었는데, 한 단계를 낮추니 정상적으로 반응하더라구요.
Firebase 버전 (11.11.0 -> 10.24.0)
버전을 바꾸고 다시 크래시 내고서 xcode를 실행하니 위에 출력된 로그 양의 3~4배가 나오던데 그렇게 나와야 정상적으로 동작되는 느낌이 들었었습니다.
좋은점?
실제로 배포중인 앱이 비정상적인 종료를 발생했는데, 크래시 로그가 firebase crashlytics 로그에 나타나서 다행히 수정할 수 있게되었습니다.
'iOS > JourneyOfFaith App' 카테고리의 다른 글
[iOS] No 6. iOS앱 AppStore에 출시 후기!! (0) | 2025.04.22 |
---|---|
[iOS] No 4. Scale up 기본 애니메이션에 변화 주기 with AnchorPoint + 발생 가능한 에러 해결하기 (0) | 2025.04.01 |
[iOS] No 3. 메모리 점유율 줄이기. Retain cycle 형성 원인 분석 및 해결 과정 (0) | 2025.03.30 |
[iOS] No 2 Database. illegal multi-threaded access to database connection! 디비 접근 동시성 충돌 (0) | 2025.03.30 |