crash-triagelisted
Install: claude install-skill gagip/gagip-dev
# crash-triage
크래시 목록을 훑는 것과 원인을 아는 것은 다르다. 이 스킬은 **집계 → 개별 이벤트 → 코드 대조**를
끝까지 밀어 "무엇이 몇 건"이 아니라 "왜 터지고 누가 고쳐야 하나"로 답을 만든다.
**핵심 원칙**:
- **건수 순위는 심각도 순위가 아니다.** 1위가 사용자에게 무해한 잡음일 수 있고, 3건짜리가 강제
종료일 수 있다. 순위와 별개로 치��도·현재성을 따로 판정한다.
- **이미 등록된 이슈를 다시 올리지 않는다.** 조사 결과의 절반은 "이건 이미 알고 있다"로 끝나는
게 정상이다. 중복 확인을 건너뛰면 저장소에 쓰레기 이슈가 쌓인다.
- **원인은 코드를 읽고 말한다.** 스택만 보고 추정한 원인은 리포트에 쓰지 않는다. 읽지 못했으면
"미확인"이라고 적는다.
---
## 실행 절차
### 1. 앱 ID를 찾는다
Crashlytics 도구는 전부 `appId`를 인자로 요구한다. 서버 설정에 프로젝트가 박혀 있지 않으므로
매 호출에 넘겨야 한다. 프로젝트 안에서 찾는다:
```bash
find . -name 'google-services.json' -o -name 'GoogleService-Info.plist' | grep -v node_modules
```
- Android: `google-services.json` → `client[].client_info.mobilesdk_app_id`
- iOS: `GoogleService-Info.plist` → `GOOGLE_APP_ID`
찾지 못하면 추측하지 말고 사용자에게 묻는다. 여러 앱이 나오면 어느 것을 볼지 확인하거나, 사용자가
범위를 안 정했으면 전부 순회하고 결과를 앱별로 나눠 보고한다.
### 2. 상위 이슈를 집계한다
`crashlytics_get_report`를 `report: "topIssues"`로 부른다. 기본은 최근 30일·상위 5건이고,
사용자가 기간이나 건수를 말했으면 그쪽을 쓴다. 조회 가능 범위는 최근 90일이며, 그보다 앞선
구간을 넣으면 거부된다.
집계만으로 판단이 안 서면 `topVersions`(특정 버전에 몰렸나) · `topAndroidDevices` ·
`topOperatingSystems`(기종·OS 편중인가)로 보조한다. 편중이 뚜렷하면 그 자체가 원인 단서다.
### 3. 이슈마다 실제 이벤트를 본다
`crashlytics_list_events`에 `filter.issueId`를 걸어 표본을 가져온다. 집계에는 없고 여기에만
있는 것들이 원인 규명의 핵심이다:
- **스택 트레이스** — 어디서 터졌나
- **커스텀 키** — 화면·로그인 상태·앱 버전 등 앱이 심어 둔 맥락
- **breadcrumb 로그** — 터지기 직전 무슨 일이 있었나(네트워크 응답 등)
- **기기·OS·앱 버전·이벤트 시각**
같은 이슈라도 표본을 2건 이상 보면 **무엇이 매번 달라지는지**가 드러난다. 이번 사례에서는
오류 메시지 안의 식별자 숫자가 매번 달라지는 것이 "요