
안드로이드 개발을 하다 보면 가장 자주 부딪히는 주제가 바로 Activity와 Fragment의 생명주기(Lifecycle)였다.
처음에는 “onCreate → onResume → onPause → onDestroy” 정도만 대충 외우고 넘어갔지만, 실제 프로젝트에서 메모리 누수, 잘못된 UI 참조, 화면 전환 시 뷰가 초기화되지 않는 문제 같은 걸 겪으면서 다시 깊게 공부하게 됐다.
이번 글에서는 Activity와 Fragment의 생명주기를 정리하면서, 공부 과정에서 정리했던 Q&A들을 함께 풀어보겠다.

Activity는 크게 아래 단계로 움직인다.
👉 정리하면
예시: Activity A → Activity B → 다시 A 복귀
[A 시작]
A: onCreate → onStart → onResume
[B 실행]
A: onPause → onStop (B가 전체화면일 경우)
B: onCreate → onStart → onResume
[B 종료 → A 복귀]
B: onPause → onStop → onDestroy
A: onRestart → onStart → onResume
👉 핵심은 A가 다시 돌아올 때 onRestart()가 호출된다는 점이다. A는 이미 메모리에 살아 있기 때문에 다시 onCreate부터 시작하지 않는다.

Fragment는 Activity와 유사하지만, 뷰(View) 관련 단계가 추가되었다.
👉 만약 뷰 해제를 onDestroy에서 한다면, Fragment는 살아있는데 뷰는 이미 사라진 상황이 발생해 메모리 누수가 생긴다. 따라서 뷰 관련 리소스는 onDestroyView에서 해제해야 했다.
class SampleFragment : Fragment() {
private var _binding: FragmentSampleBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentSampleBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null // 메모리 누수 방지
}
}
Activity는 onCreate에서 setContentView()로 UI를 붙이는 게 정상이다.
하지만 Fragment의 onCreate는 아직 container 정보가 없기 때문에, inflate를 하면 문제가 생긴다.
또한 Fragment는 View가 여러 번 생성/파괴될 수 있는데, onCreate는 한 번만 호출된다. 따라서 UI 재생성 과정이 꼬이게 된다.
👉 결론: Fragment UI는 반드시 onCreateView에서 inflate해야 한다.
즉, Activity → ParentFragment → ChildFragment 구조라면,
Fragment는 인스턴스와 View 생명주기가 다르다. 따라서 LiveData나 Flow를 observe할 때는 this 대신 viewLifecycleOwner를 사용해야 한다.
viewModel.data.observe(viewLifecycleOwner) { value ->
binding.textView.text = value
}
👉 viewLifecycleOwner는 뷰가 생성될 때 활성화되고, 뷰가 파괴될 때 종료된다.
👉 따라서 UI 관련 작업을 안전하게 처리할 수 있고, 메모리 누수도 막을 수 있었다.
정리해보면
나 역시 처음에는 생명주기를 “암기”로만 접근했지만, “언제 보이고, 언제 포커스를 잃고, 언제 뷰가 없어지는가”라는 관점으로 접근했을 때 비로소 정리가 됐다.
생명주기는 안드로이드 앱의 안정성과 직결되기 때문에, 이 부분을 정확히 이해하면 앱 품질 관리가 훨씬 수월해진다.