React Native Crash와 ANR: 앱 종료와 무응답을 어떤 증거로 나누는가
같은 “앱이 멈췄다” 신고를 화면 증상만으로 분류하는 실패를 재현하고, Android 종료 이유·ANR 기록, iOS crash·hang 진단과 React Native 실행 흐름을 서로 다른 증거로 보존한다.
목차
표준·구현·측정·해석 표시는 무엇인가요?
- 표준웹 표준이나 언어 명세가 정한 동작
- 구현특정 기술이나 브라우저가 실제로 구현한 동작
- 측정명시한 환경에서 직접 실행해 관찰한 결과
- 해석앞선 근거에서 도출한 설계 판단
- 미확인아직 공식 근거나 재현 결과를 확인하지 못한 내용
30초 요약
Crash는 처리되지 않은 오류나 신호 등으로 앱 process가 예기치 않게 끝난 사건이다. Application Not Responding(ANR, 앱 무응답)은 Android가 앱이 정해진 시간 안에 입력이나 특정 플랫폼 작업에 응답하지 못했다고 판정한 사건이다. iOS는 같은 사용자 증상을 ANR이라고 부르지 않고 crash 보고서와 hang 진단을 따로 제공한다.
React Native에서는 JavaScript 실행 흐름이 오래 막혀 React 사건 처리가 늦어져도 Android UI 스레드가 계속 움직일 수 있다. 그러므로 화면 증상은 조사 시작점이고, 분류는 플랫폼 원본 증거로 닫는다.
jetsam은 iOS가 메모리를 회수하려 앱 process를 끝내고 그때의 메모리 상황을 별도 보고서로 남기는 체계다. 따라서 화면이 사라졌다는 사실만으로 Apple crash라고 분류하지 않는다.
앱 process 종료 Android exit reason / Apple crash·jetsam 보고서
Android 무응답 ANR 범주 / 당시 trace와 관련 스레드
iOS 무응답 hang 진단 / responsiveness 보고서
JavaScript 지연 JS heartbeat 간격 / native UI가 계속 움직였는지반복해서 기억할 문장은 이것이다.
“멈췄다”는 증상을 기록하되, crash·ANR·hang 분류는 운영체제 증거로 결정한다.
이 글을 관통하는 상황: 결제 완료 뒤 화면이 멈췄다가 사라졌다
결제 완료 버튼을 누른 일부 사용자는 “화면이 몇 초 멈췄고 앱이 사라졌다”고 신고했다. 팀은 모든 신고를
crash 한 묶음에 넣고, JavaScript heartbeat가 3초 넘게 비면 ANR이라고 저장했다. heartbeat는 앱이
일정 간격으로 남기는 “현재 JavaScript가 실행 중” 기록이다.
하지만 같은 설명에는 서로 다른 사건이 섞일 수 있다.
- 처리되지 않은 네이티브 오류로 process가 끝난 Android crash
- Android가 UI 스레드의 장시간 차단을 판정한 ANR
- process는 살아 있지만 JavaScript 계산 때문에 React 사건만 늦어진 상태
- iOS가 별도 hang 진단으로 수집한 무응답
이 글의 질문은 하나다.
앱이 종료되는 오류와 응답하지 않는 상태를 어떤 증거로 나눠 조사하는가?
화면 증상만으로 분류하면 두 번 틀린다
잘못된 분류 규칙은 “process가 끝났으면 crash, process가 살아 있고 화면이 멈췄으면 ANR”이다. 이 규칙은 두 가지를 놓친다.
첫째, ANR 뒤 process가 종료된 기록도 있다. 둘째, React Native JavaScript 실행 흐름만 막혀 React 버튼이 늦게 반응하는 동안에도 Android UI 스레드가 맡은 native scroll은 계속 움직일 수 있다. 후자는 무응답 증상이지만 그 사실만으로 Android ANR은 아니다.
같은 증거 묶음을 잘못된 규칙과 교정 규칙으로 비교한다
20편에서 이어 쓴 React Native 프로젝트의 App.tsx를 교체한다. 외부 패키지는 필요 없다. 이 코드는
실제 crash·ANR·hang을 만들지 않는 가상 fixture다. 플랫폼 진단에서 가져올 최소 필드의 모양과 분류
순서만 반복 검증한다.
processExited는 process가 끝났는지, androidExitReason은 Android가 기록한 종료 이유,
appleDiagnostic은 Apple 보고서 범주다. jsHeartbeatGapMs는 JavaScript 기록 사이의 간격이고,
nativeScrollContinued는 같은 시간에 UI 스레드의 native scroll이 계속 움직였는지 나타낸다.
USE_PLATFORM_EVIDENCE = false가 잘못된 기준선이다.
import React, { useState } from 'react'
import { Button, SafeAreaView, StyleSheet, Text, View } from 'react-native'
const USE_PLATFORM_EVIDENCE = false
type AndroidExitReason =
| 'REASON_CRASH'
| 'REASON_CRASH_NATIVE'
| 'REASON_ANR'
| 'REASON_USER_REQUESTED'
| null
type AppleDiagnostic = 'crash' | 'hang' | 'jetsam' | null
type SharedEvidence = {
id: string
reportedFrozen: boolean
processExited: boolean
jsHeartbeatGapMs: number
nativeScrollContinued: boolean
}
type AndroidEvidence = SharedEvidence & {
platform: 'android'
androidExitReason: AndroidExitReason
androidAnrTraceAvailable: boolean
}
type AppleEvidence = SharedEvidence & {
platform: 'ios'
appleDiagnostic: AppleDiagnostic
}
type EvidenceCase = AndroidEvidence | AppleEvidence
type Classification =
| 'crash'
| 'android-anr'
| 'ios-hang'
| 'memory-termination'
| 'other-termination'
| 'js-thread-stall-symptom'
| 'needs-platform-evidence'
type Result = {
id: string
classification: Classification
evidence: string
}
const CASES: EvidenceCase[] = [
{
id: 'android-crash',
platform: 'android',
reportedFrozen: false,
processExited: true,
androidExitReason: 'REASON_CRASH',
androidAnrTraceAvailable: false,
jsHeartbeatGapMs: 80,
nativeScrollContinued: false,
},
{
id: 'android-anr-killed',
platform: 'android',
reportedFrozen: true,
processExited: true,
androidExitReason: 'REASON_ANR',
androidAnrTraceAvailable: true,
jsHeartbeatGapMs: 5200,
nativeScrollContinued: false,
},
{
id: 'react-native-js-stall',
platform: 'android',
reportedFrozen: true,
processExited: false,
androidExitReason: null,
androidAnrTraceAvailable: false,
jsHeartbeatGapMs: 4200,
nativeScrollContinued: true,
},
{
id: 'ios-hang',
platform: 'ios',
reportedFrozen: true,
processExited: false,
appleDiagnostic: 'hang',
jsHeartbeatGapMs: 3600,
nativeScrollContinued: false,
},
]
function classifyFromSymptom(input: EvidenceCase): Result {
if (input.processExited) {
return {
id: input.id,
classification: 'crash',
evidence: 'process 종료만 확인',
}
}
if (input.reportedFrozen) {
return {
id: input.id,
classification: 'android-anr',
evidence: '사용자 무응답 신고만 확인',
}
}
return {
id: input.id,
classification: 'needs-platform-evidence',
evidence: '플랫폼 원본 없음',
}
}
function classifyFromPlatformEvidence(input: EvidenceCase): Result {
if (input.platform === 'android') {
if (
input.androidExitReason === 'REASON_CRASH' ||
input.androidExitReason === 'REASON_CRASH_NATIVE'
) {
return {
id: input.id,
classification: 'crash',
evidence: input.androidExitReason,
}
}
if (input.androidExitReason === 'REASON_ANR') {
return {
id: input.id,
classification: 'android-anr',
evidence: input.androidAnrTraceAvailable
? 'REASON_ANR + trace 있음'
: 'REASON_ANR + trace 없음',
}
}
if (input.processExited && input.androidExitReason !== null) {
return {
id: input.id,
classification: 'other-termination',
evidence: input.androidExitReason,
}
}
}
if (input.platform === 'ios' && input.appleDiagnostic === 'crash') {
return { id: input.id, classification: 'crash', evidence: 'Apple crash' }
}
if (input.platform === 'ios' && input.appleDiagnostic === 'hang') {
return { id: input.id, classification: 'ios-hang', evidence: 'Apple hang' }
}
if (input.platform === 'ios' && input.appleDiagnostic === 'jetsam') {
return {
id: input.id,
classification: 'memory-termination',
evidence: 'Apple jetsam',
}
}
if (
!input.processExited &&
input.jsHeartbeatGapMs >= 3000 &&
input.nativeScrollContinued
) {
return {
id: input.id,
classification: 'js-thread-stall-symptom',
evidence: `JS ${input.jsHeartbeatGapMs}ms / native scroll 계속`,
}
}
return {
id: input.id,
classification: 'needs-platform-evidence',
evidence: '운영체제 원본을 더 수집',
}
}
export default function App() {
const [results, setResults] = useState<Result[]>([])
function runClassification() {
const classify = USE_PLATFORM_EVIDENCE
? classifyFromPlatformEvidence
: classifyFromSymptom
setResults(CASES.map(classify))
}
return (
<SafeAreaView style={styles.screen}>
<Text style={styles.title}>Crash·ANR 증거 분류 fixture</Text>
<Text>
플랫폼 증거 사용: {USE_PLATFORM_EVIDENCE ? 'on' : 'off'}
</Text>
<Button title="4개 사례 분류" onPress={runClassification} />
<View style={styles.results}>
{results.map(result => (
<View key={result.id} style={styles.row}>
<Text>{result.id}</Text>
<Text>분류: {result.classification}</Text>
<Text>근거: {result.evidence}</Text>
</View>
))}
</View>
</SafeAreaView>
)
}
const styles = StyleSheet.create({
screen: { flex: 1, padding: 16, gap: 12 },
title: { fontSize: 22, fontWeight: '700' },
results: { gap: 10 },
row: { borderWidth: 1, borderColor: '#8A8A8A', padding: 10, gap: 4 },
})실행 전에 예측한다.
- process가 끝난
android-anr-killed를 증상 규칙은 무엇으로 분류할까? - process가 살아 있고 native scroll이 계속된 JavaScript 지연을 ANR이라고 확정할 수 있을까?
- iOS hang을 Android ANR 이름으로 저장하면 어떤 원본 정보를 잃을까?
개발자 메뉴에서 Reload한 뒤 4개 사례 분류를 누른다.
android-crash → crash
android-anr-killed → crash
react-native-js-stall → android-anr
ios-hang → android-anr첫 결과만 맞다. Android ANR 뒤 process가 끝난 사례를 crash로 합쳤고, JavaScript 지연과 iOS hang을 Android ANR로 잘못 이름 붙였다.
운영체제 증거를 분류의 입구로 쓴다
상수를 바꾼다.
const USE_PLATFORM_EVIDENCE = trueReload 뒤 같은 버튼을 누른다.
android-crash → crash / REASON_CRASH
android-anr-killed → android-anr / REASON_ANR + trace 있음
react-native-js-stall → js-thread-stall-symptom / JS 4200ms / native scroll 계속
ios-hang → ios-hang / Apple hang교정 규칙은 사용자의 설명을 버리지 않는다. reportedFrozen, 마지막 제품 행동과 heartbeat 간격은 플랫폼
원본을 찾는 문맥으로 남긴다. 다만 crash·ANR·hang의 최종 이름을 그 문맥만으로 정하지 않는다.
이 fixture가 증명하는 것은 같은 입력 필드에 대한 분류 순서와 화면 결과다. 실제 Android가 ANR을 만들었거나 Apple 기기가 hang 진단을 수집했다는 증거는 아니다.
Android는 종료 이유와 ANR trace를 따로 읽는다
ApplicationExitInfo는 Android가 남긴 앱 process 종료 기록 객체다. reason은 종료 이유 코드이고,
timestamp는 종료 시각이다. traceInputStream은 종료 전에 수집한 실행 기록 데이터를 차례로 읽는
입구이며, 기록이 없으면 null일 수 있다. 이 세 값의 역할을 먼저 나눈 뒤 아래 계약을 읽는다.
앱 시작 때 최근 기록을 수집한다면 다음 순서를 지킨다.
1. timestamp와 reason으로 종료 사건을 식별
2. REASON_CRASH / REASON_CRASH_NATIVE / REASON_ANR을 다른 범주로 보존
3. reason이 ANR이면 trace stream을 추가 증거로 읽되 null 가능성 처리
4. 앱 버전·React Native 버전·기기·마지막 비민감 제품 행동과 연결
5. 같은 종료 사건을 다음 시작마다 중복 전송하지 않도록 사건 ID 저장description은 사람이 읽는 설명이며 Android 버전과 기기 사이에서 안정된 형식을 보장하지 않는다. 문자열을
파싱해 분류 규칙으로 쓰지 않는다. trace가 있다는 이유만으로 reason을 덮어쓰지도 않는다.
ANR이 항상 process 종료로 이어지는 것도 아니다. 앱이 회복될 수 있으므로 API 30 이상의 종료 기록만으로 모든 ANR을 셀 수 없다. Android vitals는 Google Play가 기기에서 동의받아 수집한 crash·ANR을 묶어 보는 운영 품질 화면이다. 운영 배포에서는 이 화면의 ANR cluster와 해당 시점의 trace를 함께 본다. cluster는 같은 원인 후보의 보고서를 묶어 보는 단위다.
Android ANR에서는 “어느 스레드가 왜 기다렸는가”를 묻는다
Android 입력 전달 ANR은 일반적으로 앱 UI 스레드가 입력에 제때 답하지 못할 때 발생한다. Android Open Source Project(AOSP, Android 공개 기반 코드)와 Pixel 기기의 기본 입력 응답 제한 시간은 5초지만 제조사와 시스템 상태에 따라 달라질 수 있으므로 제품 코드에 5초 숫자를 판정기로 복사하지 않는다.
ANR trace를 열면 먼저 ANR 종류와 UI 스레드 상태를 연결한다.
화면 입력 응답 제한 UI 스레드가 touch·key 입력 처리 중 무엇을 실행·대기했는가
broadcast 수신 제한 Android 사건을 받는 함수가 제때 끝났는가
service 시작 제한 화면에 보이지 않는 동안에도 운영체제가 시작할 수 있는 구성요소의 시작 함수가 제때 끝났는가
잠금 대기 한 작업만 자원에 들어가게 막는 잠금을 어느 스레드가 쥐고 있는가
느린 운영체제 호출 앱 스레드가 실제로 실행됐는지, Android 시스템 서비스가 느렸는가UI 스레드의 위쪽 한 프레임만 보고 원인을 확정하지 않는다. 잠금을 기다린다면 잠금을 가진 스레드를 본다. Perfetto는 시간축으로 여러 스레드와 Android 시스템 작업을 함께 기록하는 추적 도구다. 운영체제 문제 가능성이 있으면 Perfetto에서 앱 UI 스레드가 실행 중인지·실행 대기인지와 Android 시스템 서비스 상태를 함께 본다.
JavaScript 스택과 UI 스레드 trace도 같은 것으로 합치지 않는다. React Native 연결 코드가 UI 스레드에서 JavaScript 결과를 같은 자리에서 끝날 때까지 기다렸는지, 네이티브 SDK가 결과를 알릴 때 실행하는 함수가 UI 스레드를 막았는지처럼 두 실행 흐름이 만나는 경로를 증거로 연결한다.
iOS는 crash와 hang 진단을 나눠 읽는다
MetricKit은 기기가 수집한 성능·진단 보고서를 앱이 받게 하는 Apple API다. Xcode의 responsiveness 도구는 Mac 개발 도구에서 무응답 보고서를 수집·분석하는 기능 묶음이다. 이 역할을 먼저 구분한 뒤 Claim을 읽는다.
iOS에서 화면이 사라졌다고 모두 crash라고 부르지 않는다. Apple은 다음 원본을 구분한다.
crash report는 앱 종료 이유와 당시 각 스레드 호출 목록을 담은 보고서다. hang diagnostic은 UI 스레드가 오래 실행 중이거나 다른 작업·자원을 기다리느라 막혀 입력을 제때 처리하지 못한 구간의 호출 경로를 담은 진단 보고서다. device console log는 같은 시점의 운영체제·앱 보조 사건을 시간순으로 보여 주는 기록이다. exception은 실행 중 발생한 예외 조건이다.
| 원본 | 먼저 답하는 질문 |
|---|---|
| crash report | 어떤 종료와 exception이 있었고 당시 각 스레드는 무엇을 실행했는가 |
| hang diagnostic | UI 실행 흐름이 오래 일하거나 작업·자원을 기다리느라 막혔을 때 어떤 호출 경로가 오래 걸렸는가 |
| jetsam event report | 메모리 압박 때문에 운영체제가 앱을 종료했는가 |
| device console log | 같은 시점에 운영체제와 앱에서 어떤 보조 사건이 있었는가 |
글에서는 원본 범주를 먼저 고정하고, 주소와 축약된 함수 이름을 처음 작성한 코드 위치로 되돌리는 일은 27편으로 넘긴다.
Apple의 on-device Hang Detection은 지원 실기기의 Developer 설정에서 무응답 기록 수집을 켜는 기능이다. 수집한 hang 보고서는 Mac에서 분석한다. Xcode Organizer는 배포 앱의 진단을 모아 보는 Xcode 화면이다. Simulator에서 UI 지연을 재현하는 것만으로 실제 기기 hang 보고서가 수집됐다고 주장하지 않는다.
공통 제품 분류와 플랫폼 원본을 동시에 보존한다
대시보드에서 공통 분류가 필요해도 원본을 덮어쓰지 않는다.
공통 영향의 terminated는 종료됨, unresponsive는 응답 없음, degraded는 앱은 계속 실행되지만 성능이
저하됨을 뜻한다. attempt ID는 한 번의 제품 시도와 여러 기록을 잇는 식별값이다.
공통 영향 terminated / unresponsive / degraded
플랫폼 원본 android-crash / android-anr / ios-crash / ios-hang / ios-jetsam
실행 경계 JavaScript / UI thread / 플랫폼 background 작업 / 운영체제
버전 app / React Native / platform SDK / 운영체제
사건 문맥 마지막 비민감 제품 단계 / attempt ID / timestamp
원본 증거 위치 Android cluster·trace / Apple 보고서·진단 기록응답 없음(unresponsive)이라는 공통 영향 아래 iOS hang과 Android ANR을 함께 볼 수는 있다. 그러나 원본
필드를 지우면 각 플랫폼의 응답 제한 시간, trace와 수집 조건을 잃는다. JavaScript stall은 운영체제 범주가
확인되기 전까지 성능 저하(degraded)나 별도 증상으로 남긴다.
로그에는 token, 결제 정보, 광고 내용, 사용자 입력과 전체 메모리를 남기지 않는다. 실패를 연결하는 데 필요한 버전·비민감 단계·시간·사건 ID만 수집하고, 플랫폼 보고서 접근 권한과 보존 기간을 제한한다.
emulator·Simulator와 실기기 증거를 구분한다
| 검증 | Android emulator | iOS Simulator | 지원 실기기·운영 집계 |
|---|---|---|---|
| 분류 fixture 화면 | 확인 | 확인 | 필요 시 회귀 확인 |
| JavaScript 지연과 native scroll 차이 | 통제 입력으로 관찰 | 통제 입력으로 관찰 | 지원 기기에서 재측정 |
| Android ANR 종류·trace | Android 기능 수준 30 이상 emulator의 개발용 앱에서 재현 | 해당 없음 | 기기·Android vitals로 최종 확인 |
| Apple crash·hang 원본 | 해당 없음 | crash 개발 재현 보조 | 기기 보고서·Hang Detection·Organizer/MetricKit |
| 제조사·메모리·운영체제 부하 | 제한적 | 제한적 | 실제 지원 조건에서 확인 |
의도적으로 UI 스레드를 막거나 process를 crash시키는 fixture는 개인 데이터가 없는 개발용 앱과 emulator·Simulator에서만 실행한다. 운영 앱, 실제 결제·광고 흐름과 개인 실기기에서 강제하지 않는다. 실기기 접근이 필요하면 사용자 승인, 테스트 계정과 민감 정보 마스킹 조건을 먼저 갖춘다.
pull request에서 달라져야 할 행동
Crash·무응답 관련 pull request에는 다음 표가 있어야 한다.
사용자 증상 사라짐·입력 지연·화면 정지를 원본 범주와 분리했는가
process 증거 이전 process 종료 여부와 종료 이유를 확인했는가
Android 원본 crash reason과 ANR reason·trace를 구분했는가
iOS 원본 crash·hang·jetsam 보고서를 구분했는가
스레드 증거 JavaScript와 UI 스레드 중 무엇이 실행·대기했는가
재현 환경 개발용 fixture·emulator·Simulator·실기기 범위를 적었는가
버전 앱·React Native·운영체제·기기·SDK를 기록했는가
개인정보 token·사용자 입력·전체 메모리를 수집하지 않는가
교정 검증 같은 플랫폼 원본 범주의 재현이 사라졌는가검토자는 다음을 확인한다.
- 화면이 멈췄다는 이유만으로 Android ANR이라고 이름 붙이지 않는가?
- 앱이 다시 시작됐다는 이유만으로 crash라고 이름 붙이지 않는가?
- JavaScript heartbeat를 플랫폼 crash·ANR 판정기로 사용하지 않는가?
- Android 종료 reason과 trace 존재 여부를 한 필드처럼 취급하지 않는가?
- iOS hang과 Android ANR의 원본 범주를 지우지 않는가?
- 평균이나 전체 비율만 보고 가장 큰 기기·버전 cluster를 놓치지 않는가?
- 원본 stack 복원 전에 사용자 설명만으로 코드 위치를 추측하지 않는가?
- 실제 지원 기기 증거 없이 개발용 fixture 결과를 운영 결론으로 확대하지 않는가?
한 장으로 다시 보기
문제 “화면이 멈췄다가 앱이 사라졌다”는 신고
오판 process 종료=crash, 화면 정지=Android ANR로 즉시 분류
실패 killed ANR은 crash로, JS stall과 iOS hang은 ANR로 잘못 저장
교정 Android exit reason·ANR trace, Apple crash·hang 원본부터 읽음
React Native 경계 JavaScript 실행 지연은 중요한 문맥이지만 ANR 단독 증거가 아님
Android crash와 ANR을 분리하고 reason과 trace도 별도 필드로 보존
iOS crash report·hang diagnostic·jetsam report를 분리
검증 가상 분류 규칙과 실제 플랫폼 진단 수집 범위를 구분
다음 25~27편에서 JavaScript·Android·iOS stack 위치를 복원사용자 증상은 문제를 발견하는 가장 중요한 출발점이다. 그러나 같은 증상을 만드는 실행 경계가 여러 개이므로 분류는 운영체제가 남긴 종료·무응답 기록으로 닫아야 한다. 그 다음에야 어느 stack을 복원하고 어느 스레드의 기다림을 줄일지 선택할 수 있다.
스스로 확인할 질문
- React Native 화면이 몇 초 멈췄다는 사실만으로 Android ANR을 확정할 수 없는 이유는 무엇인가?
- Android
ApplicationExitInfo.reason과traceInputStream을 왜 다른 증거로 읽어야 하는가? - JavaScript 실행 흐름 지연과 Android UI 스레드 ANR은 어떤 관찰로 나눌 수 있는가?
- iOS에서 crash와 hang, jetsam을 어떤 원본 보고서로 구분하는가?
- 가상 분류 fixture의 네 결과가 실제 플랫폼 사건을 증명하지 않는 이유는 무엇인가?
- 공통
unresponsive분류를 만들 때 플랫폼 원본 필드를 왜 함께 보존해야 하는가?
Active recall
기억에서 꺼내 보기
답을 쓰지 않아도 됩니다. 먼저 머릿속으로 답한 뒤 펼쳐서 정답·이유·흔한 오해를 비교하세요.
01React Native 버튼이 늦게 반응하고 화면이 멈춘 것처럼 보이면 Android ANR이 발생했다고 결론내려도 될까?
정답
아니다. JavaScript 실행 흐름 지연도 React 사건과 화면 갱신을 늦출 수 있다. Android ANR은 운영체제의 ANR 기록과 당시 관련 스레드 증거로 확인한다.
관련 설명 다시 읽기왜 그런가
사용자가 본 무응답 증상과 운영체제가 판정한 ANR 범주는 같은 증거가 아니다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
02앱 화면이 사라지고 다음 실행에서 새 process가 만들어졌다면 crash가 확정될까?
정답
아니다. 운영체제 회수, 사용자 중지, 업데이트와 메모리 압박도 process를 끝낼 수 있다. Android 종료 이유나 Apple 진단 보고서로 범주를 확인한다.
관련 설명 다시 읽기왜 그런가
새 실행은 이전 process가 끝났다는 증거이지 종료 원인을 단독으로 설명하지 않는다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
03Android의 이전 종료 기록에 ANR trace가 있으면 마지막 종료 이유도 반드시 ANR일까?
정답
아니다. 먼저 reason을 읽는다. 이전에 회복한 ANR trace가 남은 뒤 process가 다른 이유로 끝난 기록에도 trace가 포함될 수 있다.
관련 설명 다시 읽기왜 그런가
reason과 trace 존재 여부는 서로 다른 필드이며 trace stream은 없거나 덮어써질 수도 있다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
04iOS 앱이 사용자 입력에 반응하지 않으면 Android ANR과 같은 이름으로 저장해도 될까?
정답
아니다. 공통 제품 분류는 무응답일 수 있지만 플랫폼 원본은 iOS hang 진단과 Android ANR을 구분해 보존한다.
관련 설명 다시 읽기왜 그런가
플랫폼 수집 조건과 보고서 형식이 다르므로 한 원본 범주로 합치면 조사 입구를 잃는다.
선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.
출처와 검증 범위
아래 날짜는 링크를 마지막으로 열어 본 날입니다. 문서 상단의 검증일은 글의 설명과 적용 범위를 다시 확인한 날입니다.
- Performance OverviewReact Native · 공식 문서 · 확인 2026-08-09
- CrashesAndroid Developers · 공식 문서 · 확인 2026-08-09
- Diagnose and fix ANRsAndroid Developers · 공식 문서 · 확인 2026-08-09
- ApplicationExitInfoAndroid Developers · 공식 문서 · 확인 2026-08-09
- Android 11 Features and APIs — App process exit reasonsAndroid Developers · 공식 문서 · 확인 2026-08-09
- Android vitalsAndroid Developers · 공식 문서 · 확인 2026-08-09
- Diagnosing issues using crash reports and device logsApple Developer · 공식 문서 · 확인 2026-08-09
- Improving app responsivenessApple Developer · 공식 문서 · 확인 2026-08-09
- Monitoring app performance with MetricKitApple Developer · 공식 문서 · 확인 2026-08-09
- HangDiagnosticApple Developer · 공식 문서 · 확인 2026-08-09
- Run apps on the Android EmulatorAndroid Developers · 공식 문서 · 확인 2026-08-09
- Run apps on a hardware deviceAndroid Developers · 공식 문서 · 확인 2026-08-09
- Running your app on simulated or physical devicesApple Developer · 공식 문서 · 확인 2026-08-09