Weekly Flutter

함수의 실행을 제한하자. Debounce와 Throttle

ssuncake 2023. 8. 17. 15:13

이번에 무한 스크롤이 있는 검색페이지를 만들게 되었다.
그런데, 가끔씩 스크롤을 내리다 보면 페이지를 여러개 가져와버리고, 검색편의성을 위해 넣은 자동완성은 쓸데없이 많은 api요청으로 트래픽을 증가시킨다.

 

그래서 비용을 조금이라도 아껴보고자 debounce와 throttle개념을 이용해보기로 했다.

 

성능을 향상시키거나 비용을 줄이고 싶은 경우에 debounce와 throttle이라는 개념을 이용해서 사용자의 의도와 상관없이 반복적으로 실행되는 함수의 실행 빈도를 제어를 할 수 있다.

 

개념

Debounce와 Throttle은 특정 함수의 실행을 제한하는데 목적을 두고 있다.

  • Debounce는 특정기간동안 추가로 실행되지 않으면 함수를 실행한다.
  • Throttle은 함수를 실행 하고 특정 기간동안추가실행을 모두 취소한다.

아래 사이트에서 원을 옮겨보면 더 쉽게 이해 할 수 있다.

https://rxmarbles.com/#debounce

https://rxmarbles.com/#throttle

 

개념적으로

Throttle은 함수를 일단 실행하고 특정기간내에 추가 실행되는 경우 실행하지 않지만,

Debounce는 함수의 실행이 특정기간 내에 계속해서 이루어지는 경우 실행시점이 미뤄지는 점이 Throttle과는 다른점이다.

 

Dart 패키지 소개

dart 패키지로는 아래의 패키지 혹은 rxdart 등에서 제공을 한다. 코드량이 많지 않기에 직접 만들어서 사용해도 무방할듯 하다.

 

https://pub.dev/packages/debounce_throttle

 

debounce_throttle | Dart Package

A debouncer and throttle that works with Futures, Streams, and callbacks.

pub.dev

 

Debouncer 사용법

    final _debouncer =
        Debouncer<String>(const Duration(milliseconds: 200), initialValue: '');

    textEditingController
        .addListener(() => _debouncer.value = textEditingController.text);
        
    _debouncer.values.listen((search) => submitSearch(search));

 

Throttle 사용법

  final throttle = Throttle<double>(Duration(milliseconds: 100));

  sensor.addListener(throttle.setValue);
  
  throttle.values.listen((data) => print('$data'));

 

Tick은 시간을 의미하고, changed는 변화의 유무, 각 변화마다 함수의 실행결과가 D, T 이다.

 

debounce_throttle 패키지의 경우 Throttle이 위에서 살펴본 개념과는 살짝 다르게 마지막에 한번 더 실행을 하도록 동작한다. 실 사용에 맞춰서 변형된것이 아닐까 싶다.

 

어떤 상황에 어떻게 써야할까?

앱에서는 무한 스크롤, 버튼 클릭, 자동완성 기능 등에서 debounce나 throttle 을 적용 할 수 있다.

 

자동 완성 기능을 예로들면 키보드 타이핑시에 onChanged 이벤트에 따라 요청이 여러번 들어가게 되는데 모든 요청이 필요하지 않을 수 있다.

 '김치찌개' 라는 단어의 입력 타이핑으로 살펴보자면 각 글자의 타이핑 마다 키보드의 종류에 따라 다르겠지만 -일반적으로 기능의 도움없이 모든 글자를 키보드를 쳐서 입력한다고 하면- 김치찌개는 'ㄱ', 'ㅣ', 'ㅁ', 'ㅊ', 'ㅣ', 'ㅉ', 'ㅣ', 'ㄱ', 'ㅐ' 최소 9번의 onChanged 이벤트가 발생한다. 

keyboard의 onChanged마다 자동완성 api를 요청하면 9번의 요청이 발생하는데 사용자는 '김치찌개' 라는 단어에 대한 자동완성결과는 9번 모두 필요 하지 않을 수 있다. 

 

debounce를 적용한다면, 김치찌개 타이핑을 특정시간 이내에 모두(극단적) 할 경우 9번의 api요청을 1번으로 줄일 수 있다.

하지만 일단 한번 함수를 실행하고, 중간 중간에도 실행 결과를 보여주고 싶다면 Throttle을 적용 할 수 있을 것 같다.