• Javascript: 타이머는 어떻게 동작하는가? :: 마이구미
    Javascript 2018. 4. 30. 00:16
    반응형

    이 글은 자바스크립트 내부에서setTimeout, setInterval 과 같은 타이머들의 동작을 알아본다.

    타이머들은 비동기로 처리되는데 이와 관련된 싱글 스레드, 비동기 처리등과 같은 또한 얻을 수 있을 것이다.

    참고 자료 - https://johnresig.com/blog/how-javascript-timers-work/


    글의 주제는 두 가지 의문을 가지고 글을 진행할 것이다.


    첫번째 의문은 다음과 같다.


    자바스크립트에서 타이머 관련 함수는 2가지로 볼 수 있다.


    • setTimeout() -  일정 시간 뒤에 함수가 실행된다. * ms(1000분의 1초)
    • setInterval() - 일정 시간마다 함수가 실행된다.


    즉, 지연시간(delay)을 조작할 수 있다.

    하지만 100ms 후 실행을 원하는 함수가 있을 때, 정확한 시간인 100ms 를 보장하지는 않는다.


    두번째 의문은 다음과 같다.


    setTimeout(function(){ /* Some long block of code... */ setTimeout(arguments.callee, 10); }, 10); setInterval(function(){ /* Some long block of code... */ }, 10);


    위 2가지는 기능으로는 같아보이지만, 내부적으로는 다르게 동작한다.




    기본적으로 자바스크립트는 싱글 스레드를 통해 동작한다는 사실을 알고 있을 것이다.

    위의 의문점을 해결하기 위해서는 자바스크립트의 싱글 스레드를 이해해야한다.

    싱글 스레드는 단순히 동시에 할 수 있는 일은 오로지 하나밖에 못한다고 보면 된다.

    비동기 이벤트에 대한 흐름의 다이어그램은 다음과 같다.


    비동기 처리


    위 그림은 각 블록으로 나눈 형태로, 각 블록은 실행되는 영역을 의미한다.

    예를 들면 첫번째 블록은 자바스크립트가 약 18ms 동안 실행되었고, 두번째는 마우스 이벤트 실행이 약 11ms 동안 실행되었다.

    위에서 아래방향으로 실행된다고 보면된다.

    Javascript 블록에서 상황의 순서는 다음과 같다.


    1. setTimeout 타이머가 설정되었다.
    2. 마우스 클릭 이벤트가 발생했다.
    3. setInterval 타이머가 설정되었다.
    4. 타이머가 실행되었다.


    현재 상황에서 실행되는 건 Mouse Event 와 setTimeout 이 실행된다.

    하지만 실제로는 즉시 실행되지 않고 큐에 넣어 대기하게 된다.  

    이유는 아직 Javascript 블록의 실행이 끝나지 않았기 때문에 다른 처리를 할 수 없다. (싱글 스레드)


    이벤트 큐


    그 후 Javascript 블록이 끝이 나면, 내부에서는 큐에서 대기하는 처리가 있는지 확인한다.

    이 부분이 Mouse Click Callback 블록전에 있는 "What's waiting?" 을 의미한다.

    그 후 큐에서 가져온 후, Mouse Click Callback 블록이 생기게 되고 Timer(setTimeout) 은 여전히 가능한 시간까지 대기하게 된다.


    Mouse Click Callback 블록에서 1번째 Interval 콜백이 발생하는 것을 볼 수 있다.

    아직 처리중이기 때문에 이 또한 큐에서 대기하게 된다.


    이벤트 큐


    Mouse Click Callback 블록이 끝이 나면, 큐에서 Timer 를 가져온다.

    Timer 블록에서 2번째 Interval 콜백이 발생했지만, Timer 핸들러가 실행되고 있기 때문에 처리되지않고 드랍된다,

    반대로 Timer 블록이 끝난 후, Interval 블록에서 3번째 Interval 콜백이 발생했을 때는 드랍되지 않고 그대로 처리되는 모습을 볼 수 있다.

    즉, Interval 의 경우에는 이전 콜백 실행 여부와 상관없이 10ms 마다 실행을 시도한다.
    반대로 Timer 는 실행되고 있는 이전 콜백이 완료를 기다린 후에 10ms 이후에 실행을 시도한다.


    2번째 Interval 블록이 끝이 나면, 실행되는 블록과 큐에는 아무것도 없기 때문에 빈 공백을 볼 수 있다.

    그로 인해 50ms 에 발생되는 Interval 콜백은 즉시 실행되는 모습을 볼 수 있다.



    이러한 흐름을 통해 두번째 의문의 답을 추측할 수 있다.

    setTimeout 은 항상 이전의 콜백의 실행 후로부터 지연시간을 갖게 된다.

    setInterval 은 이전 콜백 실행 여부와 상관없이 항상 지연시간마다 실행하려고 시도한다.


    결론적으로 요약한 결과는 다음과 같다.

    • 자바스크립트 엔진은 오직 싱글 스레드만을 가짐으로써, 비동기 이벤트들을 큐에 대기하게 한다.
    • setTimeout 과 setInterval 은 근본적으로 다르게 실행된다.
    • setTimeout 과 setInterval 은 즉시 실행될 수 없는 상황이라면, 실행 가능할 때까지 지연돼서 시간을 보장할 수 없다.
    • Interval 의 경우 실행주기가 지연시간보다 길다면, 지연없이 연속적으로 실행을 보장할 수 있다.


    반응형

    댓글

Designed by Tistory.