개발자의 생활

안드로이드 생명 주기(Life Cycle) 본문

안드로이드 앱 개발

안드로이드 생명 주기(Life Cycle)

Developer성현 2025. 11. 2. 22:19

1. 생명주기 란

안드로이드 OS는 앱이 시작하고 끝나는 과정에서 단계별로 나뉘어 실행됩니다.

앱을 개발하기 위해 프로젝트를 처음 생성하면 기본적으로 onCreate() 함수가 오버라이드 되어 있습니다.

이 함수는 앱이 실행될 때 가장 처음으로 호출되는 함수로 C, Java, Kotlin 프로그래밍을 할 때 main() 함수와 같은 위치의 함수라고 볼 수 있습니다.

안드로이드는 onCreate() 함수 이외에도 앱이 실행되고 종류 되는 단계별로 호출되는 함수가 존재합니다.

 

2. 액티비티(Activity) 상태

생명주기는 activity 상태가 변경되는 과정이라고 보면 됩니다.

Activity의 상태는 5단계로 구분됩니다.

Activity 가 시작될 때의 과정

초기화 단계

이 부분에서는 Activity 가 생성되기 위한 시스템을 준비하는 과정입니다.

메모리에 Activity인스턴스를 로드하는 등의 작업이 실행되며 이 부분은 개발자가 관여할 수 없는 부분입니다.

 

생성 단계

이 부분에서 개발한 Activity 화면이 메모리에 올라가게 됩니다.

하지만 아직 화면에 그려지지는 않습니다.

 

시작 단계

여기서부터 화면이 사용자에게 보이게 됩니다.

하지만 버튼입력과 같은 상호작용은 아직 못합니다.

 

재개 단계

이 부분이 실제로 앱을 사용하는 단계입니다.

뒤로 가기 버튼이나 finish() 함수를 호출하기 전까지 계속 이 단계를 유지합니다.

Activity 가 종료될 때의 과정

재개 단계

이 부분이 실제로 앱을 사용하는 단계입니다.

뒤로 가기 버튼이나 finish() 함수를 호출하기 전까지 계속 이 단계를 유지합니다.

 

시작 단계

여기서는 아직 화면이 사용자에게 보이지만

버튼입력과 같은 상호작용은 아직 못합니다.

 

생성 단계

이 부분에서 개발한 Activity 화면이 메모리에 내려가고

화면에서 사라지게 됩니다.

 

초기화 단계

이 부분에서 Activity 가 제거되기 위한 시스템을 준비하는 과정입니다.

메모리에 Activity 인스턴스를 삭제하는 등의 작업이 실행되며 이 부분은 개발자가 관여할 수 없는 부분입니다.

3. 생명주기 호출 순서

위 단계들은 앱을 실행하고 종료하는 과정에서 시스템에 의해 자동으로 전환되며 전환될 때 콜백함수가 호출이 됩니다.

콜백 함수들은 위 이미지에 나와있는 순서대로 실행이 됩니다.

이미지를 보시면 onStart()와 함께 onRestart() 콜백함수도 같이 있습니다.

onRestart() 이 함수는 시작 단계에서 생성 단계로 내려왔다가 다시 시작 단계로 올라갈 때 호출되는 함수입니다.


앱이 실행되는 과정에서 실제로 어떻게 생명주기 가 동작하는지 확인해 보기 위해 Log를 찍어 보겠습니다.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        Log.d(TAG, "onCreate")
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            LifeCycleTheme(
                darkTheme = false
            ) {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Box(
                        contentAlignment = Alignment.Center,
                        modifier = Modifier
                            .fillMaxSize()
                    ){
                        Text(
                            text = "LifeCycle",
                            fontSize = 32.sp,
                            modifier = Modifier
                                .padding(innerPadding)
                        )
                    }
                }
            }
        }
    }

    override fun onStart() {
        super.onStart()
        Log.d(TAG, "onStart")

        finish()
    }

    override fun onRestart() {
        super.onRestart()
        Log.d(TAG, "onRestart")
    }

    override fun onResume() {
        super.onResume()
        Log.d(TAG, "onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.d(TAG, "onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.d(TAG, "onStop")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "onDestroy")
    }

}

위 코드에서 Compose 코드는 신경 쓸 필요는 없습니다.

 

1. 앱 실행

 

 

2. 앱 종료(홈버튼 클릭) & 전원버튼 클릭 또는 화면 자동꺼짐

 

 

3. 앱 재실행

 

 

4. 앱 종료(뒤로 가기 버튼 클릭)

 

이처럼 앱이 실행되고 종료될 때 생명주기를 따르게 됩니다.

 

 

하지만 버그 또는 시스템에 의해 다르게 동작하는 경우도 있습니다.

앱이 실행되는 과정에서 사용자가 의도적으로 강제종료 하거나 시스템 또는 코드에 문제가 발생하면 생명주기를 따라 앱이 종료되지 못하는 경우도 있습니다.

 

1. 코드에 문제가 있는 경우

override fun onStart() {
    super.onStart()
    Log.d(TAG, "onStart")

    finish()
}

의도적으로 시스템에 문제를 만들기 어렵기 때문에 onStart 함수 내부에 finish() 종료함수를 호출해 보겠습니다.

실제로 onResume와 onPause 함수가 호출되지 않았습니다.

 

2. 사용자가 강제종료 했을 경우

강제종료 나는 건 앱이 뒤로 가기 버튼 또는 finish()을 사용하여 정상적으로 종료되는 경우를 제외하고 최근목록 탭에서 앱을 스와이프 또는 모두 갇기 기능을 통해 종료하는 경우를 말합니다.

이런 경우에는 일반적으로 onStop 까지는 호출되지만 onDestroy는 호출이 안됩니다.

 

3. 시스템에 의해 강제종료되는 경우

이는 코드에 문제가 생긴 경우 에러가 발생하여 종료되는 경우도 있지만 홈 버튼을 눌러 onStop 만 호출되어 프로세스가 살아있는 경우에도 시스템 자원이 부족할 경우 사용하지 않은 앱으로 간주되어 시스템이 자동으로 메모리에서 프로세스를 회수하게 됩니다.

 

4. 생명주기가 중요한 이유

앱을 사용하지 않는 시간 화면을 꺼놓는 경우, 앱을 종료하지 않고 다른 앱을 사용할 때와 같은 경우 에 만약 계속 리소스(카메라, 센서 등) 자원을 사용하고 있으면 하드웨어 자원이 낭비되고 배터리 또한 소모량이 많아지게 됩니다. 그래서 onPause 또는 onStop 에서 리소스 자원을 해제해 주는등의 작업을 해 주어야 합니다.

 

반대로 앱을 재실행 할때 onRestart, onStart 에서 리소스 를 다시 로드하는 작업을 수행할 수 있습니다.