DEVELOPMENT

ViewModel : 뷰모델

OSP 2026. 8. 25. 17:29

ViewModel 뷰모델


  •  뷰모델이란 : 랜더링 데이터 책임 + 중간 생명주기 독립
  • 더보기

     

    • 고전적 의미
      • 포괄적/아케텍쳐적으로는 뷰모델이라는 컴포넌트를 두는 디자인 패턴을(MVVM: Model-View-ViewModel) 약식으로 의미하기도 하고,구체적/기능적으로는 랜더링 데이터 관리를 책임지는 컴포넌트를 의미한다.
      • 아주 정형적인 설명이다. 어렵게 생각할 것이 전혀 없고, UI 코드와 비즈니스 로직을 분리하겠다는 단순하고 오래된 책임 분리 패턴/컴포넌트이다. 그러나 현대적인 중심 의미는 여기서 더 발전되었기 때문에 여기에만 의존하면 뷰모델의 사용 맥락을 이해하기 어렵다.
    • 현대적 의미
      • 현대적으로 뷰모델의 주요한 의미는 생명주기에 있다. 이는 아래 공식 문서의 그림이 아주 명확하게 표현한다. 그렇다고 고전적 의미를 잃은 건 아니고, "액티비티/프래그먼트의 전체 수명에만 의존하는 랜더링 데아터 책임 패턴/컴포넌트" 의 형태로 생명주기에 대한 의미가 추가되었다고 봄이 옳다.
        • 현대적으로는 생명주기가 A to V쯤 되는데, 뷰모델 도입을 고민하게 만드는 문제는 열에 아홉이 생명주기 문제이기 때문이다. 사실 생명주기 문제가 아니면 뷰모델을 도입할 이유가 잘 없다. 프로세스 생명주기에서 독립적인 프로세스의 랜더링 데이터? "인간의 생애주기에서 독립적인 인간의 의류" 같은 것이기 때문이다. 
      • https://developer.android.com/static/images/topic/libraries/architecture/viewmodel-lifecycle.png
    •  

     

  • 뷰모델의 용처 : 생명주기 독립이 필요한 랜더링 책임
  • 더보기

     

    뷰모델이 왜 사용되고, 어떻게 사용되는지 이해하려면 데이터 랜더링 패턴에 대해 살펴보아야 한다.

    1. 인메모리 랜더링 : 랜더링 패턴의 가장 원시적인 형태이다. 메모리에 값을 입력받고, 이를 랜더링하는 것이다. 명확하고 또렷한 갱신시점(입력)이 있으나, 값이 휘발적이라는 문제가 있다
      • 여기서 첫번쨰 문제가 발생한다. 대표적으로 화면 회전이 있는데, 화면 회전은 onDestroy -> onCreate로 이어지는 공격적인 동작이다. 이는 액티비티/프래그먼트를 통째로 파괴하고 다시 시작하는 것으로 메모리의 휘발성 데이터가 전부 사라져 초기값으로 돌아가는 문제가 발생한다.
    2. 1회성 쿼리 랜더링 : 그 다음으로는 DB 등에 값을 저장해두고, 이를 일회적으로 읽어 랜더링하는 것이다. 데이터 자체가 휘발적이지는 않으며, 큰 변함이 없는 케이스에서유용하다. 그러나 변환이 잦은 데이터에 대해서는 갱신 시점을 제어하기 어려운 문제가 있다.
    3. 리액티브 랜더링 : 현대적 패턴으로 값 자체는 DB등에 저장해두며, 그 DB의 데이터를 구독하다가 데이터가 변하면 알아서 랜더링하도록 제어하는 것이다. 데이터의 비휘발성과 갱신 시점의 제어를 모두 잡은 패턴이다. 
      • 여기서 이 구독 상태를 제어하지 않으면 액티비티/프래그먼트가 백그라운드이거나, 멈춤상태 등일 경우에도 데이터가 변하는 경우 보이지도 않는 UI를 갱신하기 위해 메모리를 소모하는 문제가 발생한다.
      • 따라서 액티비티/프래그먼트가 활성 상태인 생명주기에서만 구독을 유지하는 것이 권장되는데, 이러한 생명주기 종속은 해당 생명주기에 진입할 떄마다 종속 구문을 통째로 실행해버려 구독을 새로 시작하는 문제가 있다. 쉽게 말하면 잠깐 다른 액티비티 들어갔다 탈출로 복귀한 경우, 데이터가 동일해도 똑같은 값을 다시 방출하는 꼴이다.

    인메모리 랜더링과 리액티브 랜더링에서 발생하는 문제는 모두 생명주기와 관련이 있다. 이렇게 액티비티/프래그먼트의 랜더링을 담당하면서도, 해당 그 생명주기에서 한 발 떨어진 컴포넌트가 필요해지는데, 이것이 바로 뷰모델이다. 이 생명주기에 대해서는 앞선 링크의 공식 문서 그림을 참조하면 이해가 빠르다.

    • 다만 화면 회전의 경우 onDestroy()가 호출되지만, 뷰모델은 화면 회전에 의한 데이터 리셋을 방어하려는 의도가 강한 패턴인 만큼, onDestroy() 에서 화면 회전을 검증하여 화면 회전인 경우 뷰모델을 OS 메모리에 대피시켜 파괴를 막는다. 냄새가... 난다!
  • 요약