플러터 앱 개발

Chapter 15. 효율적인 앱 개발을 위한 스로틀링과 디바운싱

yuna 2026. 1. 29. 19:34

01. 스로틀링과 디바운싱이란?

스로틀링

오래 사용하면 발열, 전력 과소모 등으로 인해 노트북이 갑자기 느려짐

-> 스로틀링을 통해서 성능을 일부러 제한

  • 시스템을 보호하거나 안전성을 위해 일부러 속도를 낮추는 제어
  • 특정 시간 간격 내에서 이벤트가 여러 번 발생하더라도, 그 중 한 번만 실행되도록 하는 기능

예시 상황

  • 스크롤 이벤트 너무 자주 발생
  • 일정 간격마다만 처리
class ThrottleExample extends StatefulWidget {
  @override
  _ThrottleExampleState createState() => _ThrottleExampleState();
}

class _ThrottleExampleState extends State<ThrottleExample> {
  DateTime _lastRun = DateTime.now();

  void _onScroll() {
    final now = DateTime.now();

    if (now.difference(_lastRun) < const Duration(milliseconds: 200)) {
      return;
    }

    _lastRun = now;
    print('스크롤 위치 계산');
  }

  @override
  Widget build(BuildContext context) {
    return NotificationListener<ScrollNotification>(
      onNotification: (notification) {
        _onScroll();
        return true;
      },
      child: ListView.builder(
        itemCount: 100,
        itemBuilder: (_, index) => ListTile(
          title: Text('Item $index'),
        ),
      ),
    );
  }
}

 

 

디바운싱

짧은 시간에 여러 번 발생하는 이벤트를 마지막 한 번만 처리하는 기법

 

동작 방식

  1. 이벤트 발생
  2. 타이머 시작
  3. 그 안에 또 이벤트 발생
    1. 이전 타이머 취소
    2. 새 타이머 시작
  4. 이벤트가 더 이상 안 오면 실행

 

예시 상황

  • TextField에 타이핑할 때마다 API 호출 x
  • 입력이 멈춘 뒤 한 번만 호출 o
import 'dart:async';
import 'package:flutter/material.dart';

class DebounceExample extends StatefulWidget {
  @override
  _DebounceExampleState createState() => _DebounceExampleState();
}

class _DebounceExampleState extends State<DebounceExample> {
  Timer? _debounce;

  void _onSearchChanged(String query) {
    // 이전 타이머 취소
    _debounce?.cancel();

    // 새 타이머 시작
    _debounce = Timer(const Duration(milliseconds: 300), () {
      print('검색 API 호출: $query');
      // fetchSearchResult(query);
    });
  }

  @override
  void dispose() {
    _debounce?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextField(
      onChanged: _onSearchChanged,
      decoration: const InputDecoration(
        hintText: '검색어 입력',
      ),
    );
  }
}