가치투자자

[JS/기술면접] 타이머와 디바운스 및 스로틀 본문

Programming/JavaScript

[JS/기술면접] 타이머와 디바운스 및 스로틀

미주민 2023. 4. 23. 15:00
728x90
반응형

* 기술면접 질문은 맨 아래에 적혀 있습니다

 

 타이머 

1. 호출 스케쥴링

일정 시간이 지난 이후에 함수를 호출하도록 하고 싶다. 이때 사용하는 함수가  타이머 함수 이며, 함수를 명시적으로 호출하지 않고 일정 시간이 지난 후에 호출하도록 함수 호출을 예약하는 것을  호출 스케쥴링 (scheduling a call) 이라 한다.

 

이러한 호출 스케쥴링을 구현하는 타이머 함수에는 setTimeoutsetInterval이 있다.

 

728x90

2. 타이머 함수

1) setTimeout / clearTimeout

먼저,  setTimeout 함수 특정 시간(delay)이 지난 후에 콜백함수 func를 1번 실행한다.

이때 특정 시간은 ms(1/1000초) 단위로 적어줘야 하며, 적지 않을 경우 기본값으로 0이 할당된다.

delay 뒤에 추가적인 인자도 넣을 수 있다. 이러한 인자들은 IE9 이하에선 지원되지 않으니 참고하도록 하자.

setTimeout(func, delay, param1, param2, ...);

 

아래의 예시를 살펴보자.

예시를 보면, 1초 뒤에 sayHi 함수를 실행하며, 따라서 1초 뒤에 "안녕하세요"라는 알람을 띄워준다.

이때 꼭 함수명인 sayHi라고 문자열을 넣어줘야 한다. 만약 sayHi()로 넣어주게 되면 sayHi 함수의 결과값을 반환한다.

근데 sayHi 안에는 return이 없기에 결과는 undefined가 되어 setTimeout이 제대로 작동하지 않는다.

function sayHi() {
  alert('안녕하세요.');
}

setTimeout(sayHi, 1000);

 

위의 경우엔 따로 함수 코드를 짜고 setTimeout 함수의 1번째 인자로 넣어줬다.

그렇지 않고 아래처럼 화살표 함수로 함수를 넣어줄 수도 있다.

setTimeout(() => alert('안녕하세요.'), 1000);

 

인자를 받는 경우도 살펴보자.

아래처럼 2개의 인자를 넣어주면 차례대로 sayHi()에 들어간다. 단, 인자를 넘겨줄 경우 콜백 함수의 인자 개수와 동일해야 한다. 

function sayHi(who, phrase) {
  alert( who + ' 님, ' + phrase );
}

setTimeout(sayHi, 1000, "홍길동", "안녕하세요."); // 홍길동 님, 안녕하세요.

 


 

이렇게 setTimeout이 호출되면, 이 타이머를 식별할 수 있는 고유한 타이머 id를 부여한다.

아래 코드처럼 setTimeout  함수를 timeId 변수에 할당해주고 호출해보면 타이머 id에 어떤 값이 부여되었는지 알 수 있다.

let timerId = setTimeout(() => alert("아무런 일도 일어나지 않습니다."), 1000);
alert(timerId); // 타이머 식별자

아래 실행 결과를 보면, 타이머 id에 숫자 1이 타이머 id로 부여된 것을 알 수 있다.

브라우저 환경에선 숫자이지만, Node.js 환경이라면 객체가 id에 부여된다.

 

 

이렇게 생선된 타이머 id를 통해 setTimeout 함수의 타이머를 취소할 수 있다.

원래라면 1초 뒤에 콘솔창에 "Hi!"가 찍혀야 하지만,  clearTimeout 함수 를 통해 setTimeout의 타이머를 취소했다. 이때 clearTimeout 함수는 타이머 id를 받아와 타이머를 취소한다.

const timeId = setTimeout(() => console.log('Hi!'), 1000);
clearTimeout(timeId);

 

 


2) setInterval / clearInterval

다음으로,  setInterval 함수 는 특정 시간(delay)이 지날 때마다 콜백함수 func를 반복적으로 실행한다.

setTimeout 함수와 문법은 동일하다. 특정 시간은 ms(1/1000초) 단위로 적어줘야 하며, 적지 않을 경우 기본값으로 0이 할당된다.

delay 뒤에 추가적인 인자도 넣을 수 있다. 이러한 인자들은 IE9 이하에선 지원되지 않으니 참고하도록 하자.

setInterval(func, delay, param1, param2, ...);

 

이러한 setInterval 함수의 실행을 중단하려면  clearInterval 함수 로 타이머 id 값을 받아와야 한다.

 

아래의 예시를 살펴보자.

"째깍"이라는 알람이 2초 간격으로 발생하다가 5초 이후로는 더 이상 알람이 발생하지 않는다.

// 2초 간격으로 메시지를 보여줌
let timerId = setInterval(() => alert('째깍'), 2000);

// 5초 후에 정지
setTimeout(() => { clearInterval(timerId); alert('정지'); }, 5000);

 

 


3. 디바운스와 스로틀

scroll, resize, input, mousemove 같은 이벤트들은 짧은 시간 간격으로 연속적으로 발생한다. 이러한 이벤트에 바인딩된 이벤트 핸들러는 과도하게 호출되어 성능 문제를 일으킬 수 있다. 이러한 문제를 해결하기 위해 짧은 시간 간격으로 연속해서 발생하는 이벤트를 그룹화해서 과도한 이벤트 핸들러 호출을 방지하는 프로그래밍 기법인 디바운스와 쓰로틀이 있다.

 

