1. 생명주기(Lifecycle)란?
안드로이드에서 Activity는 사용자 인터페이스(UI)를 구성하는 핵심 요소다. 사용자가 앱을 실행하고 다른 앱으로 전환하고 다시 앱으로 돌아오는 등 다양한 상호작용 과정에서 Activity는 여러 상태를 거치게 되는데 이러한 상태 변화를 생명주기(Lifecycle)라고 한다.
각 상태에 따라 Activity는 특정한 콜백(Callback) 메서드를 호출하고 개발자는 이 메서드들을 재정의(override)하여 특정 시점에 필요한 작업을 수행할 수 있다. 예를 들면 Activity가 처음 생성될 때 UI를 초기화하거나, 화면에서 사라질 때 데이터를 저장하는 등의 작업을 할 수 있다.
2. 생명주기 콜백 메서드
Activity 생명주기는 다음과 같은 주요 콜백 메서드들로 구성된다.
메서드 | 설명 | 호출 시점 |
onCreate() | Activity가 처음 생성될 때 호출됨. UI 초기화, 리소스 할당 등 필수적인 초기화 작업을 수행. | Activity가 처음 시작될 때 (시스템에 의해) |
onStart() | Activity가 사용자에게 보여지기 직전에 호출됨. | onCreate() 호출 후, 또는 Activity가 다시 시작될 때 (onRestart() 호출 후) |
onResume() | Activity가 사용자와 상호작용하기 직전에 호출됨. (Foreground 상태) | onStart() 호출 후, 또는 일시 중지(paused) 상태에서 다시 활성화될 때 (onPause() 호출 후) |
onPause() | 다른 Activity가 화면에 나타나 Activity가 부분적으로 가려지거나 시스템이 Activity를 일시 중지(paused) 상태로 만들 때 호출됨. 데이터 저장, 네트워크 요청 중지 등 일시 중지 관련 작업을 수행. | 다른 Activity가 화면에 나타나거나, 시스템이 Activity를 일시 중지할 때 |
onStop() | Activity가 더 이상 사용자에게 보이지 않을 때 호출됨. 리소스 해제나 불필요한 작업 중지 등 백그라운드 관련 작업을 수행. | onPause() 호출 후, Activity가 완전히 가려지거나 종료될 때 |
onRestart() | onStop() 상태에서 Activity가 다시 시작될 때 호출됨. | onStop() 호출 후, 사용자가 다시 Activity로 돌아올 때 |
onDestroy() | Activity가 소멸되기 직전에 호출됨. 모든 리소스 해제, 종료 관련 작업을 수행. | Activity가 완전히 종료될 때 (사용자가 앱을 종료하거나, 시스템이 메모리 확보를 위해 종료시킬 때) |
참고:
- onSaveInstanceState(Bundle): Activity가 예기치 않게 종료될 때 (예: 화면 회전) 상태를 저장하기 위해 호출됨.
- onRestoreInstanceState(Bundle): 저장된 상태를 복원하기 위해 onStart() 이후에 호출됨. (필요한 경우에만)
3. 생명주기 흐름
[최초 실행]
onCreate() -> onStart() -> onResume()
[다른 Activity로 이동]
onPause() -> onStop()
[다시 앱으로 돌아옴]
onRestart() -> onStart() -> onResume()
[홈 버튼 누름]
onPause() -> onStop()
[앱 종료 (Back 버튼)]
onPause() -> onStop() -> onDestroy()
[화면 회전 (Configuration Change)]
onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()
4. 코틀린 코드 예제
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivityLifecycle"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(TAG, "onCreate() 호출됨")
// UI 초기화, 리소스 할당 등
}
override fun onStart() {
super.onStart()
Log.d(TAG, "onStart() 호출됨")
}
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 onRestart() {
super.onRestart()
Log.d(TAG, "onRestart() 호출됨")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy() 호출됨")
// 모든 리소스 해제
}
}
5. 생명주기 관련 추가 고려 사항
- onPause()는 빠르게 처리: onPause() 메서드는 다음 Activity가 화면에 표시되기 전에 완료되어야 한다. 너무 많은 시간이 소요되면 사용자 경험에 부정적인 영향을 주게 된다.
- 데이터 저장: onPause() 또는 onStop()에서 중요한 데이터를 저장하는 것이 좋다.
- 리소스 관리: onStop() 또는 onDestroy()에서 불필요한 리소스를 해제하여 메모리 누수를 방지해야한다.
- Configuration Changes (구성 변경): 화면 회전과 같은 구성 변경 시 Activity는 기본적으로 onDestroy() -> onCreate()를 거쳐 다시 생성된다. onSaveInstanceState()와 onRestoreInstanceState()를 사용하여 상태를 보존하거나 android:configChanges 속성을 사용하여 구성 변경을 직접 처리할 수 있다.
- ViewModel: AAC ViewModel은 생명주기를 인지하는 컴포넌트로 UI 관련 데이터를 더 안전하게(configuration changes 에서도 안전하게) 관리할 수 있도록 도와준다.
- onDestroy()의 호출 보장 문제: onDestroy()는 시스템의 메모리 관리 등 이유로 호출되지 않을 수 있다. 강제 종료나 메모리 회수가 발생할 경우 onDestroy()가 호출되지 않을 수 있으니 중요한 정리 작업은 onStop() 등에서 처리해야 한다.
- Lifecycle-aware 컴포넌트: 지금은 ViewModel, LiveData, 그리고 LifecycleObserver 등과 같은 Lifecycle-aware 컴포넌트를 활용하여 생명주기를 관리하는 것이 권장된다. 이후에 알아보도록 하자.
- 멀티 윈도우/다중 재개(Multi-resumed) 상황 : 안드로이드 10 이상부터 도입된 다중 재개 모드나 멀티 윈도우 환경에 따른 생명주기 변화(예: onResume 호출 방식 차이)가 존재한다. 이것도 이후에 알아보도록 하자.
더욱 자세한 정보는 아래의 공식 사이트를 참조하면 된다..
https://developer.android.com/guide/components/activities/activity-lifecycle?hl=ko
활동 수명 주기 | Android Developers
활동은 사용자가 전화 걸기, 사진 찍기, 이메일 보내기 또는 지도 보기와 같은 작업을 하기 위해 상호작용할 수 있는 화면을 제공하는 애플리케이션 구성요소입니다. 각 활동에는 사용자 인터페
developer.android.com
'어플리케이션, 앱 (Application) > 안드로이드 (Android)' 카테고리의 다른 글
안드로이드 jetpack compose 공부 정리 3강 (코틀린, 함수와 클래스) (0) | 2025.05.29 |
---|---|
애드몹 GDPR 메시지 적용 준비 (0) | 2025.03.27 |
안드로이드 앱 애드몹 광고를 이용한 수익화 방향 (애드몹 리워드 광고 단가) (0) | 2025.03.18 |
findViewById()를 버리고 ViewBinding을 쓰자 (0) | 2025.03.17 |
안드로이드 jetpack compose 공부 정리 2강 (기본 문법 정리) (0) | 2025.03.12 |