안드로이드

Kotlin Flow에서의 Debounce와 Throttle 기법

Zibro 2025. 3. 25. 22:25
728x90
반응형

Kotlin에서는 Flow를 활용하여 비동기적으로 이벤트를 처리할 수 있으며, 이벤트가 지나치게 자주 발생하는 경우 이를 제어하는 다양한 기법이 필요합니다. 

Debounce Throttle은 이러한 상황에서 유용하게 사용되는 기법으로, 불필요한 작업을 줄이고 성능을 최적화하는 데 큰 도움이 됩니다.

본 글에서는 이 두 기법의 개념과 이를 Kotlin Flow에서 어떻게 적용할 수 있는지에 대해 살펴보겠습니다.

 

1. Debounce와 Throttle 기법이란?

Debounce

Debounce는 연속된 이벤트 중 마지막 이벤트만 실행되도록 처리하는 기법입니다.

일정 시간 동안 추가적인 이벤트가 발생하지 않으면, 그때서야 마지막 이벤트를 처리하게 됩니다.

즉, 빠르게 발생하는 여러 이벤트 중에서 마지막 이벤트를 처리하고자 할 때 유용합니다.

사전적 의미📚

Debounce는 "반동을 없애다" 또는 "충격을 완화하다"라는 의미를 가지며, 과도한 반복적인 반응을 없애기 위한 방식입니다.

주요 사용 사례👉🏻

  • 검색 자동완성: 사용자가 검색어를 입력할 때마다 서버 요청을 보내는 대신, 입력이 멈춘 후 마지막 검색어만 서버로 보내 불필요한 요청을 방지합니다.
  • 실시간 입력 처리: 실시간 유효성 검사나 필터링에서, 입력이 끝날 때까지 기다린 후 최종적으로 처리합니다.

Throttle

Throttle은 이벤트가 일정 시간 간격으로만 실행되도록 제한하는 기법입니다.

이벤트가 자주 발생하더라도 지정된 시간 간격마다 한 번만 처리되며, 그 사이의 이벤트는 무시됩니다.

사전적 의미📚

Throttle은 "조절하다" 또는 "속도를 늦추다"라는 의미를 가지며, 흐름의 속도를 제한하는 방식입니다.

주요 사용 사례👉🏻

  • 버튼 클릭 방지: 버튼을 너무 자주 클릭하는 것을 방지할 때, 일정 시간 간격으로 한 번만 처리합니다.
  • 스크롤 최적화: 스크롤 이벤트가 자주 발생할 수 있지만, 일정 간격으로만 이벤트를 처리하여 성능을 최적화합니다.

 

반응형

2. Kotlin Flow에서 Debounce와 Throttle 구현하기

Kotlin의 Flow에서는 debounce와 throttle을 쉽게 구현할 수 있습니다. 우선 debounce부터 살펴보겠습니다.

Debounce 구현 예시

Kotlin의 Flow에서 제공하는 debounce 함수는 연속적인 이벤트 중 마지막 이벤트만 처리하는 기능을 제공합니다.

예를 들어, 검색창에서 사용자가 타이핑을 할 때마다 서버에 요청을 보내는 경우, debounce를 사용하여 입력이 끝날 때만 서버에 요청을 보낼 수 있습니다.

Debounce 예시 코드

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking {
    val searchFlow = MutableSharedFlow<String>() // 입력 이벤트 스트림

    // debounce(500): 500ms 동안 추가 입력이 없으면 마지막 입력만 처리
    searchFlow
        .debounce(500) 
        .collect { query ->
            println("서버 요청: 검색어 = $query")
        }

    // 사용자가 빠르게 입력하는 시뮬레이션
    launch {
        listOf("코", "코틀", "코틀린").forEach {
            searchFlow.emit(it)
            delay(200) // 빠르게 입력되는 상황
        }
    }
}

 

  • debounce(500): 이 코드에서는 사용자가 "코", "코틀", "코틀린"을 빠르게 입력한다고 가정합니다. debounce는 입력 후 500ms 동안 추가 입력이 없으면 마지막 입력인 "코틀린"만 처리합니다.
  • emit: MutableSharedFlow를 사용해 이벤트를 방출하고, 이를 debounce로 처리합니다.

Throttle 구현 예시

Throttle은 일정 시간 간격마다 이벤트가 실행되도록 제한합니다.

예를 들어, 사용자가 버튼을 빠르게 클릭할 때, 한 번만 처리되도록 Throttle을 적용 할 수 있습니다.

Throttle 예시 코드

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

fun main() = runBlocking {
    val clickFlow = MutableSharedFlow<Unit>()

    // throttleFirst(1000): 1000ms마다 한 번만 실행
    clickFlow
        .throttleFirst(1000)
        .collect {
            println("버튼 클릭 이벤트 처리!")
        }

    // 사용자가 빠르게 클릭하는 시뮬레이션
    launch {
        repeat(5) {
            clickFlow.emit(Unit)
            delay(300) // 사용자가 빠르게 클릭하는 상황
        }
    }
}

// throttleFirst 확장 함수 구현
fun <T> Flow<T>.throttleFirst(windowDuration: Long): Flow<T> = flow {
    var lastTime = 0L
    collect { value ->
        val currentTime = System.currentTimeMillis()
        if (currentTime - lastTime >= windowDuration) {
            lastTime = currentTime
            emit(value)
        }
    }
}

 

  • throttleFirst(1000): 이 코드에서는 사용자가 300ms 간격으로 버튼을 클릭하지만, throttleFirst(1000)을 적용하여 1000ms마다 한 번만 처리됩니다.
  • throttleFirst 확장 함수는 이벤트가 발생한 시점에서 windowDuration만큼 간격을 두고 실행하도록 합니다.
728x90

 

 

본 글을 통해 Kotlin Flow에서 Debounce Throttle 기법을 쉽게 이해하고, 실제 프로젝트에서 어떻게 활용할 수 있는지 알게 되기를 바랍니다.

부족한 글 읽어주셔서 감사합니다.

 

728x90
반응형