이미 ViewModel에 용도에 대해 한가지 언급을 하셨네요. "생명주기에 상관없이 ui상태를 저장"
말씀하신게 ViewModel 을 사용하는 이유 중의 하나입니다. Lifecycle(생명주기)가 View(Activity, Fragment) 보다 길기 때문에 디바이스 회전 등과 같은 Configuration changes에도 살아남을 수 있기 있기 때문에, 뷰의 상태를 복구할 때 편리함을 제공합니다. SavedInstance를 통해서도 동일한 결과를 만들 수 있지만, SavedInstance는 제한적인 사이즈의 데이터만 저장이 가능합니다. (정확히는 기억이 안나는데 500KB였던가 그럴겁니다.)
라이프사이클적인 특징 때문에 ViewModel은 보통 LiveData 와 같은 observable이나 Flow, RxJava같은 스트림과 같이 많이 사용하게 됩니다.
그리고 ViewModel을 사용하면 SavedStateHandle을 사용할 수 있게 되는데, 이걸 사용하면 앱이 백그라운드로 갔을 때 시스템에 의해 강제종료되는 process death를 처리할 수 있도록 해줍니다. process death는 DB같은 영구저장소등을 이용하지 않는한 SavedStateHandle을 사용하지 않고는 뷰상태를 완전히 복구할 수가 없습니다. 따라서 process death까지 원할하게 핸들링하길 원한다면 ViewModel + SavedStateHandle 을 사용하는걸 고려해볼 수 있습니다.
그리고 ViewModel은 onCleared 메소드가 제공되는데 여기에 사용했던 리소스를 정리하는 코드를 사용하면 라이프사이클에 안전하게 리소스를 해제할 수 있는데, 보통는 RxJava나 Coroutine 을 사용할 때 사용했던 리소스를 클리어하는 용도로 많이 사용됩니다.
ViewModel를 꼭 써야하는 게 아니기 때문에, 굳이 프로젝트에서 위에서 말할 것들을 지원해야 하는 경우가 아니라면, Presenter, ViewController 등등 다른 패턴을 사용해서 사용할 수 있습니다. 이것들의 주된 임무는 사용자액션을 서버 API와 같은 데이터를 처리하는 곳에 전달해주고 응답받은 결과를 화면에 보여주기 쉬운 구조로 가공하여 뷰에 던져주는 겁니다.