오늘 DDD에서 발표한 내용을 가져와 블로그에 글을 써보고자 합니다.
시간이 지남에 따라 변하는 모든것을 지칭합니다.
예를 들어 아래와 같은 화면을 구현한다고 가정해봅시다.
이곳에서 상태는 어떤게 있을까요?
아마 대략적으로 간추려보면, 위와 같은것들을 상태로 볼수있을것 같습니다.
안드로이드 공부의 절반은 상태관리 때문에 나온다고 해도 무방한데요.
왜냐면 모바일은 너무나 리액티브 하기 때문입니다.
안드로이드는 왜 리액티브 할까?
한번 렌더링되면 끝인 웹사이트와 다르게 앱은 가로 세로 변경 뿐만 아니라 전화,다른 앱 사용, 작은 메모리로 인한 프로세스 종료 등 여러 상황이 발생합니다.
우리는 이러한 Configuration Change에 반응해, 저장이 필요한 상태들을 StateHolder(일반적으로 AAC ViewModel)에 담아놓기 시작했습니다.
저장이 필요한 상태들은 비즈니스 로직을 통해 가져온 데이터, 사용자가 입력한 Data등(전화와서 받았더니 입력했던 정보들이 날아갔을때의 기분이란..)들이 있습니다.
우리는 이중에서도 비즈니스 로직을 통해서 가져온 데이터(네트워크 콜이든 데이터베이스에서)를 중점적으로 관리하는데
초점을 맞추고 있습니다.
자 이제 State에 대한 설명은 좋으니 아래와 같은 화면을 구현해보도록 합시다!
livedata
가 나오고 mvvm이 한참 대세가 되었던 시기에 State를 각자 구독하여 상태를 만들곤 했습니다.
DataBinding을 통해 1:1 매핑이 편했었기에 주로 사용하던 방식이였으나,
위와 같은 이유로 점차 UIState를 하나로 관리하자는 얘기가 시작되었습니다.
현재 Google Android Guide가 권장하는 UiState로 화면이 아무리 복잡해도 1:1 매핑이 가능합니다.
또한, 하나의 UiState를 구독하기에, 1번에 비해 관리가 편해졌습니다.
하지만 DataClass를 관리하는것에 있어서 아래와 같은 문제가 발생하기 시작했습니다.
dataClass는 copy()
를 통해 부분업데이트를 강력하게 지원하는데, 하나의 프로퍼티가 바뀌어도 모든 옵저버에 변경을 알리기 때문에 1회성 동작에 있어서 개발자가 꼼꼼히 확인을 해야했습니다.
아래의 이미지를 보고 서로 몇가지의 상태를 표현할 수 있는지 상상해보세요!
어느정도 State를 만들다보니, 일반적인 화면에서는 Loading과 Error와 Success는 상호베타적인 화면이라는것을 깨달았습니다.
그렇다면 UI State를 Sealed Class
로 만든다면, 개발자의 실수로인해 Loading과 Error과 같은 화면에 존재하는 일은 발생하지 않겠죠.
또한 명확하게 1가지의 상태만 가지기 때문에, 현재 어떤 상태인지 명확하게 알수가 있습니다.
하지만 1가지의 상태만 가지는것이 결국 발목을 잡을때도 있습니다.
예를들어 Paging을 직접구현한다고 생각해봤을때, sealedClass
로 상태를 구현한다면, 이전값을 저장하는 문제가 생길수 있습니다.
결국 1번, 2번, 3번에 서로 장단점이있고, 옳은것은 없습니다.
화면에따라 뭘 선택할지 고민하는것이 가장 Best지만, 어떻게든 통일성을 맞추고자 한다면 3번과 1번은 같이 사용될것 (Now in Android 형태)같네요.
항상 개발에는 정답이 없다는것이 요즘 절실하게 생각되는 때입니다.
긴 글 읽어 주셔서 감사합니다 <3
Compose sample app: UI state with Flow, offline first
A cleaner way to interact between Composable and ViewModel in Jetpack Compose
Managing Jetpack Compose UI State With Sealed Classes
[Proposal] Primitive or Channel that guarantees the delivery and processing of items