Jetpack Compose에서의 DisposableEffect와 LaunchedEffect 활용

오리·2025년 6월 27일

1. Compose와 액티비티 생명주기의 차이

전통적인 안드로이드의 생명주기

  • 액티비티나 프래그먼트 등 주요 컴포넌트가 앱 실행 중에 거치는 다양한 상태 변화와, 그에 따라 호출되는 일련의 콜백 메서드 집합을 의미
  • 콜백 메서드들은 앱이 상태 변화에 따라 적절히 반응하고, 리소스를 효율적으로 관리할 수 있도록 도와줌
  • 상태 변화를 지속적으로 모니터링 가능
  • 상태 변화 흐름
    콜백 메서드호출 시점 및 역할
    onCreate()액티비티가 처음 생성될 때 호출. UI 초기화, 데이터 바인딩, 리소스 할당 등 1회성 초기화 작업 수행
    onStart()액티비티가 사용자에게 보이기 직전에 호출. 아직 포커스는 없지만 화면에 표시됨. UI 갱신, 센서 등록 등
    onResume()액티비티가 포커스를 얻고, 사용자와 상호작용 가능한 상태가 될 때 호출. 애니메이션 시작, 카메라 미리보기 등
    onPause()다른 액티비티가 전면에 나타나거나, 일시적으로 포커스를 잃을 때 호출. 리소스 해제, 진행 중인 작업 일시 중지 등
    onStop()액티비티가 더 이상 사용자에게 보이지 않을 때 호출. 무거운 리소스 해제, 상태 저장 등
    onRestart()onStop() 이후 다시 시작될 때 호출. onStart() 직전 실행됨
    onDestroy()액티비티가 완전히 종료되기 직전 호출. 모든 리소스 해제, 마지막 정리 작업 등
    1. 생성onCreate() → onStart() → onResume()
    2. 일시 중지onPause() → (필요 시) onStop()
    3. 재개onRestart() → onStart() → onResume()
    4. 종료onPause() → onStop() → onDestroy()

Jetpack Compose의 컴포지션

  • @Composable 함수가 실행될 때 UI 트리가 구성되는 시점이 컴포지션
  • 상태(state) 변경 시마다 재실행 → 재컴포지션 발생
  • onCreate()처럼 단 한 번만 호출되는 구조가 아님
LaunchedEffect(Unit) {
    // 컴포지션 진입 시 1회 실행
}

2. LaunchedEffect와 DisposableEffect 차이

LaunchedEffect(Unit)

1회성 비동기 작업 (ex. 초기 네트워크 요청)에 적합

LaunchedEffect(Unit) {
    viewModel.loadInitialData()
}
  • 컴포지션 최초 진입 시 1회만 실행
  • 컴포지션 종료 시 자동으로 취소됨
  • 수동 클린업 불필요

DisposableEffect(lifecycleOwner)

외부 리소스와 연동할 때 사용 (예: Lifecycle 감지)

DisposableEffect(lifecycleOwner) {
    val observer = LifecycleEventObserver { _, event ->
        when (event) {
            Lifecycle.Event.ON_RESUME -> camera.start()
            Lifecycle.Event.ON_PAUSE -> camera.stop()
        }
    }
    lifecycleOwner.lifecycle.addObserver(observer)

    onDispose {
        lifecycleOwner.lifecycle.removeObserver(observer) // ✅ 반드시 클린업
    }
}
  • 컴포지션 생애 동안 외부 리소스를 등록/해제
  • onDispose를 통해 명시적으로 클린업 로직 작성 필수
  • LifecycleEventObserver를 통해 onResumeonPause 등을 감지 가능

3. Compose에서 Lifecycle 이벤트 감지 방법

  • 컴포저블은 액티비티 생명주기(예: onResume)를 자동으로 감지하지 않음
    • 예: 화면 전환 시 액티비티는 onPause() → onResume()을 트리거하지만, 컴포지션은 상태 변경이 없으면 재실행되지 않음.

      → 필요 시 DisposableEffect + LifecycleObserver를 통해 수동으로 연동해야 함

DisposableEffect(lifecycleOwner) {
    val observer = LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_RESUME) {
            // 포그라운드 진입 시 동작
        }
    }
    lifecycleOwner.lifecycle.addObserver(observer)

    onDispose {
        lifecycleOwner.lifecycle.removeObserver(observer)
    }
}

4. 상황별 정리

상황적합한 방법설명
컴포지션 진입 시 초기 데이터 로드LaunchedEffect(Unit)1회성 비동기 처리
앱 포그라운드 진입 시 카메라 시작DisposableEffect + LifecycleObserver명시적 이벤트 감지 및 리소스 제어 필요
네트워크 요청, 애니메이션 트리거LaunchedEffect단발성 처리
외부 콜백, 브로드캐스트 등록 등DisposableEffect등록과 해제가 필요한 작업

5. 결론

  • Compose 컴포지션은 상태 기반으로 동작하며, 전통적인 생명주기 메서드(onCreate 등)와 다르게 작동
  • 외부 생명주기 이벤트(onResume 등)를 다루려면 DisposableEffect를 통해 명시적으로 처리해야 함
  • 둘은 목적, 작동 방식, 생명주기 흐름이 다르기 때문에 혼용하거나 직접 비교하면 안 됨

0개의 댓글