1) 디바운스

 디바운스 (debounce) 짧은 시간 간격으로 발생하는 이벤트를 그룹화하여 이벤트 핸들러를 호출(call)하지 않다가 일정 시간이 경과된 후에 한 번만 호출하도록 하는 기법이다.

 

 

아래 예시를 살펴보자.

사용자가 입력창(input 태그)에 값을 연속으로 입력하면 이벤트가 발생한다. 그러나 과도한 호출을 막기 위해 debounce 함수는 0.3초 이전에는 이벤트를 발생시키지 않다가 그 이후에 이벤트 핸들러를 한 번만 호출한다.

 

이러한 디바운스는 resize 이벤트 처리나 input 요소에 입력된 값으로 ajax 요청하는 입력 필드 자동완성 UI 구현, 버튼 중복 클릭 방지 처리 등에 유용하게 사용된다.

<!DOCTYPE html>
<html>
  <body>
    <input type="text" />
    <div class="msg"></div>
    <script>
      const $input = document.querySelector("input");
      const $msg = document.querySelector(".msg");

      const debounce = (callback, delay) => {
        let timerId;
        
        return (event) => {
          if (timerId) clearTimeout(timerId);
          timerId = setTimeout(callback, delay, event);
        };
      };
      
      $input.oninput = debounce((e) => {
        $msg.textContent = e.target.value;
      }, 300);
    </script>
  </body>
</html>

 

 


2) 스로틀

 스로틀 (throttle) 짧은 시간 간격으로 발생하는 이벤트를 그룹화하여 일정 시간 간격으로 이벤트 핸들러가 호출되도록 하는 기법이다.

 

 

scroll 이벤트 예시를 살펴보자.

스크롤을 내릴 때마다 이벤트가 발생하면 엄청난 과부하에 걸릴 것이다. 이를 방지 하기 위해 1초마다 이벤트를 발생하도록 하고 그 이전에는 이벤트가 발생하지 않도록 해준다.

 

이러한 스로틀은 scroll 이벤트 처리나 무한 스크롤(infinite scrolling) UI 구현 등에 유용하게 사용된다.

<!DOCTYPE html>
<html>
  <head>
    <style>
      .container {
        width: 300px;
        height: 300px;
        background-color: rebeccapurple;
        overflow: scroll;
      }

      .content {
        width: 300px;
        height: 1000vh;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="content"></div>
    </div>
    <div>
      일반 이벤트 핸들러가 scroll 이벤트를 처리한 횟수:
      <span class="normal-count">0</span>
    </div>
    <div>
      쓰로틀 이벤트 핸들러가 scroll 이벤트를 처리한 횟수:
      <span class="throttle-count">0</span>
    </div>

    <script>
      const $container = document.querySelector(".container");
      const $normalCount = document.querySelector(".normal-count");
      const $throttleCount = document.querySelector(".throttle-count");

      const throttle = (callback, delay) => {
        let timerId;
        
        return (event) => {
          if (timerId) return;
          timerId = setTimeout(
            () => {
              callback(event);
              timerId = null;
            },
            delay,
            event
          );
        };
      };

      let normalCount = 0;
      $container.addEventListener("scroll", () => {
        $normalCount.textContent = ++normalCount;
      });

      let throttleCount = 0;
      $container.addEventListener(
        "scroll",
        throttle(() => {
          $throttleCount.textContent = ++throttleCount;
        }, 1000)
      );
    </script>
  </body>
</html>

 

반응형

 


🌟 자바스크립트 기술면접 질문

1. 호출 스케쥴링이 무엇인가요?

 

  • 함수를 명시적으로 호출하지 않고, 일정 시간이 지난 후에 호출하도록 함수 호출을 예약하는 것을 호출 스케쥴링이라 하며, 이때 사용하는 함수가 타이머 함수다.

 

2. 타이머 함수에는 어떤 것들이 있나요? 🔥

 

  1. setTimeout 함수

    - 일정 시간이 지난 이후에 콜백함수를 1번 실행해주는 함수이며, 지연 시간은 ms 단위로 적어준다.

    - 이러한 setTimeout 함수가 실행되면 고유한 타이머 id를 갖는데, 이 타이머 id를 clearTimeout 함수가 인자로 받아와 setTimeout 함수의 실행을 취소할 수 있다.

  2. setInterval 함수

    - 일정 시간마다 반복적으로 콜백 함수를 실행해주는 함수이며, 이 반복 시간은 ms 단위로 적어준다.

    - 이러한 setInterval 함수가 실행되면 고유한 타이머 id를 갖고, 이 타이머 id를 clearInterval 함수가 인자로 받아와 setInterval 함수의 반복적 실행을 멈출 수 있다.

 

3. 이벤트가 과도하게 호출되어 성능에 문제를 일으킬 경우에 할 수 있는 어떤 일을 통해 해결할 수 있나요?

 

  • 디바운스와 쓰로틀 기법을 사용해 짧은 시간 간격으로 발생하는 이벤트를 그룹화하여 문제를 해결할 수 있다.

 

4. 디바운스에 대해서 알고 있나요?

 

  • 짧은 시간 간격으로 발생하는 이벤트를 그룹화하여 이벤트 핸들러를 호출(call)하지 않다가 일정 시간이 경과된 후에 한 번만 호출하도록 하는 기법

 

5. 쓰로틀에 대해서 알고 있나요?

 

  • 짧은 시간 간격으로 발생하는 이벤트를 그룹화하여 일정 시간 간격으로 이벤트 핸들러가 호출되도록 하는 기법

 


</> 끊임없이 성장하기 위해 공부한 내용을 글로 작성하고 있습니다. 틀린 부분이나 추가해야 할 부분이 있다면 언제든 댓글로 남겨주세요❗️

 


References

 

 

728x90
반응형