Android UI State Modeling 어떤게 좋을까?

Youngjik Yoon
6 min readSep 9, 2021

--

Photo by Kaleidico on Unsplash

우리는 안드로이드를 개발 할 때 MVVM 패턴을 사용하면서 ViewModel에서 데이터를 요청하고 결과를 UI로 만들고는 합니다.

데이터 요청은 로딩이 따라오고 항상 성공만 하지는 않습니다.
또한 UI는 한 가지 상태만을 가지고 있지 않습니다.
이를 위해 여러 개의 State를 만드는 법부터 sealed class를 활용한 State Modeling 전략까지 다양한 방법이 이용되고 있습니다.

이러한 방법들을 다양하게 시도 해 보면서 언제 사용하는게 적합한지 그리고 어떤 장・단점이 있었는지에 대한 생각을 정리해볼까 합니다.

UI 모델링을 처리하는 방법은 정말 많지만 일반적으로 사용되는 4가지 모델링 패턴으로 얘기를 해보도록 하겠습니다.

  1. 여러 개의 State를 만들고 Loading, Error 별도로 만들기
  2. sealed class로 하나의 State를 만들고 상태 개수만큼 구현체 만들기
  3. 하나의 State data class를 만들어서 관리하기
  4. 하나의 State data class와 Loading, Error 별도로 만들기

한 가지 시나리오를 가정하고 위의 네 가지 방법으로 구현 해보겠습니다.

들어가기에 앞서 프로젝트를 직접 실행 해 보고 싶으시다면
아래 GitHub 프로젝트를 확인 해주세요.

| 요구사항 |

“유저 정보를 받아와 2초정도 후에 이름과 나이를 화면에 그려주세요.
오류가 발생하면 따로 표시 해 주세요”

State 1

여러개의 State를 만들고 Loading, Error 별도로 만들기

Pros.

  • 개별적으로 State를 정의함으로써 원하는 데이터만 변경이 가능하다.
  • 각 State가 서로에게 영향을 발생시키지 않는다.
  • 데이터바인딩 코드를 작성하기 쉽다

Cons.

  • State 가짓수가 많아 실수를 유발하기 쉽다.
  • Event를 통해 상태가 어떻게 변경될지 예측이 어렵다.
  • 구독을 처리하는 코드가 많고 복잡하다.

When.

  • Base 구조를 사용하지 않는 간단한 화면에 적합
  • State와 데이터바인딩을 1:1 구조로 사용하는 경우

State 2

sealed class로 하나의 State를 만들고 상태 개수만큼 구현체 만들기

Pros.

  • MVI와 유사한 형태의 구현으로 UI에 대한 의도를 명확하게 표현이 가능
  • sealed class를 활용함으로써 객체지향적인 처리에 유리하다.
  • UI를 변경하는 코드가 분산되지 않아 코드 분석이 편하다.
  • 한 가지 상태만 가지기 때문에 상태가 섞이는 것을 고려하지 않아도 된다.

Cons.

  • 표현하고자 하는 모든 상태를 나열해야 하기 때문에 화면이 복잡해지면 상태가 비약적으로 늘어나고 부분적인 업데이트가 불가하다.
  • 각 상태가 변경되면 이전 상태를 별도로 보관하지 않는 한 이전 상태에 대한 데이터를 복구할 방법이 없다.
  • 공통으로 쓰이는 상태를 표현하기가 어렵고 공유하는 것은 더욱 복잡함
  • 데이터바인딩을 사용하기가 상당히 어렵다.

When.

  • 명확한 의도를 갖고 UI를 표현하는 경우 (생각을 바로 상태로 변경 가능)
  • 로딩이나 오류를 전체 상태로 취급할 수 있는 경우
  • 부분적인 데이터 수정 혹은 이전 상태가 필요없는 경우

State 3

하나의 State data class를 만들어서 관리하기

Pros.

  • 하나의 데이터에 필요한 모든 상태를 포함할 수 있어 UI에 대한 비즈니스 로직 처리가 편하다.
  • data class를 사용함으로써 copy라는 강력한 부분 업데이트 수단을 제공
  • UI를 변경하는 코드가 분산되지 않아 코드 분석이 편하다.
  • LiveData나 StateFlow의 map 함수와 distinctUntilChanged를 조합해 원하는 형태로 데이터바인딩에 적용 가능

Cons.

  • copy가 어느정도 안전성을 보장하지만 데이터 변경에 대한 동시성 이슈에 취약하다.
  • 화면이 복잡해지는 경우 data class에 필요한 프로퍼티가 비약적으로 늘어난다.
  • data class 특성상 하나의 프로퍼티 값만 바뀌어도 구독하고 있는 모든 옵저버에 변경을 알려 애니메이션같은 1회성 동작에 주의가 필요하다.

When.

  • UI에 대한 부분적인 수정이 빈번하게 일어나는 경우
  • UI 비즈니스 로직이 다소 복잡한 경우
  • 상태를 조합하여 자주 사용하는 경우
  • 로딩이나 오류도 상태에 포함하여 취급할 수 있는 경우

State 4

하나의 State data class와 Loading, Error 별도로 만들기

Pros.

  • UI 상태가 로딩이나 오류에 의존적이지 않아 따로 처리가 가능하다.
  • Base를 사용하는 경우 확장성 있는 구조를 제공한다.

Cons.

  • UI 상태가 로딩이나 오류와 의존성이 있는 경우 처리가 다소 복잡하다.
  • 로딩 상태를 여러 곳에서 변경할 수 있기 때문에 상태 변경에 주의가 필요하다.

When.

  • UI 상태를 로딩과 오류와 나누어서 사용하는 경우
  • Base에서 로딩과 오류를 일반적으로 처리하고 싶은 경우

여러분은 어떤 UI State Modeling 전략을 사용하고 계신가요?

저는 디자인 요구사항과 아키텍처 그리고 팀원들과의 컨벤션까지 고려하다보면 결국 이 물음에 대한 완벽한 정답은 없다고 생각합니다.
Best Practice 보다는 Team Practice가 더욱 중요하기도 하구요.

최근 LiveData나 StateFlow를 이용해 상태를 어떻게 처리해야 좋을까요?
라는 질문을 많이 받는데 이 내용을 통해 자기만의 적합한 UI State Modeling을 비교해 보면서 좋은 구조를 찾아가시길 바랍니다.

다음에는 Compose에서의 UI State Modeling을 주제로 찾아뵙겠습니다.

끝.

읽어보기 )

--

--