너네는 setInterval 같은거 하지마라

kshired·2021년 7월 29일
2
post-thumbnail

주의! : 이번 글은 제목부터 어그로성이 다분합니다🤦‍♂️

이 글을 쓰게 된 이유는, 주기적으로 어떤 작업을 해야하는 상황에서 setInterval이 좋은 선택인지에 대해 얘기해보기위해서입니다.

setInterval(callback,ms)

  • 일정한 시간 간격(ms)으로 callback을 수행할 때 사용합니다.
  • clearInterval() 을 사용하여 중지합니다.

setTimeout(callback,ms)

  • 일정한 시간(ms) 후에 callback을 실행합니다.
  • clearTimeout() 을 사용하여 작업을 중지합니다.

문제가 없어보이지만, setInterval에선 맹점이 하나 있습니다.

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval#delay_restrictions

위 문서의 Delay restrictions 에서도 언급하고 있듯이, setInterval은 다른 interval이 running 되고 있는 동안에도 또 다른 setInterval의 callback이 호출 될 수 있습니다.

이게 뭐가 문제냐하면..

어떤 A라는 작업을 setInterval을 이용하여 반복하고 싶은데, 이 A라는 작업이 지정해놓은 interval보다 오래 걸리면 선행 작업이 끝나지도 않은채 또 다른 A작업을 시작하게 된다는 것입니다.

이렇게 되면 생각지도 못한 side effect가 일어날 수 있고

개발자는 A가 순차적으로 끝난 뒤 반복 되는 줄 알았는데..
그냥 끝나지도 않은 채 반복해버리니 이게 무슨 상황인가 당황하게 되버릴겁니다.

이걸 어떻게 해결할까요?

setTimeout을 재귀적으로 호출하여 사용자 정의 setInterval을 선언하면 됩니다.

setTimeout은 일단 지정해놓은 시간만큼 대기 후 작업을 진행하기 때문에, 재귀적으로 호출하게 되면 setInterval과 달리 선행 작업이 끝나고 interval만큼 기다린 뒤에 실행되게 됩니다.

그래서 이걸 어떻게 구현할까요?

아래와 같은 패턴을 사용하여 mySetInterval이라는 함수를 정의하면 됩니다.

const mySetInterval = () => {
  setTimeout(() => {
    A();
    mySetInterval();
  }, delay);
};

이렇게 되면, 아래와 같은 순서로 실행이 됩니다.

delay 만큼 대기 -> A 작업 실행 및 종료 -> mySetInterval이 재귀로 실행 -> delay 만큼 대기 -> ... 반복

이렇게 setTimeout을 재귀적으로 구현함으로써, setInterval이 가지고 있는 문제를 해결 할 수 있었습니다.

결론

사실 이 문제는 직접 어떤 것을 개발하다가 직접 겪게 되어서 정리할김에 적어본 글입니다.

글의 제목이 어그로성이 짙어서 조금 그럴 수도 있지만, 많은 분들께 도움이 되었으면 좋겠습니다 😄

아 그리고, 만약 A라는 작업을 선행 작업이 끝나던 말던 상관없이 interval 마다 실행하고 싶다면 setInterval을 사용해야겠죠?

참고

profile
글 쓰는 개발자

0개의 댓글