FrontEnd/ES&JS 문법

[Javascript] 이벤트 루프와 태스크 큐

기은P 2022. 10. 18. 15:23
반응형

1. Javascript 이벤트 루프 

자바스크립트는 기본적으로 싱글 스레드로 한번에 하나의 작업만 할 수 있는 특징이 있습니다.

  • One thread == one call stack == one thing at a time

Call stack(호출 스택)은 우리가 어떤 순서로 작업을 수행하는지 기록하는 작업 스케쥴링과 관련된 도구입니다.

특정 함수를 실행하면 그 함수를 호출 스택의 맨 위에 놓는데 이것을 push 과정이라고 합니다.

만약에 함수가 어떤 값을 리턴하거나 실행을 종료하면, 호출 스택 맨 위에서 그 함수를 꺼내는데 이 과정을 pop이라고 합니다.

이와 같은 코드가 있으면 스택에 순서대로

  • main() -> printSquare() -> square() -> multiply()로 push가 되고,

pop은 함수의 실행이 종료되었을 때 그 함수를 꺼내는 것이니까

  • multiply() -> square() -> console.log() -> printSquare() -> main()과 같은 과정으로 pop이 됩니다.

* console.log도 함수입니다.

 

이런 식으로 콜 스택에 재귀적인 호출이 일어나 함수가 계속 쌓이게 되면 Maximum call stack size exceeded라는 에러메세지를 발생시킵니다.

 

 

2. 비동기 콜백

또한 간단한 프로그램이라면 상관 없지만, 복잡한 프로그램을 구동한다고 하고 시간이 매우 오래걸리는 작업이 스택에 쌓이고 실행될 경우, 그 다음 작업은 무한정 대기하게 되는데, 이 경우를 블로킹(blocking)이라고 합니다.

 

이것이 문제가 되는 이유는, 블록킹이 발생할 경우 브라우저가 다른 일을 할 수가 없기 때문에 조작이 불가능해지기 때문입니다.

이러한 문제를 해결하기 위한 해결 방안이 비동기 콜백(Asynchronous Callbacks)입니다.

자바스크립트가 싱글 스레드임에도 불구하고 웹사이트에서 여러 작업을 할 수 있도록 지원해주는 것이 브라우저가 Web APIs 같은 것들을 제공해 비동기 작업을 가능하게 해주기 때문입니다!

 

자바스크립트 내부에는 callstack이 있는데, ajaxsetTimeout, dom event 함수와 같은 비동기 함수pop 과정을 거쳐 실행하게 되면, 자바스크립트 엔진은 call stack에서 web APIs(브라우저)로 함수를 보내고 정해진 시간 혹은 이벤트가 발생한 순간에 순차적으로 Callback Queue라는 곳에 적재합니다.

 

Callback queue에 적재된 함수들은 jscall stack에 쌓여있던 것들이 모두 제거되었을 때 차례대로 스택에 쌓여서 실행되게 됩니다. 이것을 이벤트 루프라고 합니다.

->이후 콜백 큐태스크 큐라고 정정합니다. HTML 표준 스택에서 task queue로 표기하기 때문입니다.

 

 

3. 태스크 큐와 마이크로태스크 큐

일반적인 동작과정은 위에서 설명한 것과 같은데, 세부적으로는 태스크 큐마이크로 태스크 큐, 2개의 큐로 나누게 되고 이는 Promise 동작 방식과 연관이 있습니다.

또한 자세한 내용으로 태스크큐와 마이크로태스크 큐 모두 제일 오래된 태스크에 우선순위를 주어 태스크를 꺼내는 우선순위 큐(priority Queue)로 동작합니다.

 

태스크큐에 들어가는 콜백함수들

  • setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI 렌더링

마이크로태스크큐에 들어가는 콜백함수들

  • Process.nextTick, promise, object.observe, MutationObserver

이벤트 루프는 이와 같은 2개의 큐에서 콜백함수를 꺼내야하는데, 순서는 마이크로태스크 큐가 태스크 큐보다 우선순위를 가지고 있습니다!

 

console.log('콜 스택!');
setTimeout(() => console.log('태스크 큐!'), 0);
Promise.resolve().then(() => console.log('마이크로태스크 큐!'));
 
->
콜 스택!
마이크로태스크 큐!
태스크 큐!

 

따라서 비동기 로직을 다룰 때 콜백 함수를 사용하게 될 경우, 이러한 우선순위를 예측하여 코드를 작성해야 합니다.

 

 

반응형