Throttling과 Debounce

💡이벤트 처리와 관련 된 개념인 Throtting과 Debounce에 대하여 학습한 내용을 기록하였습니다.

 

개요

  • Throttling와 Debounce는 자주 사용 되는 이벤트나 함수들의 실행되는 빈도를 줄여서 효율적인 성능 개선을 가져오기 위한 개념입니다.
  • 검색 시 자동 완성 기능에 주로 활용되며, keyboard가 한자씩 입력될 때마다 API로 데이터를 가져오게 되면 사용자의 의도와 무관하게 많은 요청이 발생합니다.
  • 이를 줄이기 위해서 특정 단위마다 api 값을 가져오도록 요청할 수 있는데, 이러한 방식이 Throttling과 Debounce에서 활용됩니다.

두 방법 모두 사용자 인터페이스에서 빠르게 발생하는 이벤트를 제어하고 불필요한 처리를 줄이기 위한 방법이지만, 처리 방식에 차이가 있습니다.

Throttling

  • 지정된 시간 간격 동안 이벤트가 발생하더라도 최대 한 번만 이벤트를 처리하는 방식입니다.
  • 특정 시간 동안 이벤트가 여러 번 발생해도 가장 최근 이벤트나 첫 번째 이벤트만 처리되고, 그 시간 내의 나머지 이벤트는 무시됩니다.

Throttling 예시

  • 특정 시간 간격동안 최대 한 번만 실행하게 하며, delay(300)을 통해 0.3초마다 함수를 반복해서 호출하지만 실제로는 1초에 한 번만 실행하게 됩니다.
import kotlinx.coroutines.*

fun throttle(wait: Long, function: () -> Unit): () -> Unit {
    var lastCallTime = 0L
    return {
        val currentTime = System.currentTimeMillis()
        if (currentTime - lastCallTime >= wait) {
            lastCallTime = currentTime
            function()
        }
    }
}

fun main() = runBlocking {
    val throttledFunction = throttle(1000L) {  // 1초에 한 번만 호출됨
        println("Throttled function executed at ${System.currentTimeMillis()}")
    }

    repeat(5) {
        throttledFunction()  // 반복해서 호출해도 1초에 한 번만 실행
        delay(300L)  // 0.3초마다 호출 시도
    }
}

Debouncing

  • 디바운싱은 이벤트가 끝난 후 일정 시간이 지나면 이벤트를 처리하는 방식입니다.
  • 이벤트가 계속 발생하더라도 아무 작업도 진행하지 않다가, 이벤트가 더 이상 발생하지 않으면 그때 마지막으로 발생한 이벤트를 처리합니다.
  • 디바운싱은 가장 최신으로 실행된 이벤트를 실행하게 합니다.

Debouncing 예시

  • 특정 delay가 지나도 아무런 동작이 없을 때 가장 최신 작업을 수행합니다.
  • delayMillis 동안 이벤트가 계속 발생하면 이전 작업을 취소하고, 시간이 지나면 마지막으로 호출된 함수를 실행합니다.
import kotlinx.coroutines.*

fun debounceCoroutine(delayMillis: Long, function: () -> Unit): () -> Unit {
    var debounceJob: Job? = null

    return {
        debounceJob?.cancel()  // 이전 코루틴 취소
        debounceJob = CoroutineScope(Dispatchers.Main).launch {
            delay(delayMillis)  // 딜레이
            function()  // 함수 실행
        }
    }
}

// 사용 예시: 입력이 끝난 후 1초 후에 이벤트 처리
val debouncedInputCoroutine = debounceCoroutine(1000L) {
    println("입력 완료 후 1초 후에 처리")
}

// 입력 필드의 텍스트 변경 리스너에 넣으면 입력이 끝난 후 1초 후에 이벤트가 처리됩니다.
editText.addTextChangedListener {
    debouncedInputCoroutine()
}

정리

  • Throttling은 일정 시간 간격 동안 이벤트가 여러 번 발생해도 최대 한 번만 이벤트를 처리합니다.
    • 스크롤 이벤트를 정기적으로 처리하는 데 사용됩니다.
  • Debounce는 이벤트가 연속적으로 발생하는 동안은 무시하고, 이벤트가 끝난 후 일정 시간이 지나면 한 번만 처리합니다.
    • 사용자 입력이 끝난 후 API 호출을 하는 데 사용됩니다.
  • 두 방법은 이벤트 발생 빈도를 줄이고, 불필요한 작업을 피하면서 성능 최적화에 유용합니다.

참고

https://velog.io/@eassy/Throttling과-Debouncing