상식닷컴
로그인
가입하기
2026년 상식닷컴 선정 식당 & 카페 리스트
2025년 2026년 신상 호텔 리스트
최근에 오픈한 호텔을 찾는다면 살펴보세요
일주일 식단표 어플
자동 일주일 식단표 어플
안드로이드
아이폰
주식 & 코인 차트의 신
1000만원으로 2000만원 만들기 프로젝트
수정하기 - LiveData를 단일 이벤트 처리에 사용하는 방법은?
닉네임
비밀번호
제목
내용
[이미지 업로드는 권한이 있는 사람만 가능. 하단 카톡으로 연락]
LiveData는 안드로이드 아키텍처 컴포넌트 중 하나로, 주로 UI에 상태 변화를 관찰 가능하게 전달하는 데 사용됩니다. 하지만 LiveData는 기본적으로 상태 기반(State-based)이며, 이벤트 기반(Event-based) 동작에는 몇 가지 한계가 있습니다. 예를 들어, 화면 회전 등으로 액티비티/프래그먼트가 <a href='https://sangseek.com/sangseeks/재생성/ko'>재생성</a>될 때 LiveData의 값이 재전달되어, 단일 이벤트(예: 토스트 메시지 표시, 네비게이션)도 다시 발생하는 문제가 있습니다. 즉, LiveData는 상태 변화를 저장하고 관찰자에게 지속해서 최신 상태를 전달하지만, '한 번만 처리되어야 하는 이벤트'를 다루기에는 적합하지 않습니다. 이런 단일 이벤트(single event)를 올바르게 처리하기 위해 몇 가지 대표적인 패턴이 존재합니다. --- 1. <a href='https://sangseek.com/sangseeks/Event Wrapper/ko'>Event Wrapper</a> 사용 가장 흔히 사용되는 방법은 이벤트 내용을 래핑하는 클래스(Event wrapper)를 만들어 LiveData가 이 객체를 관찰하도록 하는 것입니다. 이 클래스는 이미 이벤트가 처리되었는지 여부를 추적해, 같은 이벤트가 중복 처리되지 않도록 만듭니다. 예시로 다음과 같은 클래스를 만들 수 있습니다. ```kotlin open class Event<out T>(private val content: T) { private var hasBeenHandled = false / * 이벤트 내용이 아직 처리되지 않았다면 반환, 이후에는 null 반환 */ fun getContentIfNotHandled(): T? { return if (hasBeenHandled) { null } else { hasBeenHandled = true content } } / * 이벤트 내용을 무조건 반환 (처리 여부와 상관없이) */ fun peekContent(): T = content } ``` ViewModel에서는 이렇게 정의한 `Event` 클래스를 활용해 LiveData를 만듭니다. ```kotlin private val _singleEvent = MutableLiveData<Event<String>>() val singleEvent: LiveData<Event<String>> = _singleEvent fun triggerEvent() { _singleEvent.value = Event("이벤트 내용") } ``` View(액티비티나 프래그먼트)에서는 옵저버에서 `getContentIfNotHandled()`로 이벤트가 아직 처리되지 않았을 때만 처리합니다. ```kotlin viewModel.singleEvent.observe(this) { event -> event.getContentIfNotHandled()?.let { message -> Toast.makeText(context, message, Toast.LENGTH_SHORT).show() } } ``` 이 방식의 장점은: - 이벤트가 한 번만 처리되도록 보장 - 같은 이벤트가 두 번 이상 중복 실행되는 것을 방지 - LiveData 기본 메커니즘을 그대로 사용 가능 단점은: - 이벤트 래퍼 클래스 코드를 별도로 작성해야 함 - 약간의 boilerplate 코드 존재 --- 2. SingleLiveEvent 사용 Google이나 커뮤니티에서 만들어진 `SingleLiveEvent` 라이브러리를 사용하는 방법도 있습니다. `SingleLiveEvent`는 내부적으로 한 번만 이벤트를 전달하도록 구현된 LiveData의 서브클래스입니다. `SingleLiveEvent`는 다음과 같은 특징이 있습니다. - 오직 한 번만 값이 전달됨 - 여러 옵저버가 있을 때 하나의 옵저버에만 이벤트가 전달되는 문제 존재 (대부분 단일 소비자가 있어 문제가 없다) - 별도의 이벤트 래핑없이 사용 가능 사용 예시는 다음과 같습니다. ```kotlin private val _singleEvent = SingleLiveEvent<String>() val singleEvent: LiveData<String> = _singleEvent fun triggerEvent() { _singleEvent.value = "이벤트 내용" } ``` View에서는 그냥 일반 LiveData 옵저버처럼 사용하면 되며, 이벤트는 한 번만 전달됩니다. 단점: - SingleLiveEvent의 구현 결정권이 라이브러리나 직접 구현한 코드에 따라 다름 - 여러 옵저버가 있을 때 예상치 못한 동작이 발생할 수 있음 --- 3. 코루틴과 Channel, Flow 사용 (최근 권장 방법) 요즘 안드로이드에서는 코틀린의 코루틴을 활용하는 방식을 권장합니다. 특히 `<a href='/sangseeks/StateFlow/ko'>StateFlow</a>`나 `<a href='https://sangseek.com/sangseeks/SharedFlow/ko'>SharedFlow</a>` 등 Flow API를 활용하면 단일 이벤트 처리에 매우 적합합니다. 예를 들어 `SharedFlow`를 `MutableSharedFlow<Event>`로 만들고 한 번만 이벤트를 방출한 후, UI 쪽에서는 collect하여 처리합니다. - MutableSharedFlow는 버퍼 크기와 replay 옵션을 활용해서 이벤트를 한 번만 제공하도록 설정 가능 - LiveData와 달리 재구독 시에 이벤트가 중복 전달되는 문제 없음 간단 예시: ViewModel ```kotlin private val _eventFlow = MutableSharedFlow<String>(replay = 0) val eventFlow = _eventFlow.asSharedFlow() fun triggerEvent() { viewModelScope.launch { _eventFlow.emit("이벤트 내용") } } ``` View(프래그먼트) ```kotlin lifecycleScope.launchWhenStarted { viewModel.eventFlow.collect { message -> Toast.makeText(context, message, Toast.LENGTH_SHORT).show() } } ``` 장점: - 단일 이벤트 처리에 최적화됨 - 재구독해도 이벤트가 중복 전달되지 않음 - 코루틴 라이브러리와 결합해 유연한 제어 가능 단점: - 코루틴, Flow 문법에 대한 학습 필요 - 기존 LiveData와는 다소 다른 사용법 --- 결론 - LiveData는 상태 기반 컴포넌트로, 단일 이벤트 전용으로 사용하기에 적합하지 않음 - 단일 이벤트 처리를 위해 `Event Wrapper` 패턴 혹은 `SingleLiveEvent`를 사용할 수 있음 - 최신 안드로이드 개발에서는 코루틴 `SharedFlow`를 단일 이벤트용으로 추천 - 상황과 프로젝트 성격에 맞게 적절한 방식을 선택하는 것이 가장 중요 --- 이와 같은 방법들로 LiveData 혹은 유사한 Observable 컴포넌트 위에서 단일 이벤트를 안전하고 중복 없이 처리할 수 있습니다.
이용안내
커뮤니티 이용안내
×
- 게시한 게시글로 발생하는 문제는 게시자에게 책임이 있습니다.
- 게시글이 타인/타업체의 저작권을 침해할 경우 모든 책임은 게시자에게 있습니다. 게시자가 모든 손해를 부담해야 합니다.
- 상식닷컴 운영자는 게시자와 상의하지 않고 게시글을 수정 또는 삭제할 수 있습니다.
- 상식닷컴 운영자는 깨끗한 커뮤니티 공간을 만드는 것이 1순위입니다.
수정하기
취소하기