[Android] ANR

πŸ’‘μ•ˆλ“œλ‘œμ΄λ“œ 개발 ν™˜κ²½μ—μ„œ 자주 λ§ˆμ£Όν•  수 μžˆλŠ” ANR에 λŒ€ν•˜μ—¬ μ •λ¦¬ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

 

κ°œμš”

  • μ•ˆλ“œλ‘œμ΄λ“œ κ°œλ°œμ„ μ§„ν–‰ν•˜λ©΄μ„œ ANR μ—λŸ¬λ₯Ό λ§ˆμ£Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • μ΄λŠ” μ‚¬μš©μžκ°€ 앱을 μ œκ±°ν•˜λŠ” λ™μž‘μœΌλ‘œ μ΄μ–΄μ§ˆ 수 μžˆλŠ” 치λͺ…적인 μ—λŸ¬μ΄λ©°, κ°œλ°œμžλŠ” 이λ₯Ό λ°˜λ“œμ‹œ ν•΄κ²°ν•΄μ•Ό ν•©λ‹ˆλ‹€.
  • ANRκ³Ό κ΄€λ ¨ν•΄μ„œ 자주 μ‚¬μš©λ˜λŠ” μš©μ–΄λ₯Ό μ •λ¦¬ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

ꡐ착 μƒνƒœ

  • ν•œ μŠ€λ ˆλ“œμ—μ„œ ν•„μš”ν•œ λ¦¬μ†ŒμŠ€λ₯Ό λ‹€λ₯Έ μŠ€λ ˆλ“œκ°€ λ³΄μœ ν•˜μ—¬, λ‹€λ₯Έ μŠ€λ ˆλ“œκ°€ ν•΄λ‹Ή λ¦¬μ†ŒμŠ€λ₯Ό λŒ€κΈ°ν•˜λŠ” μƒνƒœλ₯Ό λœ»ν•©λ‹ˆλ‹€.
  • μŠ€λ ˆλ“œκ°€ 연속 λŒ€κΈ° μƒνƒœκ°€ λ˜λ©΄μ„œ ꡐ착 μƒνƒœκ°€ λ°œμƒν•©λ‹ˆλ‹€.

Background Service

  • μ‚¬μš©μžμ—κ²Œ 보이지 μ•Šκ³  λ¬΅μ‹œμ μœΌλ‘œ μ‹€ν–‰λ˜λ©° μ‚¬μš©μžκ°€ μž‘λ™ μ—¬λΆ€λ₯Ό μ•Œμ§€ λͺ»ν•©λ‹ˆλ‹€.
  • 데이터 동기화, λ„€νŠΈμ›Œν¬ μš”μ²­, DB μ—…λ°μ΄νŠΈ λ“±μ˜ μž‘μ—…μ„ μ§„ν–‰ν•©λ‹ˆλ‹€.

Foreground Service

  • μ‚¬μš©μžμ—κ²Œ λˆˆμ— λ„λŠ” μž‘μ—…μ„ μˆ˜ν–‰ν•˜λ©°, μ•Œλ¦Όμ²˜λŸΌ μ•±κ³Ό μƒν˜Έμž‘μš© ν•˜μ§€ μ•ŠλŠ” κ²½μš°μ—λ„ μ‹€ν–‰λ©λ‹ˆλ‹€.

ANR

  • Application Not responding의 μ•½μžλ‘œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ‘λ‹΅ν•˜μ§€ μ•ŠμŒμ„ λœ»ν•©λ‹ˆλ‹€.
  • μ•ˆλ“œλ‘œμ΄λ“œ 개발 λ¬Έμ„œμ—λŠ” μ•„λž˜μ™€ 같이 μ •μ˜λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

Android μ•±μ˜ UI Thread(메인 μŠ€λ ˆλ“œ)κ°€ λ„ˆλ¬΄ μ˜€λž«λ™μ•ˆ 차단될 μ‹œ ANR 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€. μ•„λž˜ κ·Έλ¦Όκ³Ό 같이 μ‚¬μš©μžμ—κ²Œ λŒ€ν™” μƒμžλ₯Ό ν‘œμ‹œν•˜λ©°, μ‚¬μš©μžκ°€ 앱을 κ°•μ œμ’…λ£Œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • ANR은 UI μ—…λ°μ΄νŠΈλ₯Ό λ‹΄λ‹Ήν•˜λŠ” μ•±μ˜ κΈ°λ³Έ μ“°λ ˆλ“œκ°€ μ‚¬μš©μž μž…λ ₯ 이벀트 λ˜λŠ” 그림을 μ²˜λ¦¬ν•˜μ§€ λͺ»ν•΄ μ‚¬μš©μž λΆˆλ§Œμ„ μ΄ˆλž˜ν•˜λ―€λ‘œ 큰 λ¬Έμ œκ°€ λ©λ‹ˆλ‹€.

ANR λ°œμƒ 원인

