Skip to main content

Command Palette

Search for a command to run...

[Android] ViewModel Event 처리에 대한 개인적인 오해

ViewModel에서 Event를 처리하는 방법을 잘못 이해하고 있었습니다...

Updated
2 min read
[Android] ViewModel Event 처리에 대한 개인적인 오해

더 잘하고 싶은 안드로이드 개발자.

https://github.com/jinukeu

오해의 시작

MVVM의 ViewModel에서 이벤트를 처리하는 방법 6가지 이 글을 보고 "아 ... ViewModel에서 이벤트를 처리하기 위해서는 무조건 LiveData + Event같은 방식을 사용해야 하는구나" 라고 생각했다. 글을 읽어보면 알겠지만, 단순히 버튼을 클릭해서 토스트 메세지를 띄우는 로직을 setOnClickListener로 처리하지 않고 LiveData를 Observe하는 (실제론 조금 더 복잡하고 다양한) 방식으로 처리했기 때문이다. 그래서 지금까지 진행해왔던 프로젝트는 전부 무조건 SingleLiveData를 사용하여 클릭 이벤트를 처리해왔다.

그러다 문득, "아니 토스트 메세지 출력 처럼 간단한 로직은 그냥 setOnClickListener로 처리하면되지 않나?" 라는 생각이 들었고 MVVM에서 setOnClickListener를 사용하면 안되는 이유를 구글링해보았다. 하지만 ... MVVM에서 setOnClickListener 사용하지 마세요! 같은 글을 찾아볼 순 없었고 궁금증을 확실하게 해결하기 위해 오픈 채팅방에 질문을 올렸다.

감사하게도 많은 분들이 답변을 주셨고 이를 토대로 내린 결론은 다음과 같다.

  1. 위 링크의 단순한 버튼 클릭 -> 토스트 출력예시를 위한 것이고 실제로 이런 비즈니스 로직을 처리하지 않는 간단한 로직은 setOnClickListener로 처리해도 상관없다.

  2. 비즈니스 로직이 들어간 경우 해당 로직을 viewModel에 위임할 수 있으며 이를 통해 액티비티에 로직을 작성하지 않을 수 있다.

구글 공식 문서에도 다음과 같이 나와있다.

UI 요소의 상태 수정과 관련된 경우 UI에서 사용자 이벤트를 직접 처리할 수 있습니다. 이벤트가 화면상 데이터의 새로고침 같은 비즈니스 로직을 실행해야 하는 경우 ViewModel로 처리해야 합니다.

class LatestNewsActivity : AppCompatActivity() {

    private lateinit var binding: ActivityLatestNewsBinding
    private val viewModel: LatestNewsViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        /* ... */

        // The expand section event is processed by the UI that
        // modifies a View's internal state.
        binding.expandButton.setOnClickListener {
            binding.expandedSection.visibility = View.VISIBLE
        }

        // The refresh event is processed by the ViewModel that is in charge
        // of the business logic.
        binding.refreshButton.setOnClickListener {
            viewModel.refreshNews()
        }
    }
}

코드를 보면 setOnClickListener를 사용한 것을 볼 수 있다.

결론

MVVM의 ViewModel에서 이벤트를 처리하는 방법 6가지을 사용하는 이유는 ViewModel에 비즈니스 로직을 위임하기 위함이었다 ... 혼자 멋대로 오해하고 ... 북치고 장구치고 ... ㅋㅋㅋ 후 갈 길이 정말 멀다. 추가로 오픈 채팅의 답변 내용 중에 유닛 테스트관련 내용도 있었는데 이것도 공부해야겠다.

More from this blog

단위테스트 2장 정리

단위 테스트의 정의에는 많은 늬앙스가 있다. 크게 고전파, 런던파로 나뉜다. 고전파: 모든 사람이 단위 테스트와 테스트 주도 개발에 원론적으로 접근하는 방식 런던파: 런던의 프로그래밍 커뮤니티에서 시작 단위 테스트의 정의 단위 테스트는 작은 코드 조각을 검증하고 빠르게 수행하고 격리된 방식으로 처리하는 자동화된 테스트다. 격리 문제에 대한 런던파의 접근 코드 조각을 격리된 방식으로 검증한다는 것은 무엇을 의미할까? 런던파에서는 테스트 ...

Sep 3, 20243 min read

단위 테스트 1장 정리

단위 테스트 1장 정리 내용입니다. 단위 테스트에 시간을 투자할 때는 항상 최대한 이득을 얻도록 노력해야하며, 테스트에 드는 노력을 가능한 줄이고 그에 따르는 이득을 최대화해야 한다. 이 책에서 다루는 내용은 비용 편익 분석 방법을 배우고 특정 상황에서 적절한 테스트 기술을 적용할 수 있다. 또한 공통적인 안티 패턴을 피하는 방법도 배운다. 단위 테스트의 목표 단위 테스트의 목표는 무엇인가? 프로젝트의 지속 가능한 성장을 가능하게 하는 것이다...

Aug 27, 20242 min read

23년 하반기 회고

23년 상반기 회고에서 이어지는 글이다. 8 - 9월 이력서 제출 그리고 ... 이력서와 포트폴리오를 만들었다. 꽤나 잘 만들었다고 생각했다. 개발자 지인들의 첨삭, 인프런 멘토링, 유료 이력서 첨삭 서비스를 받으며 칭찬을 꽤 받았기 때문이다. 내가 보기에도 괜찮은 것 같고 ... 다른 사람들이 보기에도 괜찮다고 했으니 서류 합격률은 꽤 높을거라 생각했다. 50개의 서류를 넣은 결과, 3번의 서류 합격 그리고 단 한 곳에서만 최종합격했다. (최...

Jan 1, 20243 min read
23년 하반기 회고

[Android] Compose 수명 주기, 부수효과

수명 주기 개요 컴포지션은 UI를 기술하는 컴포저블의 트리 구조이다.컴포지션은 초기 컴포지션을 통해서만 생성되고 리컴포지션을 통해서만 업데이트 된다. 컴포저블의 수명 주기 컴포지션 시작 리컴포지션 컴포지션 종료 리컴포지션은 일반적으로 State<T> 객체가 변경되면 트리거됩니다. 컴포지션 내 컴포저블의 분석 컴포지션 내 컴포저블의 인스턴스는 호출 사이트(call site)로 식별된다. (호출 사이트는 컴포저블이 호출되는 소스코드 위치...

Dec 22, 20236 min read
[Android] Compose 수명 주기, 부수효과

[Android] rememberUpdatedState 완벽 이해

rememberUpdatedState 정의 공식 문서에는 다음과 같이 적혀있다. 값이 변경되는 경우 다시 시작되지 않아야 하는 효과(Effect)에서 값 참조 포스팅을 정리하면서 정의한 rememberUpdateState는 아래와 같다. remember는 초기 컴포지션에서만 값을 저장하고 리컴포지션 때 들어온 값은 저장하지 않는다. 리컴포지션 때 들어온 값도 저장하고 싶을 때 rememberUpdateState를 사용한다. 이게 도대체 ...

Dec 14, 20234 min read
[Android] rememberUpdatedState 완벽 이해

Jinukeu

33 posts