JavaScirpt # Event Loop (이벤트 루프)

JohnKim·2021년 8월 14일
1

javascript

목록 보기
25/26

자바스크립트 살펴보기...

  • 자바스크립트는 단일 스레드 기반의 언어로 한순간 하나의 작업만 처리할 수 있다.

  • 자바스크립트는 비동기로 동작하기 때문에 단일 스레드에도 불구하고 동시에 많은 작업을 수행한다.

그러나

비동기로 동작하는 핵심요소는 자바스크립트 언어가 아니라 브라우저가 가지고 있다.

브라우저는 Web APIs, Event Table,Callback Queue, Event Loop 등으로 구성되며 자바스크립트 코드가 실행될 때 브라우저와의 동작은 아래 그림으로 표현할 수 있다.

JS Engine

  • 위 그림의 왼쪽 부분이 바로 js의 엔진의 형태이다.

  • 자바스크리브 엔진은 Memory Heap 과 Call Stack으로 구성되어 있다.

  • 가장 유명한 엔진은 구글의 V8 Engine이다.

  • 단일 스레드(single thread) 프로그래밍 언어라는것의 의미는 Call Stack이 하나라는 이야기다.(멀티로 처리하는것이 아닌 하나하나씩 처리한다는 의미)

    Memory Heap
    메모리 할당이 일어나는 곳 (선언한 변수, 함수 등이 담겨져 있음)

    Heap
    구조화되지 않은 넙은 메모리 영역 -> 객체(변수, 함수 등)들이 담긴다.

    Call Stack (호출 스택)
    실행될 코드의 한 줄 단위로 할당이 되는 자료구조이다.

Web APIs

비동기 처리를 담당한다.

Web API 는 브라우저에서 제공하는 API 로, DOM, Ajax, Timeout 등이 있다.

Call Stack에서 실행된 비동기 함수는 Web API를 호출하고,
Web API는 콜백함수를 Callback Queue에 밀어 넣는다.

Callback Queue (Task Queue, Event Queue 등 다얀한 형태로 설명된다)

비동기적으로 실행된 콜백함수가 보관 되는 영역이다.
예를 들어 setTimeout에서 타이머 완료 후 실행되는 함수,
addEventListener에서 click 이벤트가 발생했을 때 실행되는 함수 등이 보관된다.

Queue(큐) : 자료 구조 중 하나, 선입선출(FIFO, Frist In Frist OUT)의 룰을 따른다.

Event Loop

Queue에 할당된 함수를 순서에 맞춰 Call Stack에 할당해준다.

Event LoopCall StackCallback Queue의 상태를 체크하여,

Call Stack이 빈 상태가 되면, Callback Queue의 첫번째 콜백을 Call Stack으로 밀어넣는다.

이러한 반복적인 행동을 틱(tick) 이라 부른다.

w자바스크립트으

실행 순서 🧮

기본적인 동작 원리를 그림으로 표현하면 이렇게 표현할 수 있다.

함수를 동기 호출하게 되면 call stack에 차곡차곡 쌓여 순차적으로 실행된다.

이 때 만약에 우리가 AJAX나 setTimeout 혹은 DOM event 함수등 비동기 함수를 실행하면

자바스크립트 엔진은 call stack에서 Web APIs로 보내고 정해진 시간 혹은

이벤트가 발생한 순간에 순차적으로 callback queue에 적재한다.

callback queue에 줄을 선 함수들은 call stack에 쌓여있던 것들이 모두 제거되어 깨끗해지면

차례대로 스택에 쌓여서 실행되게 된다.

👇아래 그림으로 순서를 이해하자 👇

위 예제는 setTimeout()을 사용했을때, 어떤 식으로 동작하는지 그림으로 나타낸 것이다.

먼저 main() 함수가 실행되고, console.log(1)이 스택에 쌓인다.

console.log(1)이 실행되어 콘솔 창에 1이 출력되고 setTimeout의 콜백 함수인 cb가 스택에 쌓이는데,

setTimeout은 브라우저에 의해 제공된 API로 자바스크립트 엔진에서 처리하지 않고 바로 web APIs로 넘긴다.

그러면 브라우저는 마치 setTimeout 함수가 완료된 것처럼

스택에서 pop하고 다음 작업을 진행하므로 console.log(3)이 실행되어 콘솔 창에 3이 출력된다.

모든 코드가 실행되었으므로 main() 함수가 스택에서 제거되고,

5초 동안 대기하고 있던 cb 함수가 5초가 지난 시점에 task queue에 들어온다.

stack이 비어있으므로 cb 함수를 stack에 적재하고 console.log(2)를 실행하게 된다.


promise 가 있다면?? (feat...Microtask Queue)

console.log('script start'); 

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');

위에 예제 코드를 console로 찍어보면 순서는 다음과 같다.

script start
script end
promise1
promise2
setTimeout

promise가 setTimeout보다 먼저 실행되는이유!!

Callback Queue도 여러가지 Queue로 구성되어 있는데 promise의 then()콜백

Microtask Queue에 담기고, setTimeoutTask Queue에 담긴다.

Queue마다 Call Stack에 넣는 순서 다른데 Microtask Queue를 최우선으로 넣기 때문이다.


Callback Queue의 구성 😎

Microtask Queue

Event Loop는 stack에 처리할 작업이 없을 경우 우선적으로 microtask queue를 확인한다. microtask queue에 작업이 있다면 microtask(비동기 작업이 현재 실행되는 스크립트 바로 다음에 일어나는 작업)에 있는 작업을 꺼내서 call stack에 넣는다. 만약 microtask의 queue가 비어서 더 이상 처리할 작업이 없으면 이때 task queue를 확인한다.

Animation Frames

requestAnimationFrame API가 실행되면 콜백이 Animation Frames으로 담긴다.

task Queue

setTimeout 이나 setInterval 같은 비동기 함수의 콜백 함수, 이벤트 핸들러가 일시적으로 보관되는 영역이다.

우선순위! ✅

Microtask Queue > Animation Frames > task Queue


실제 처리 과정 확인하기 🧞‍♂️

console.log("script start");

setTimeout(function() {
  console.log("setTimeout");
}, 0);


Promise.resolve().then(function() {
  
  console.log("promise1");
  
}).then(function() {
  
  console.log("promise2");
  
});


requestAnimationFrame(function {
                      
    console.log("requestAnimationFrame");
})

console.log("script end");

👆위에 코드를 실행시키면 아래 이미지와 같은 순서로 처리가 된다.👇

console로 찍었을 때 아래와 같은 순서로 찍힌다.

script start
script end
promise1
promise2
requestAnimationFrame
setTimeout

출처

0개의 댓글