로그 분석 대시보드 Android logcat 파일 분석
← 아티클 목록

ANR 로그 분석하기 — Reason 읽기부터 traces의 메인 스레드까지

심화 · 응답 없음(ANR) · Android 공식 문서 기준 · 2026년 10월 5일

ANR(Application Not Responding)은 크래시와 달리 프로세스가 죽지 않아도 생깁니다. 사용자는 "리모컨이 안 먹는다", "화면이 멈췄다"고 말하고, 로그에는 ANR in 한 줄과 몇 줄의 요약만 남습니다. 이 글은 그 요약에서 종류를 가려내고, 메인 스레드가 그 순간 무엇을 하고 있었는지 찾아가는 순서를 정리합니다. 시간 기준은 Android Developers의 Diagnose and fix ANRs 문서를 따랐습니다.

1. logcat에 남는 ANR 요약

E ActivityManager: ANR in com.example.tv (com.example.tv/.MainActivity)
E ActivityManager: PID: 1102
E ActivityManager: Reason: Input dispatching timed out (...)
E ActivityManager: Parent: com.example.tv/.MainActivity
E ActivityManager: Load: 3.2 / 2.9 / 2.5
E ActivityManager: CPU usage from 0ms to 8123ms later (...):
E ActivityManager:   87% 1102/com.example.tv: 80% user + 7% kernel / faults: 1520 minor
E ActivityManager:   12% 512/system_server: 8% user + 4% kernel

버전과 제조사에 따라 줄의 구성은 조금씩 다르지만, 보통 다음 순서로 읽습니다.

  1. ANR in — 어느 앱, 어느 화면(괄호 안 컴포넌트)인지.
  2. PID — 이후 같은 PID의 기록을 따라가는 열쇠. 크래시와 달리 ANR 뒤에도 PID가 그대로일 수 있습니다(사용자가 "기다리기"를 고르거나 시스템이 종료하지 않은 경우).
  3. Reason — 가장 중요합니다. 무엇이 늦었는지에 따라 조사 방향이 갈립니다(아래 2장).
  4. CPU usage — 해당 앱이 CPU를 거의 다 쓰고 있었다면 무거운 계산, 앱은 한가한데 응답이 없었다면 무언가를 기다리는 중(잠금, 디스크, 네트워크, 다른 프로세스 호출)일 가능성이 큽니다. 기기 전체가 바빴다면 앱만의 문제가 아닐 수 있습니다.

2. Reason으로 종류 가리기

종류Reason에 보이는 표현(예)기본 시간 기준
입력 처리(Input dispatch)Input dispatching timed out5초
포커스 창 없음... does not have a focused window5초 (입력 ANR의 한 종류)
브로드캐스트 수신(포그라운드)Broadcast of Intent { ... }Android 13 이하 10초, 14 이상 10~20초
브로드캐스트 수신(백그라운드)Broadcast of Intent { ... }Android 13 이하 60초, 14 이상 60~120초
서비스 실행(포그라운드)executing service ...20초
서비스 실행(백그라운드)executing service ...200초
포그라운드 서비스 시작Context.startForegroundService() did not then call Service.startForeground()5초 안에 startForeground() 호출 필요

Reason 문장은 버전마다 표현이 다르므로 위 표의 문구는 "이런 단어가 들어 있다" 정도로 보세요. 시간 기준은 기기 제조사가 바꿀 수 있습니다.

셋톱박스·TV에서 특히 흔한 것

리모컨은 키 이벤트를 계속 보내므로 입력 처리 ANR이 가장 흔합니다. 채널 전환이나 목록 스크롤처럼 키를 빠르게 연속으로 누르는 동작 중에 메인 스레드가 한 번 멈추면, 뒤따르는 키 이벤트가 쌓이면서 5초 기준을 넘기 쉽습니다. 부팅 직후 여러 앱이 동시에 브로드캐스트를 받는 시점에는 브로드캐스트 ANR도 자주 나옵니다.

3. 메인 스레드 스택 확보하기

