[Android] "내 binding 이 죽었어요" - 프래그먼트 생명주기와 ViewBinding 의 진실

이도연·2025년 10월 14일
0

android studio

목록 보기
33/33

private var _binding: FragmentXBinding? = null + private val binding get() = _binding!!
이 조합은 개발자의 생명을 구합니다.
반면 lateinit var binding 은 조용히 당신의 메모리를 잡아먹습니다.

Scene 1: 늦은 밤, 죽지 않는 뷰

밤 11시.
개발자는 평화롭게 앱을 종료했다.
하지만 Logcat에는 여전히 붉은 메시지가 깜빡인다.

“Memory leak detected: Fragment binding is still referenced after onDestroyView()”

그렇다.
우리의 lateinit var binding은 이미 죽은 뷰의 시체를 품고 있었다.


Scene 2: 진짜 원흉은 누구인가

사건의 전말은 단순했다.

private lateinit var binding: FragmentArtistBinding

override fun onCreateView(...) : View {
    binding = FragmentArtistBinding.inflate(inflater, container, false)
    return binding.root
}

보기엔 깔끔하다.
lateinit — Kotlin의 마법 같은 단어.
“나 나중에 초기화할게, 지금은 그냥 믿어줘.”

문제는 Fragment의 생명주기다.
onDestroyView() 가 호출되어도 binding은 여전히 메모리에 남아,
사라진 뷰를 기억하는 망령이 된다.

이게 바로 “뷰 참조 누수(View leak)”이다.


Scene 3: 구세주의 등장

구글 공식 문서는 이런 유령 사태를 방지하기 위해 백업 변수(backing property) 패턴을 소개한다.

private var _binding: FragmentArtistBinding? = null
private val binding get() = _binding!!

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    _binding = FragmentArtistBinding.inflate(inflater, container, false)
    return binding.root
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

이 한 줄이 바로 “구글이 승인한 엑소시즘”이다.
onDestroyView() 에서 _binding = null
즉, 망령을 보내버리는 구절.

이제 binding은 살아 있을 때만 non-null,
죽으면 확실히 null이 된다.
이게 바로 “메모리 누수 제로 라이프스타일”.


Scene 4: DataBinding vs ViewBinding — 이름이 비슷하다고 친구는 아니다

이쯤 되면 헷갈린다.

“아니, DataBindingUtil.inflate()랑 그냥 Binding.inflate()는 뭐가 달라요?”

이건 가톨릭과 개신교 정도의 차이다.
둘 다 신(=View)을 믿지만, 예배 방식이 다르다.

항목DataBindingUtil.inflate()Binding.inflate()
대상XML에 <layout> 태그와 @{} 표현식이 있을 때단순 뷰 참조 바인딩
사용 목적뷰모델 연결, 표현식 바인딩 가능단순 findViewById 대체
난이도약간 복잡매우 단순
코드 스타일binding.viewModel = viewModelbinding.textView.text = "Hello"

즉,
데이터바인딩은 계약,
뷰바인딩은 조작에 가깝다.


Scene 5: Stack Overflow의 계시

Stack Overflow에는 이런 명언이 있다.

“lateinit binding in Fragment is like keeping your ex’s photo in your wallet —
it will haunt you when you least expect it.”

따라서 프래그먼트에서는 lateinit을 버리고,
nullable backing property 패턴을 택해야 한다.

Scene 6: 결론

Fragment + ViewBinding ⇒ _binding? + binding get() = _binding!!

Activity + ViewBinding ⇒ lateinit binding 도 OK (Activity는 뷰 생명주기가 단순함)

DataBinding ⇒ 필요할 때만 사용 (무조건 쓰면 XML이 점점 주술서가 됨)


Epilogue: 작은 깨달음

프래그먼트에서 메모리 누수를 막는 건
단순히 _binding = null 한 줄이 아니다.

그건 개발자와 뷰 사이의 관계를 정리하는 선언문이다.
뷰가 떠났으면, 깔끔히 보내줘야 한다.

0개의 댓글