|

안드로이드 앱 구조 입문 시리즈 (3편) – 생명주기를 알아야 설계가 쉬워지는 이유

생명주기를 알아야 설계가 쉬워지는 이유 대표 이미지
안드로이드 앱 구조 입문 시리즈 3편

안드로이드 앱 구조 입문 시리즈 (3편) – 생명주기를 알아야 설계가 쉬워지는 이유는 생명주기를 콜백 목록이 아니라 설계 기준으로 이해하게 만드는 글입니다. 안드로이드에서 코드를 어디에 둬야 하는지가 왜 생명주기와 연결되는지 설명합니다.


이 글이 시리즈에서 맡는 역할

1편에서는 안드로이드 앱을 구조로 보는 큰 그림을 잡았고, 2편에서는 Activity와 Fragment를 왜 나눠야 하는지 설명했습니다. 이번 3편은 그다음 단계로 화면 수명과 코드 책임을 어떻게 연결해서 봐야 하는지 설명합니다.

앞선 글은 1편2편에서 이어서 볼 수 있습니다.


생명주기를 왜 외우기만 하면 안 될까

생명주기를 외우는 것 자체가 나쁜 것은 아닙니다. 문제는 그걸로 끝나는 경우입니다. 초보자는 보통 생명주기를 호출 순서로만 이해하지만 안드로이드에서 더 중요한 것은 화면이 계속 같은 상태로 유지되지 않는다는 사실입니다.

즉 생명주기는 콜백 표가 아니라 화면의 수명이 계속 바뀐다는 신호입니다. 이 사실을 놓치면 화면이 잠깐 사라질 때 멈춰야 할 작업과 다시 돌아왔을 때 유지되어야 할 상태를 구분하지 못하게 됩니다.


안드로이드에서 설계가 어려운 이유는 화면 수명이 짧기 때문이다

안드로이드에서는 화면이 다른 앱에 가려질 수 있고, 회전으로 다시 만들어질 수 있고, 시스템이 메모리를 확보하려고 제거할 수도 있습니다. 즉 지금 보이는 화면을 영구한 대상으로 취급하면 설계가 바로 흔들리기 시작합니다.

이때 중요한 질문은 이것입니다. 화면이 사라져도 이 데이터는 남아 있어야 하는가, 이 작업은 화면이 안 보여도 계속 살아야 하는가, 이 코드는 지금 보이는 UI에만 속한 것인가. 이 질문이 바로 생명주기와 설계가 연결되는 지점입니다.

생명주기와 설계 관계 구조도
화면 수명, 코드 수명, 상태 수명, 작업 수명을 함께 봐야 한다

생명주기를 설계 기준으로 본다는 것은 무슨 뜻일까

안드로이드에서 코드를 어디에 둘지는 사실상 그 코드의 수명을 어디에 둘지 정하는 일과 같습니다. 잠깐 화면에 텍스트를 보여주는 코드는 화면 수명과 같이 가도 되지만, 서버에서 가져온 데이터를 보관하는 상태는 화면보다 더 길게 가야 할 수 있습니다.

즉 생명주기를 이해한다는 것은 콜백을 많이 안다는 뜻이 아니라 코드마다 적절한 수명을 배정할 수 있다는 뜻에 가깝습니다.


각 생명주기 단계는 설계에서 어떻게 읽어야 할까

onCreate: 화면의 뼈대를 처음 세우는 시점

onCreate()는 보통 화면의 기본 틀을 준비하는 위치입니다. setContentView(), view binding 초기화, RecyclerView나 Toolbar 같은 기본 UI 설정처럼 화면의 초기 뼈대를 세우는 코드가 잘 어울립니다. 하지만 초보자는 여기에 모든 것을 몰아넣기 쉽습니다.

onStart: 화면이 사용자에게 보이기 시작하는 구간

onStart()는 화면이 사용자에게 보이기 시작하는 단계입니다. 생성되었다와 보이기 시작했다는 다를 수 있다는 감각이 중요합니다. 즉 화면 가시성과 연결된 준비를 생각하기 좋은 위치입니다.

onResume: 사용자가 실제로 상호작용하는 구간

onResume()은 화면이 실제로 포커스를 가지고 사용자가 상호작용할 수 있는 상태에 들어온 시점으로 볼 수 있습니다. 입력과 직접 연결된 처리나 다시 화면이 활성화될 때 필요한 작업을 떠올리기 좋은 위치입니다. 다만 자주 다시 호출될 수 있다는 점을 같이 이해해야 합니다.

