Activity 생명주기(Activity Lifecycle)
Activity 생명주기(Activity Lifecycle)
안드로이드 Activity 생명주기는 Activity가 생성부터 소멸까지 거치는 일련의 상태 전환을 정의합니다. 시스템은 각 전환 시점에 특정 콜백(callback) 메서드를 호출하며, 이를 통해 앱은 리소스를 초기화하거나, 상태를 저장하고, 리소스를 해제하며, 화면 표시 상태 변화에 대응할 수 있습니다. 이러한 콜백을 올바르게 관리하지 않으면 메모리 누수, 사용자 상태 유실, 구성 변경(configuration changes) 시 크래시 등 다양한 문제가 발생합니다. 면접에서도 Activity 생명주기는 가장 빈출되는 주제 중 하나이므로, 각 콜백의 역할과 호출 시점을 정확히 이해하는 것이 중요합니다. 이 글을 통해 다음 내용을 학습할 수 있습니다.
onCreate()부터onDestroy()까지 전체 콜백 호출 순서를 추적할 수 있습니다.- 각 콜백이
Activity의 가시성(visibility)과 상호작용(interactivity) 측면에서 어떤 의미를 갖는지 설명할 수 있습니다. - 멀티 윈도우(multi-window) 및 PIP(Picture-in-Picture) 모드에서의 생명주기 전환을 올바르게 처리할 수 있습니다.
- 구성 변경이 어떻게
Activity의 소멸과 재생성을 유발하는지 설명할 수 있습니다. - 리소스 획득과 해제에 적합한 콜백을 식별할 수 있습니다.
onSaveInstanceState()를 활용하여 재생성 시 임시 UI 상태를 보존하는 방법을 적용할 수 있습니다.
생성 및 초기화
시스템이 Activity를 생성하면 인스턴스당 정확히 한 번 onCreate()를 호출합니다. 이 콜백에서 레이아웃을 인플레이트(inflate)하고, 뷰를 바인딩하거나 Compose 콘텐츠를 설정하며, ViewModel을 초기화하고, 이전 인스턴스에서 전달된 savedInstanceState Bundle을 통해 상태를 복원합니다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 이전 인스턴스에서 저장된 검색어 복원
val restoredQuery = savedInstanceState?.getString("search_query")
viewModel.initialize(restoredQuery)
}
onCreate() 이후 시스템은 onStart()를 호출합니다. 이 시점에서 Activity는 화면에 보이지만 아직 포그라운드 상태는 아닙니다. 윈도우가 그려지긴 했으나, 다른 Activity가 화면 일부를 여전히 가리고 있을 수 있습니다. onStart()는 Activity가 보일 때마다 실행해야 하는 UI 관련 옵저버 등록이나 애니메이션 시작에 적합한 위치입니다.
onResume()은 onStart() 이후에 호출되며, Activity가 완전히 상호작용 가능한 상태임을 나타냅니다. Activity가 포그라운드에 위치하여 사용자 입력을 받고 있는 상태입니다. 카메라 프리뷰 재개, 센서 리스너 시작, 사용자가 적극적으로 상호작용 중일 때만 실행해야 하는 재생 시작 등을 처리하기에 적합합니다.
여기서 주의할 점은 onStart()와 onResume() 모두 뷰가 실제로 화면에 그려지기 전에 실행된다는 것입니다. 첫 프레임이 렌더링된 후에 수행해야 하는 작업(뷰 크기 측정, 실제 위치 기반 애니메이션 시작 등)이 있다면, 생명주기 콜백에만 의존하지 말고 View.post()나 View.doOnLayout()을 사용해야 합니다. 이 부분은 면접에서도 간과하기 쉬운 포인트이므로 정확히 알아 두면 좋습니다.
override fun onResume() {
super.onResume()
// 레이아웃이 완료된 후 진입 애니메이션 시작
binding.root.doOnLayout {
startEnterAnimation()
}
}
일시 정지, 중지, 재시작
다이얼로그, 반투명 Activity, 또는 멀티 윈도우 분할 화면이 Activity를 부분적으로 가리면 시스템은 onPause()를 호출합니다. Activity는 여전히 보이지만 더 이상 포그라운드에 있지 않은 상태입니다. 동영상 재생이나 집중적인 애니메이션처럼 사용자가 직접 상호작용하지 않을 때 중단해야 하는 작업을 일시 정지하는 것이 좋습니다.
override fun onPause() {
super.onPause()
// 사용자가 직접 상호작용하지 않으므로 동영상 일시 정지
videoPlayer.pause()
}
Activity가 완전히 보이지 않게 되면(사용자가 다른 Activity로 이동하거나 홈 버튼을 누르면) 시스템은 onStop()을 호출합니다. 이 시점에서 Activity는 전혀 보이지 않습니다. UI 업데이트용 브로드캐스트 리시버(broadcast receiver)나 표시를 위해 유지하던 큰 비트맵처럼 보이지 않는 동안 불필요한 리소스를 해제해야 합니다.
사용자가 중지된 Activity로 돌아오면(백 스택이나 최근 앱 목록을 통해) 시스템은 onRestart()를 호출한 뒤 onStart()와 onResume()을 순서대로 호출합니다. onRestart()는 Activity가 중지 상태에서 다시 돌아올 때만 호출되며, 최초 생성 후에는 호출되지 않습니다. 이 구분 덕분에 백그라운드에서 복귀할 때만 필요한 재연결 로직을 별도로 처리할 수 있습니다.