back

Posts

클로저와 함께하는 디바운스 & 쓰로틀링

2025-02-12

프론트엔드 면접을 준비하면 클로저, 디바운스, 쓰로틀링은 자주 접하게 됩니다. 꼭 면접 준비가 아니더라도 개발을 하다 보면 위 개념들은 필수적으로 접하게 되는데요.

디바운스와 쓰로틀링에 클로저가 사용된다는 걸 아셨나요?

저는 부끄럽게도 최근 lodash 라이브러리를 직접 구현하던 중 이 사실을 깨달았습니다.

1. 클로저 (Closure)

클로저는 함수가 나중에 호출되더라도 선언 당시의 외부 변수나 상태를 접근할 수 있는 기능입니다.

즉, 외부 변수나 상태는 내부 함수가 참조하고 있는 동안에는 메모리에 남아 있습니다.

예시

function createCounter() {
  let count = 0; // 외부 함수의 지역 변수

  return () => {
    count += 1; // 외부 변수 count에 접근
    console.log(`Count: ${count}`);
  };
}

const counter = createCounter();

counter(); // Count: 1
counter(); // Count: 2
counter(); // Count: 3

동작 원리

  1. counter 변수가 생성되면서 createCounter() 함수가 실행됩니다
  2. createCounter() 함수는 종료되었지만, 내부 함수가 count를 참조하고 있습니다
  3. 따라서 count는 가비지 컬렉션 대상이 아니며, 메모리에 계속 유지됩니다
  4. counter()를 호출할 때마다 같은 count 변수에 접근합니다

2. 디바운스 (Debounce)

디바운스는 동일 이벤트가 여러 번 발생하더라도 일정 시간이 지난 후에 마지막 이벤트만 실행하는 기능입니다.

사용 예시

  • 검색창에서 입력이 끝난 후 API 호출
  • 윈도우 리사이즈 이벤트 처리

구현

const debounce = (func: Function, delay: number) => {
  let timer: NodeJS.Timeout;

  return (...args: any[]) => {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => func(...args), delay);
  };
};

클로저가 사용되는 부분

debounce 함수의 매개변수로 받은 funcdelaysetTimeout에 등록하고, 이를 timer 변수에 할당합니다.

만약 delay 전에 이벤트가 또 발생하면 기존의 timeout을 clear하고 다시 등록하는 것이죠.

클로저 동작:

  • debounce 함수가 실행된 후 내부 함수가 반환됩니다
  • 내부 함수는 timer 변수를 계속 참조하고 있습니다
  • 따라서 timer는 메모리에 유지되며, 여러 번 호출되어도 같은 timer를 사용합니다

이 구조, 위에서 봤던 클로저 예시와 동일하죠?

3. 쓰로틀링 (Throttling)

쓰로틀링은 이벤트 발생 후 일정 시간 동안 동일 이벤트를 무시하는 기능입니다.

사용 예시

  • 스크롤 이벤트 처리
  • 버튼 연속 클릭 방지

디바운스와의 차이

항목디바운스쓰로틀링
동작마지막 이벤트만 실행일정 간격으로 실행
사용 예시검색창 자동완성스크롤 이벤트

구현

const throttle = (func: Function, limit: number) => {
  let lastCall = 0;

  return (...args: any[]) => {
    const now = Date.now();
    if (now - lastCall >= limit) {
      lastCall = now;
      func(...args);
    }
  };
};

클로저가 사용되는 부분

쓰로틀링에서도 lastCall 변수를 계속 참조하고 있습니다.

클로저 동작:

  • throttle 함수가 실행된 후 내부 함수가 반환됩니다
  • 내부 함수는 lastCall 변수를 계속 참조하고 있습니다
  • limit이 지난 후 다시 실행해도 이전의 lastCall 값에 접근할 수 있습니다

정리

디바운스와 쓰로틀링은 모두 클로저를 활용한 패턴입니다:

개념핵심 메커니즘클로저 활용
클로저외부 변수 참조 유지-
디바운스타이머 리셋timer 변수를 클로저로 유지
쓰로틀링시간 간격 체크lastCall 변수를 클로저로 유지

확실히 이론적으로 외우는 것보다 실제 사용하는 코드로 접근하니 더 이해가 잘 되는 것 같습니다!