logcat의 요약만으로는 "왜 멈췄는지"까지 알 수 없습니다. ANR이 나면 시스템은 그 순간 모든 스레드의 스택을 traces 파일로 남깁니다. 공식 문서 기준 위치는 기기의 /data/anr/이며, 일반 사용자 빌드에서는 이 폴더를 직접 읽을 권한이 없는 경우가 많아 보통 버그 리포트로 받습니다.

adb bugreport bugreport.zip      # 압축 파일 안(대개 FS/data/anr/)에 traces가 들어 있음
adb pull /data/anr/              # 루팅·개발용(userdebug) 빌드라면 직접 받을 수도 있음

버그 리포트는 수십 MB가 되고 시간이 걸리므로, ANR이 재현된 직후에 받아야 합니다. 시간이 지나면 다른 ANR 기록으로 덮일 수 있습니다.

4. traces에서 "main" 스레드 읽기

traces 파일에서 해당 PID 블록을 찾고, 그 안의 "main" 스레드부터 봅니다. 첫 줄의 상태 단어가 방향을 정해 줍니다.

상태(예)뜻다음에 볼 것
"main" ... Blocked다른 스레드가 쥔 잠금을 기다림waiting to lock ... held by thread N의 그 스레드 스택
"main" ... Waiting / TimedWaiting대기·잠자기(wait, park, sleep)무엇을 기다리는지(다른 스레드의 결과, Future 등)
"main" ... Native네이티브 코드 실행 중 또는 시스템 호출 대기스택에 binder 호출·파일 입출력·소켓이 있는지
"main" ... Runnable실제로 일을 하고 있음스택 맨 위의 앱 코드 — 무거운 연산·큰 JSON 파싱·이미지 디코딩 등

스택에 MessageQueue.nativePollOnce만 보이면 메인 스레드는 쉬고 있던 상태입니다. 공식 문서는 이 경우 스택이 늦게 찍혔거나 시스템 쪽 문제일 수 있다고 설명합니다 — 이때는 CPU 사용률과 같은 시각의 다른 프로세스 기록을 함께 봐야 합니다.

스택에서 자주 보이는 원인

5. logcat에서 ANR 직전 구간 읽기

traces를 받을 수 없더라도 logcat에서 할 수 있는 것이 있습니다.

  1. ANR 시각에서 최소 5초, 넉넉히 20초 전까지 같은 PID의 기록을 거슬러 올라갑니다. 입력 ANR이라면 5초 전에 무엇이 시작됐는지가 핵심입니다.
  2. 같은 PID의 Choreographer: Skipped N frames가 점점 커지다가 ANR로 이어지는지 봅니다. 이 대시보드의 프레임 누락 패턴이 그 흔적입니다.
  3. 네트워크 시간 초과, 큰 파일 읽기, 데이터베이스 기록 같은 앱 자체 로그가 그 구간에 있는지 확인합니다.
  4. 같은 ANR이 다른 날·다른 기기에도 있다면 처음 발생한 것부터 봅니다. 대시보드의 반복 오류 묶음 표에서 처음 시각을 확인할 수 있습니다.

6. 보고서에 남길 것

- 발생 시각 / 기기 / 펌웨어·앱 버전
- ANR in 줄 전체 (패키지와 컴포넌트)
- Reason 줄 전체
- CPU usage 상위 3줄
- 직전 20초간 같은 PID의 주요 기록
- traces의 "main" 스레드 스택 (확보했다면)
- 재현 절차 (예: 채널 목록에서 아래 키를 1초에 5회 이상 연타)

정리

참고 자료: Android Developers, "Diagnose and fix ANRs" (developer.android.com/topic/performance/anrs/diagnose-and-fix-anrs). 시간 기준과 상태 해석은 이 문서를 기준으로 했고, 기기별로 다를 수 있습니다.

관련 글
· 실습: 셋톱박스 2대의 로그를 대시보드로 읽어 보기
· logcat 레벨과 태그, 자주 보는 오류 패턴 읽는 법
· 저장된 로그에서 원인 구간 좁히기
· 아티클 목록 · 패턴 사전 · 서비스 소개
문의: dkdnj123@gmail.com