onPause, onStop, onDestroy를 어떻게 읽어야 할까

onPause()는 화면이 상호작용 상태를 잃기 시작하는 신호로, onStop()은 더 이상 보이지 않는 구간으로 읽으면 좋습니다. onDestroy()는 객체가 정리되는 단계이지만 무조건 앱이 완전히 끝난다는 뜻으로 이해하면 안 됩니다. 이 단계들은 화면 수명 변화의 단계로 읽는 편이 중요합니다.


같은 코드라도 어디에 두느냐에 따라 의미가 달라진다

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        loadData()
    }

    private fun loadData() {
        // 네트워크 호출
    }
}

문법상 문제는 없지만 설계 관점에서는 질문이 생깁니다. 회전되면 다시 호출돼도 되는가, 이미 가져온 상태를 다시 덮어도 되는가, 이 작업은 정말 Activity 수명에 붙어 있어야 하는가 같은 질문입니다. 즉 중요한 것은 코드가 돌아가느냐가 아니라 이 코드가 이 위치에 있어야 하느냐입니다.


초보자가 생명주기에서 자주 하는 실수

  1. 화면과 상태를 같은 것으로 보는 경우
  2. 모든 초기화를 onCreate에 몰아넣는 경우
  3. 비동기 작업을 생명주기와 분리해서 보는 경우
  4. 콜백 이름은 외웠지만 책임 분리는 안 된 경우

이 실수들의 공통점은 생명주기를 알고 있다고 생각하지만 실제 설계 판단 기준으로는 쓰지 못한다는 점입니다.


왜 ViewModel 이야기가 자연스럽게 이어질까

생명주기를 제대로 이해하면 자연스럽게 다음 질문이 생깁니다. 그럼 화면보다 오래 살아야 하는 상태는 어디에 둬야 하지? 여기서 ViewModel이 등장합니다. 즉 ViewModel은 갑자기 튀어나온 기술이 아니라 생명주기를 이해한 다음에야 필요성이 보이는 구조적 답입니다.

class MainViewModel : ViewModel() {
    private val _uiState = MutableStateFlow<MainUiState>(MainUiState.Loading)
    val uiState: StateFlow<MainUiState> = _uiState

    fun setSuccess(items: List<String>) {
        _uiState.value = MainUiState.Success(items)
    }
}

이 예시는 단순하지만 화면은 잠깐 사라질 수 있어도 상태는 다른 수명을 가질 수 있다는 점을 보여줍니다. 즉 생명주기를 이해하면 왜 상태를 화면 밖으로 빼야 하는지도 자연스럽게 이해됩니다.


생명주기는 비동기 작업과도 바로 연결된다

class MainViewModel(
    private val repository: ItemRepository
) : ViewModel() {

    fun loadItems() {
        viewModelScope.launch {
            repository.loadItems()
        }
    }
}

생명주기를 설계 기준으로 보면 비동기 작업도 다르게 보입니다. 왜 Activity 안이 아니라 ViewModel에서 시작하는가, 왜 화면 수명과 작업 수명을 같이 고려하는가 같은 질문이 중요해집니다. 즉 코루틴도 그냥 비동기 문법이 아니라 화면 수명과 연결된 구조 문제로 보이기 시작합니다.


생명주기를 설계 기준으로 보는 습관이 왜 중요한가

안드로이드 앱은 기능보다 구조가 먼저 흔들립니다. 중복 로딩, 이상한 상태 초기화, 어색한 복구, 너무 커진 Activity, 책임이 섞인 UI 코드 같은 문제의 상당수는 생명주기를 설계 기준으로 보지 않았을 때 생깁니다.

즉 생명주기를 잘 이해한다는 것은 콜백을 많이 외운다는 뜻이 아니라 화면 수명과 코드 수명이 다를 수 있다는 사실을 기준으로 설계한다는 뜻에 가깝습니다.


이번 편의 핵심 정리

  • 생명주기는 콜백 이름 암기보다 설계 기준으로 보는 것이 중요하다
  • 안드로이드 화면은 계속 살아 있는 대상이 아니다
  • 코드를 어디에 둘지는 결국 그 코드의 수명을 어디에 둘 것인지의 문제다
  • 상태와 비동기 작업은 생명주기와 함께 봐야 한다
  • ViewModel은 생명주기 이해 다음에 자연스럽게 이어지는 답이다

이 기준이 잡히면 다음 편인 ViewModel은 왜 필요할까도 훨씬 쉽게 읽힙니다.

함께보면 좋은 글