[RxJava] debounce vs throttle 함수 차이점 비교

2021. 9. 8. 22:00Android

반응형

쓸 때마다 헷갈리는 debounce, throttle...

이번 기회에 확실히 정리해 두고, 저와 같이 헷갈리시는 분들을 위해 공유합니다. 

직접 테스트도 해보니 이해 쏙쏙 

 

목차

     


    debounce 함수

    public final Observable<T> debounce(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) {
    	Objects.requireNonNull(unit, "unit is null");
    	Objects.requireNonNull(scheduler, "scheduler is null");
    	return RxJavaPlugins.onAssembly(new ObservableDebounceTimed<>(this, timeout, unit, scheduler));
    }

     

    특정 시간(위에서 timeout 값)이 지난 후 제일 마지막으로 들어온 이벤트만 발생하도록 하는 함수. (말로 설명하기가 너무 어렵다!)

     

    예시로 이해를 돕자.

    특정 시간(timeout) 값이 5초라고 가정하고 위 그림을 설명해본다.

     

    ❤️이벤트가 들어오고, 그 이후 아무런 인풋이 없는 상태로 5초가 지났다. => ❤️이벤트 발생!

    💛이벤트가 들어오고, 2초가 지날 때쯤 💚이벤트가 새로 들어왔다.

    그럼 💚가 들어온 기준으로 5초 타이머가 새로 시작한다! 그 이후 아무런 인풋이 없는 상태로 5초가 지났다. => 💚이벤트 발생!

    💙이벤트가 들어오고, 그 이후 아무런 인풋이 없는 상태로 5초가 지났다. => 💙이벤트 발생!

     

    이제 이해가 조금 되는가!

    debounce의 특징은, 타이머가 작동하고 있을 때, 새로운 이벤트가 들어오면 타이머는 리셋된다!

     


    throttle 함수 

    public final Observable<T> throttleLast(long intervalDuration, @NonNull TimeUnit unit) {
        return sample(intervalDuration, unit);
    }
        
    public final Observable<T> throttleLast(long intervalDuration, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) {
    	return sample(intervalDuration, unit, scheduler);
    }

    RxJava에서 throttle 함수는 위와 같이 2종류가 있고, 개념은 굉장히 쉽다!

    이벤트 발생이 일정 간격(intervalDuration)으로 일어난다. 그래서 위 함수를 보면 파라미터명이 intervalDuration(간격 시간)인 것!

    throttleFirst

    새로운 이벤트가 들어온 후, 일정한 시간 간격(intervalDuration) 이 지난 후에 해당 간격 중 가장 처음 들어온 이벤트를 발생시킨다. 

    https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/throttleFirst.png

     

    예시로 이해를 돕자.

    특정 시간(timeout)값이 5초라고 가정하고 위 그림을 설명해본다.

     

    ❤️이벤트가 들어오고 => ❤️이벤트 발생! 그 이후 아무런 인풋이 없는 상태로 5초가 지났다.

    💛이벤트가 들어오고 => 💛이벤트 발생! 그 후 2초가 지날때쯤 💚이벤트가 새로 들어왔다. 그 이후 3초가 지났다. (throttleFirst 이기 때문에 이후에 들어온 초록이는 무시당함)

    💠(하늘색하트가 없어서 요 아이로 대체..)이벤트가 들어오고 => 💠이벤트 발생! 그 후 3초가 지나고💙이벤트가 들어왔다. (파랑이 무시당함)

    💜이벤트가 들어오고 => 💜이벤트 발생! 

     

     

    throttleLast

    새로운 이벤트가 들어온 후, 일정한 시간 간격(intervalDuration) 이 지난 후에 해당 간격 중 가장 마지막으로 들어온 이벤트를 발생시킨다. 

    https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/throttleLast.png

     


    debounce vs throttle 비교 테스트 

    조건

    아래와 같이 0초부터 시작해서 2초 간격으로 input 스트림에 값을 넣는다. 

    즉, for 문이 다 돌면 input 에는 아래의 값이 쌓여 있을 것이다.

    => [ "0초 후", "2초 후", "4초 후", ... , "20초 후" ]

    val input = BehaviorSubject.create<String>()
    
    for (i in 0..10) {
    	val text = "${i * 2}초 후"
    	input.onNext(text)
    
    	Thread.sleep(2000L)
    }

    그리고 debounce, throttle 에서의 타이머 또는 간격 시간은 5초로 설정.

     

    debounce 결과

    호호.. 결과 심플...

       input.debounce(5000L, TimeUnit.MILLISECONDS, Schedulers.computation())
                .subscribeOn(Schedulers.computation())
                .subscribe {
                    println("LOG>> debounce result : $it")
                }

    debounce(5000L, TimeUnit.MILLISECONDS) 실행 결과

     

    20초 만 찍힌 이유는?!

    위에서 설명했듯이, debounce 는 새로운 이벤트가 들어오면 타이머를 새로 리셋하는데,
    이벤트가 들어오는 간격은 2초이고, debounce 타이머는 5초이니 이벤트가 들어올 때마다 타이머가 계속 리셋되는 것!! (아래 그림 참고)

     

    위와 같은 결과가 나온 이유를 그림으로 풀이해봤다. 👇👇

     

    throttleLast 결과

    input.throttleLast(5000L, TimeUnit.MILLISECONDS, Schedulers.computation())
                .subscribeOn(Schedulers.computation())
                .subscribe {
                    println("LOG>> throttle result : $it")
                }

    throttleLast(5000L, TimeUnit.MILLISECONDS) 실행 결과

     

    위와 같은 결과가 나온 이유를 그림으로 풀이해봤다. 👇👇

     

     

    throttleFirst 결과

    input.throttleFirst(5000L, TimeUnit.MILLISECONDS, Schedulers.computation())
                .subscribeOn(Schedulers.computation())
                .subscribe {
                    println("LOG>> throttle result : $it")
                }

    throttleFirst(5000L, TimeUnit.MILLISECONDS) 실행 결과

     


     

    간단 요약

    • debounce, throttle 함수 모두 일정 시간 동안에 발생한 마지막 이벤트를 발생시키는 개념.
    • debounce 의 경우, 새로운 이벤트가 들어올 때마다 타이머를 리셋시켜서, 이벤트가 들어온 후 특정 시간이 지났을 때 해당 이벤트를 발생시킴.
    • throttle의 경우, 이벤트가 들어온 후 일정 시간 간격마다 이벤트가 발생한다. 일정 시간 간격 동안 가장 먼저 들어온 이벤트를 발생시키거나, 가장 마지막으로 들어온 이벤트를 발생시키거나
    • TL;DR; 위에 있는 그림 설명들을 보자. 그림을 보면 깔끔하게 이해된다! 

    Reference

    http://reactivex.io/documentation/operators/debounce.html 

    http://reactivex.io/documentation/operators/debounce.html#collapseRxSwift 

    https://proandroiddev.com/throttling-in-rxjava-2-d640ea5f7bf1  

     

     

    반응형