μž…λ ₯ 전달 νƒ€μž„μ•„μ›ƒ

  • 앱이 ν‚€ λˆ„λ¦„ λ˜λŠ” ν™”λ©΄ ν„°μΉ˜ λ“±μ˜ μž…λ ₯ μ΄λ²€νŠΈμ— 5초 이내에 μ‘λ‹΅ν•˜μ§€ λͺ»ν•˜λŠ” 경우 λ°œμƒν•©λ‹ˆλ‹€.
  • λ„€νŠΈμ›Œν¬ μš”μ²­, 파일 읽기,μ“°κΈ° λ°μ΄ν„°λ² μ΄μŠ€ μ ‘κ·Ό λ“± I/O μž‘μ—…μ„ 메인 μŠ€λ ˆλ“œμ—μ„œ μ²˜λ¦¬ν•  λ•Œ λ°œμƒν•˜λ©° AsyncTask, Thread, Handler, Coroutine 등을 ν™œμš©ν•˜μ—¬ ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ„œλΉ„μŠ€ μ‹€ν–‰

  • μ•±μ—μ„œ μ„ μ–Έν•œ μ„œλΉ„μŠ€κ°€ λͺ‡ 초 이내에 μ•„λž˜μ˜ λ™μž‘μ„ μ‹€ν–‰ν•  수 μ—†λŠ” 경우 λ°œμƒν•©λ‹ˆλ‹€.
    • Service.onCreat()
    • Service.onStartCommand()
    • Service.onBind()

μΈν…νŠΈ λΈŒλ‘œλ“œμΊμŠ€νŠΈ

  • BroadcastReceiverκ°€ μ„€μ • 된 μ‹œκ°„ 내에 싀행을 μ™„λ£Œν•˜μ§€ λͺ»ν•œ 경우 λ°œμƒν•©λ‹ˆλ‹€.
    • λΈŒλ‘œλ“œμΊμŠ€νŠΈ μˆ˜μ‹ κΈ°λŠ” 10초 이상 μ‹€ν–‰λ˜λ©΄ ANR이 λ°œμƒν•©λ‹ˆλ‹€.
  • 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ JobIntentServiceλ‚˜ WorkManagerλ₯Ό μ‚¬μš©ν•΄ λΉ„λ™κΈ°μ μœΌλ‘œ μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ContentProvider의 κΈ΄ μ‹œκ°„ μ‹€ν–‰

  • ContentProviderλŠ” 데이터λ₯Ό μ²˜λ¦¬ν•˜λŠ” 데 λ„ˆλ¬΄ λ§Žμ€ μ‹œκ°„μ„ μ†Œμš”ν•˜λ©΄ ANR이 λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œ ContentProvider κ΄€λ ¨ μž‘μ—…μ„ μ΅œμ†Œν™”ν•˜κ³  λ°±κ·ΈλΌμš΄λ“œμ—μ„œ 데이터λ₯Ό μ²˜λ¦¬ν•˜λ„λ‘ ν•΄μ•Ό ν•©λ‹ˆλ‹€.

JobScheduler μƒν˜Έμž‘μš©

  • JobServiceκ°€ λͺ‡ 초 이내에 λ°˜ν™˜λ˜μ§€ μ•ŠμœΌλ©΄ λ°œμƒν•©λ‹ˆλ‹€.

반볡 μž‘μ—…

  • λ¬΄ν•œ λ£¨ν”„λ‚˜ κΈ΄ μ‹œκ°„ λ™μ•ˆ μ‹€ν–‰λ˜λŠ” μž‘μ—…μ—μ„œλ„ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œ μž‘μ—…μ„ λ°±κ·ΈλΌμš΄λ“œ μŠ€λ ˆλ“œμ—μ„œ μ²˜λ¦¬ν•˜κ±°λ‚˜, 일정 μ‹œκ°„ κ°„κ²©μœΌλ‘œ μŠ€λ ˆλ“œλ₯Ό νœ΄μ‹μ‹œμΌœμ•Ό ν•©λ‹ˆλ‹€.

ANR ν•΄κ²° λ°©μ•ˆ

메인 μŠ€λ ˆλ“œμ—μ„œ I/O μž‘μ—… 쀑지

  • λ„€νŠΈμ›Œν¬ μš”μ²­, 파일 처리, λ°μ΄ν„°λ² μ΄μŠ€ μ ‘κ·Ό 등을 λ°±κ·ΈλΌμš΄λ“œ μŠ€λ ˆλ“œμ—μ„œ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

비동기 처리 지원

  • Coroutine, AsyncTask, ExecutorService 등을 μ‚¬μš©ν•΄ λ°±κ·ΈλΌμš΄λ“œλ‚˜ 비동기 μž‘μ—…μ„ μ§€μ›ν•©λ‹ˆλ‹€.

메인 μŠ€λ ˆλ“œ λΆ€ν•˜ κ°μ†Œ

  • λ³΅μž‘ν•œ UI μž‘μ—…μ€ λ‚˜λˆ„μ–΄ μ²˜λ¦¬ν•˜κ³ , λ„ˆλ¬΄ 큰 이미지 λ‘œλ“œ μž‘μ—…μ„ μ΅œμ ν™”ν•©λ‹ˆλ‹€.

정리

ANR은 μ•±μ˜ μ„±λŠ₯κ³Ό μ‚¬μš©μž κ²½ν—˜μ— 큰 영ν–₯을 λ―ΈμΉ˜λ―€λ‘œ, λ°±κ·ΈλΌμš΄λ“œ μž‘μ—…μ„ 적절히 μ²˜λ¦¬ν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€. 메인 μ“°λ ˆλ“œμ—μ„œμ˜ μž‘μ—…μ„ μ£Όμ˜ν•˜λ©°, λ³„λ„μ˜ μŠ€λ ˆλ“œλ‚˜ 비동기 데이터 μŠ€νŠΈλ¦Όμ„ ν™œμš©ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.