setTimeout
setTimeout 은 정해진 시간 뒤에 콜백함수를 실행하는 자바스크립트 api다.
setTimeout(() => {
console.log('hi');
}, 1000);
위의 자바스크립트를 실행하면 1초 뒤에 콘솔에 'hi' 가 찍히는 것을 볼 수 있을 것이다.
setInterval
setInterval 은 정해진 시간 간격으로 콜백함수를 계속 실행하는 자바스크립트 api다.
setInterval(() => {
console.log('hi');
}, 1000);
위의 자바스크립트를 실행하면 1초 간격으로 콘솔에 'hi' 가 찍히게 된다.
setTimeout 으로 setInterval 만들기
setTimeout 과 setInterval 의 기본적인 차이점은 한 번 실행하느냐, 반복적으로 실행하느냐에 있다. 그런데 setTimeout 을 사용해 setInterval 처럼 동작하도록 만들 수 있다.
setTimeout(function sayHi() {
console.log('hi');
setTimeout(sayHi, 1000);
}, 1000);
위의 자바스크립트를 실행하면 1초 간격으로 콘솔에 'hi' 가 찍히게 된다. 그럼 setInterval 은 이제 쓸모가 없는건가??
setTimeout 으로 만든 가짜 setInterval 과 setInterval 의 차이
위에서 만든 setTimeout 으로 만든 1초 간격으로 hi 를 콘솔에 찍는 코드와 setInterval 을 사용해 1초 간격으로 hi 를 콘솔에 찍는 코드는 우리가 눈으로 봤을 때 차이가 거이 없다. 사실 1초라는 시간이 꽤 긴 시간이어서 그렇게 느껴지는 것일 수도 있고, 동작하는 것은 똑같이 동작하기 때문에 쉽게 알 수 없다.
만약 1000 대신 10 ms 단위로 동작하고 자바스크립트 코드가 굉장히 길다고 가정하면 둘의 차이점을 이해할 수 있을 것이다.
자바스크립트는 싱글 스레드로 동작한다. 따라서 setTimeout 이나 setInterval 과 같은 비동기 이벤트들은 현재 실행중인 이벤트가 없는 경우에 실행된다. 따라서 현재 스레드를 사용중이라면 비동기 이벤트는 이벤트 큐에 저장되게 된다. 그리고 스레드를 사용하지 않는 상태가 되면 큐에서 하나씩 꺼내 실행하게 된다.
자바 스크립트 메인 코드를 실행하는 시간이 35 ms 이고, 이 안에서 setInterval 을 사용해 10ms 간격으로 콘솔에 hi 를 찍는 경우를 생각해보자. 메인 코드가 실행되는 35 ms 동안 인터벌 내의 함수는 실행되지 못하고 이벤트 큐에 들어가게 된다. 매 10ms 마다 이벤트 큐에는 인터벌 함수가 들어가려 하는데, 아직 처음 인터벌 함수도 실행되지 않은 상태이기 때문에 이벤트 큐에 추가되지는 않는다. 이후 36 ms 에 첫 번째 인터벌이 실행되고 40 ms 에 두 번째 인터벌이 즉시 실행된다. 이렇게 되면 36 ms 에 처음 인터벌 함수가 실행되고 두 번째 실행되는 함수는 40 ms 에 실행된다. setInterval 의 경우 설정은 10 ms 로 했는데 4ms 간격을 두고 인터벌 함수가 실행될 수 있다.
setTimeout 을 사용해 만든 인터벌의 경우 일단 setTimeout 내의 함수가 실행된 후 10 ms 의 타임아웃을 다시 설정한다. 따라서 setTimeout 으로 만들 경우 우리가 설정한 시간 보다 더 빨리 실행되지 않는다는 것을 보장할 수 있다.
정리
- setInterval 에 설정한 시간은 단지 큐에 인터벌 핸들러를 추가하는 시간임
- setInterval 에 설정한 시간보다 더 작은 시간 간격으로 이벤트가 실행될 수 있음
- setTimeout 은 설정한 시간보다 더 작은 시간 간격으로는 실행되지 않음을 보장함