
안드로이드 UDF란 무엇일까라는 질문은 보통 상태 버그가 늘어날 때 생깁니다. 버튼 클릭, 로딩, 에러, 재시도, 입력값 변경이 섞이기 시작하면 화면이 어느 지점에서 꼬였는지 추적하기 어려워지기 때문입니다. UDF는 이런 문제를 줄이기 위해 상태와 이벤트의 흐름을 한 방향으로 정리하자는 생각에 가깝습니다.
이번 글에서는 UDF를 패턴 이름으로 외우는 대신, ViewModel, state, event가 어떤 식으로 이어질 때 화면 버그가 줄어드는지 안드로이드 예시로 설명하겠습니다.
UDF를 가장 짧게 설명하면 무엇일까
UDF는 사용자 이벤트가 들어오고, 상태 보관자가 그 이벤트를 처리한 뒤, 새로운 UI 상태를 다시 화면에 내보내는 구조입니다. 핵심은 화면이 임의로 여러 곳의 상태를 직접 바꾸지 않고, 상태 변경 경로를 하나로 모은다는 점입니다.
- 사용자가 event를 발생시킨다
- ViewModel 같은 state holder가 event를 처리한다
- 새로운 state를 만든다
- UI는 그 state를 읽어 다시 그린다
Android 아키텍처 공식 문서도 UI를 상태와 state holder 관점으로 정리하는 흐름을 강조합니다.
왜 상태 버그가 줄어들기 쉬울까
상태 버그는 보통 “누가 값을 바꿨는지 모르겠다”에서 시작합니다. 화면이 직접 값을 바꾸고, callback도 값을 바꾸고, repository 응답도 또 값을 바꾸면 같은 화면 안에 변경 지점이 너무 많아집니다.
UDF는 이 변경 지점을 줄입니다. 즉 버그를 없애는 마법이 아니라, 상태 변경을 추적하기 쉽게 만드는 구조입니다.
안드로이드에서는 어떻게 느끼면 쉬울까
data class UiState(
val isLoading: Boolean = false,
val items: List<String> = emptyList(),
val errorMessage: String? = null
)
sealed interface UiEvent {
data object Load : UiEvent
data object Retry : UiEvent
}
class SampleViewModel : ViewModel() {
private val _uiState = MutableStateFlow(UiState())
val uiState: StateFlow<UiState> = _uiState
fun onEvent(event: UiEvent) {
when (event) {
UiEvent.Load, UiEvent.Retry -> loadItems()
}
}
private fun loadItems() {
_uiState.value = _uiState.value.copy(isLoading = true, errorMessage = null)
}
}이 구조에서 중요한 것은 화면이 직접 여기저기 상태를 바꾸지 않는다는 점입니다. UI는 event를 보내고, ViewModel은 state를 갱신하고, UI는 그 결과를 구독합니다.
MVVM이나 MVI와는 어떤 관계가 있을까
실무에서는 UDF가 MVI 이야기와 함께 자주 등장합니다. 하지만 UDF를 곧바로 특정 패턴 이름과 묶어버리면 오히려 이해가 더 어려워질 수 있습니다. 더 중요한 것은 화면 상태를 한 방향으로 흐르게 관리하려는 감각입니다.
즉 MVVM을 쓰더라도 UDF 감각을 살릴 수 있고, MVI는 그 감각을 더 엄격하게 밀어붙인 형태로 볼 수 있습니다.
자주 하는 실수
- UI가 state를 직접 여러 군데에서 바꾸는 것
- event, action, intent 이름만 바꾸고 실제 흐름은 여전히 뒤섞인 것
- 한 화면 상태를 여러 LiveData나 Flow로 쪼개서 전체 그림이 안 보이게 만드는 것
용어를 멋있게 맞추는 것보다 더 중요한 것은, 상태가 어디서 어떻게 바뀌는지 팀원 모두가 설명할 수 있는가입니다.
이 흐름은 MVVM vs MVI 글, 상태 저장 감각은 remember와 rememberSaveable 글과 함께 보면 더 잘 이어집니다.
마무리
안드로이드 UDF는 새로운 유행어라기보다, 상태 변경 경로를 한 방향으로 정리해서 화면 버그를 덜 복잡하게 만드는 사고방식에 가깝습니다.
즉 UDF의 핵심은 패턴 이름보다, event → state holder → new state → UI 흐름을 얼마나 일관되게 지키느냐에 있습니다.