Jetpack Compose는 안드로이드 앱 개발을 혁신적으로 변화시켰으며, UI 컴포넌트를 더 간편하게 구축하고 관리할 수 있게 해준다. Jetpack Compose에서 상태를 관리하는 데 자주 사용되는 두 가지 함수는 remember
와 rememberSaveable
이다. 이 두 함수는 비슷해 보일 수 있지만, 용도와 사용 사례가 다르다.
remember
란 무엇인가?remember
는 Jetpack Compose의 상태 관리 시스템의 핵심 부분으로, 컴포저블 함수 내에서 값을 생성하고 기억하는 데 사용된다. remember
를 사용하면, 값이 컴포저블이 재구성(recomposition)되더라도 유지되며, 컴포저블이 활성화된 동안 상태가 지속된다.
다음은 remember
를 사용하여 카운터를 유지하는 간단한 예제이다:
@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }
Button(
onClick = { count++ }
) {
Text(text = "Increment Counter")
}
Text(text = "Count: $count")
}
이 예제에서 count
는 기억되며, Counter
컴포저블이 재구성되더라도 값이 유지된다.
rememberSaveable
란 무엇인가?반면에, rememberSaveable
은 화면 회전이나 기기 방향 변경과 같은 구성 변경(configuration changes) 동안 값을 유지하는 데 사용된다. 이는 구성 변경이 발생할 때 상태 정보를 유지해야 할 때 유용하다.
다음은 rememberSaveable
이 유용한 예제이다:
@Composable
fun RememberSaveableExample() {
val savedText by rememberSaveable { mutableStateOf("Initial Text") }
TextField(
value = savedText,
onValueChange = { newText ->
savedText.value = newText
}
)
Text(text = "Text Entered: $savedText")
}
이 경우, 사용자가 TextField
에 텍스트를 입력한 후 기기를 회전시키면, rememberSaveable
덕분에 입력한 텍스트가 구성 변경 후에도 여전히 표시된다. 만약 rememberSaveable
을 사용하지 않았다면, 텍스트는 회전 동안 사라질 것이다.
목적:
remember
: 컴포저블의 재구성 동안 상태를 유지하는 데 사용된다.rememberSaveable
: 구성 변경 동안 상태를 보존하는 데 사용된다.사용 사례:
remember
: 구성 변경이 필요 없는 상태를 유지하는 데 사용된다.rememberSaveable
: 구성 변경 동안 상태 정보를 지속적으로 유지하려는 경우에 사용된다.수명:
remember
: 컴포저블이 활성화된 동안 상태가 유지되며, 컴포저블이 파괴되면 상태도 사라진다.rememberSaveable
: 구성 변경을 통해 상태가 유지되며, 컴포저블 자체보다 더 오래 유지될 수 있다.remember 사용이 적합한 경우:
rememberSaveable 사용이 적합한 경우:
안드로이드 앱 실행 중에는 기기 설정이 변경될 수 있는데, 대표적으로 화면 회전, 언어 변경, 테마 변경, 멀티 윈도우 모드 활성화 등이 있다. 이런 변화를 안드로이드에서는 구성 변경(Configuration Changes)이라고 부른다.
우선 Compsable 의 생명 주기에 대해 간단하게 알 필요가 있다. Android 다른 Activity 나 Fragment 와 같이 Composable 또한 생명주기를 가지지만 다른 컴포넌트보다 훨씬 심플하다.
initial Composition : 처음 호출된 Composable 상태
Recomposition : 상태가 변경됨에 따라 UI 가 다시 그려지는 상태
Decomposition : Composable 이 파괴 될 때
여기서 Recomposition 이 일어날 때 변경된 상태를 저장하기 위해 사용하는 것이 remember 키워드다.
구성 변경이 발생하면 현재 실행 중인 Activity가 재시작되며, 이는 Activity가 파괴되고 다시 생성된다는 것을 의미한다. 이 과정에서 Activity 내에 저장된 인스턴스 데이터는 모두 손실되며, 심지어 remember
로 저장된 데이터도 사라진다. Activity가 재생성되면 초기 상태로 돌아가게 되는 것이 기본 동작이다.
구성 변경 외에도, 메모리가 부족할 때 기기가 Activity를 일시적으로 파괴한 뒤 다시 필요할 때 재생성하는 경우가 있는데, 이 경우도 동일하게 상태가 손실된다.
구성 변경이 일어나도 상태를 유지하려면 rememberSaveable
을 사용해야 한다. rememberSaveable
은 remember
와 비슷하게 상태를 저장하지만, 구성 변경 시에도 상태를 유지할 수 있다.
rememberSaveable
은 대부분의 경우 쉽게 사용할 수 있지만, 복잡한 데이터 타입을 저장하려면 추가적인 작업이 필요하다.
예를 들어, 데이터가 Android Bundle에 저장 가능한 타입이라면 문제가 없지만, 그렇지 않으면 Parcelable
인터페이스를 구현해야 한다.
Parcelable
은 데이터를 Parcel이라는 컨테이너에 저장하고, 이 컨테이너는 번들에 저장될 수 있다. 이를 쉽게 구현하기 위해 kotlin-parcelize
플러그인을 사용할 수 있다.
만약 Parcelable
방식이 맞지 않다면, mapSaver
또는 listSaver
를 사용하여 데이터를 Map
이나 List
로 변환해 상태를 저장할 수 있다.
이 경우에는 데이터를 컬렉션으로 변환하는 람다 함수와, 다시 원래 데이터로 복원하는 람다 함수 두 개를 제공해야 한다.
성능:
remember
는 메모리에만 데이터를 저장하므로 rememberSaveable
보다 더 가볍고 빠르다.rememberSaveable
은 데이터를 Bundle에 저장하고 복원하는 과정이 필요하므로 약간의 오버헤드가 있다.저장 범위:
remember
는 컴포지션 내에서만 데이터를 유지한다.rememberSaveable
은 구성 변경(예: 화면 회전)이나 프로세스 재시작 후에도 데이터를 유지한다. 데이터 타입 제한:
remember
는 모든 타입의 데이터를 저장할 수 있다.rememberSaveable
은 Bundle에 저장 가능한 타입(Parcelable
, Serializable
등)으로 제한된다.메모리 사용:
rememberSaveable
은 데이터를 Bundle에 복사하므로 추가적인 메모리를 사용한다.사용 목적:
remember
는 일시적이고 재생성이 쉬운 UI 상태에 적합하다.rememberSaveable
은 장기적으로 보존해야 하는 중요한 상태에 사용된다.결론적으로, 모든 상황에서 rememberSaveable
을 사용하는 것은 불필요한 오버헤드를 발생시킬 수 있다. 상황에 따라 적절한 선택을 하는 것이 성능 최적화 면에서 가장 효율적인 접근 방식이다.
대부분의 일시적인 UI 상태나 쉽게 재생성 가능한 데이터에는 remember
를 사용하고, 중요한 사용자 데이터나 앱의 중요 상태에는 rememberSaveable
을 사용하는 것이 좋다.
rememberSaveable 뿐만 아니라, 안드로이드에는 SavedStateHandle이라는 녀석도 있다.
SavedStatehandle도 상태를 저장하는 것이다. 그렇다면 RememberSaveable과 뭐가 다른걸까?
핵심 차이점은 "UI의 상태를 저장하느냐 또는 뷰모델의 상태를 저장하느냐"에 따라 다르다는 것이다.
rememberSaveable은 Compose의 UI 상태를 저장하고 복원하는 데 매우 적합하며, 화면 회전과 같은 간단한 구성 변경에 대응할 수 있다.
ex. 스크롤 위치, 애니메이션 상태, 확장/축소 상태 등 특정 UI 컴포넌트에 국한된 상태
SavedStateHandle은 ViewModel의 상태를 저장하고 복원하는 데 사용되며, ViewModel의 생애 주기나 구성 변경 외에도 ViewModel 재생성 시 상태를 유지해야 할 때 유용하다. 상태를 수동으로 관리할 수 있으며, 복잡한 상태를 처리하는 데 적합하다.
ex. 페이지네이션
https://ibrahimcanerdogan.medium.com/remember-vs-remembersaveable-in-jetpack-compose-29a19f236847