Hanbit the Developer

Android Document | Processes and app lifecycle 본문

Mobile/Android

Android Document | Processes and app lifecycle

hanbikan 2024. 1. 25. 03:33

안드로이드 애플리케이션은 리눅스 프로세스에서 실행되며, 애플리케이션 코드 일부가 실행되어야 할 때 프로세스가 생성된다. 다른 애플리케이션이 메모리를 필요로 하면서 기존 애플리케이션이 더이상 쓰이지 않으면 종료될 수 있다.

안드로이드의 특이하면서 기본적인 특징은 애플리케이션 프로세스의 라이프타임이 해당 애플리케이션에 의해 결정되지 않고, 시스템에 의해 제어된다는 점이다. 시스템은, 실행 중인 애플리케이션 요소, 사용자에게 얼마나 중요한지, 시스템에서 사용 가능한 전체 메모리의 양을 고려한다.

개발자는 Activity, Service, BroadcastReceiver 같은 컴포넌트들이 애플리케이션 프로세스의 수명에 영향을 어떻게 미치는지를 알아야 한다. 컴포넌트를 올바르게 사용하지 않으면 시스템이 앱을 강제로 종료시킬 수도 있다.(예를 들어, BroadcastReceiver.onReceive()에서 긴 작업을 하면 메모리가 회수될 수 있다. 짧지 않은 작업을 해야하는 경우에는 JobService를 스케줄하여 이 문제를 해결할 수 있다.)

메모리가 부족하여 프로세스를 강제로 종료시켜야 할 때, 안드로이드 시스템은 다음과 같은 importance를 고려한다:

Foreground process

사용자가 현재 사용 중인 프로세스로 다음과 같은 경우에 해당한다.

  • 화면 최상단에 액티비티를 띄우고 사용자와 상호작용 하는 경우(onResume()이 호출됨)
  • 현재 작동 중인 BroadcastReceiver를 가진 경우(onReceive()가 실행 중임)
  • onCreate(), onStart(), onDestroy() 메소드 중 하나를 실행 중인 Service를 가진 경우

시스템에 몇 개밖에 없으며, 강제 종료되는 경우는 메모리가 너무 부족하여 이것들조차 계속 실행할 수 없을 때이다. 보통 기기가 memory paging state일 때 이렇게 되기 때문에 사용자가 기기를 조작하기 위해 이러한 액션이 필요하다.

*memory paging state = 시스템이 메모리 부족으로 인해 활발하게 페이징 작업을 실행하고 있는 상태

Visible process

사용자에게 보이는 작업을 하는 프로세스로 다음과 같은 경우에 해당한다:

  • 화면에 표시되지만 포어그라운드는 아닌 액티비티를 가진 경우(onPause()가 호출됨). 예를 들어 MainActivity 위에 DialogActivity가 표시되고 있으면 MainActivity가 이에 해당한다.
  • startForeground()로 인해 foreground service로 작동하고 있는 Service를 가진 경우
  • 시스템에서 live wallpaper, input method service 같이 사용자에게 인식되는 기능에 사용되는 서비스를 호스팅하는 경우

포어그라운드 프로세스보단 프로세스 수가 많지만 여전히 관리되고 있다. 매우 중요한 프로세스로 취급되며 모든 포어그라운드 프로세스를 유지해야 할 때 강제 종료된다.

Service process

startService()로 인해 시작된 서비스를 가지고 있는 프로세스이다. 사용자에게 보여지지는 않으나 사용자가 관심을 두고 있는 작업(다운로드 등)이다. 상위 프로세스(foreground, visible)를 위해 희생될 수 있다.

장기간(예: 30분 이상) 실행되면 중요도가 낮아져 cached list로 떨어질 수 있다.

장기간 실행되는 프로세스는 setForeground()로 생성할 수 있다. 실행 시간이 엄격해야 하는 경우에는 AlarmManager를 사용할 수 있다.(https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running)

Cached process

당장 필요하지 않아 시스템이 자원이 필요할 때 마음대로 종료해도 되는 프로세스이다. 제대로 작동하는 시스템은 여러 개의 cached process를 두어 효율적인 스위칭을 가능하게 한다. 언제나 종료될 수 있기 때문에, 사용자에게 치명적인 작업이 필요하면 위에서 언급한 API를 사용하여 상위 프로세스로 승급시켜야 한다.

Cached process는 대체로 1개 이상의 보이지 않는 액티비티(onStop()이 호출됨)를 가지고 있다. 생명주기를 적절히 관리하여 사용자가 앱으로 돌아왔을 때 이전 상태로 복원될 수 있게 해야 한다. 추가로 onDestroy()는 시스템에 의해 프로세스가 종료될 때 반드시 호출된다는 보장이 없다.

Android 13부터 앱 프로세스는, active lifecycle state가 되기 전까지 실행 시간이 제한되거나 실행되지 않을 수 있다.

cached process는 리스트로 관리되고, 정렬 정책은 플랫폼의 구현 사항이다. 일반적으로 가장 마지막에 본 액티비티처럼 중요한 프로세스를 앞에 유지하려고 한다. 프로세스 개수 제한, 프로세스 유지 시간 제한 등의 정책도 적용될 수 있다.

프로세스 우선순위는 컴포넌트 중 가장 높은 중요도를 기반으로 결정된다. 또한 프로세스의 종속성에 따라 우선순위가 증가할 수도 있다.

Q&A with GPT4

같은 앱의 AppleActivity, BananaActivity가 동시에 실행되고 있을 때, 각각 다른 프로세스에서 실행되는가?

ChatGPT:

일반적으로, Android 앱에서 **Activity**들은 기본적으로 같은 프로세스에서 실행됩니다. 즉, 동일한 앱의 **AppleActivity**와 **BananaActivity**는 기본적으로 같은 프로세스 내에서 수행됩니다. Android는 각 앱을 독립된 프로세스로 실행하여 앱 간의 격리를 제공하며, 이는 보안과 안정성을 향상시킵니다.

그러나, Android 앱 개발자는 AndroidManifest.xml 파일에서 android:process 속성을 사용하여 특정 Activity 또는 다른 앱 구성 요소를 별도의 프로세스에서 실행하도록 명시적으로 설정할 수 있습니다. 이렇게 하면, 해당 **Activity**는 다른 프로세스에서 실행되며, 자원 사용 및 생명주기 관리 측면에서 독립성을 가지게 됩니다.

예를 들어, **AppleActivity**가 기본 프로세스에서 실행되고, **BananaActivity**가 별도의 프로세스에서 실행되도록 설정할 수 있습니다. 그러나 이는 특별한 경우에만 사용되며, 대부분의 일반적인 앱 개발 상황에서는 모든 **Activity**가 같은 프로세스에서 실행됩니다. 별도 프로세스를 사용하는 것은 추가적인 메모리 사용과 복잡성을 초래할 수 있으므로, 필요한 경우에만 사용하는 것이 좋습니다.

문서 링크

https://developer.android.com/guide/components/activities/process-lifecycle

'Mobile > Android' 카테고리의 다른 글

Android Dependent Use Case 이슈 해결  (1) 2024.02.05
UI State Flow 이슈 해결  (0) 2024.01.25
Android Document | App startup time  (1) 2024.01.25
Room Migration 방법  (0) 2024.01.17
ViewModelStore, ViewModelProvider 분석  (1) 2024.01.12