Event Loop, Queue, MicroTask

ou·2024년 1월 19일
0

basic

목록 보기
11/24

런타임 개념

자바스크립트의 런타임 모델은 코드의 실행, 이벤트의 수집과 처리, 큐에 대기 중인 하위 작업을 처리하는 이벤트 루프에 기반함

Stack

앞서 Call stack 글로 작성함.
함수의 호출들은 '프레임' 스택을 형성

Heap

객체는 힙에 할당. 힙은 단순히 메모리의 큰 영역을 지칭하는 용어

Queue

자바스크립트 런타임은 처리할 대기열을 사용.
각각 메세지에는 처리할 함수가 연결돼있음.
대기열에서 가장 오래된 메세지부터 큐에서 꺼내 처리.(FIFO - First In First Out)
함수를 호출하면 새로운 스택 프레임 생성

함수 처리는 스택이 다시 빌 때까지 계속되며, 그 후 큐에 메세지가 남아있으면 같은 방법으로 큐가 빌 때까지 진행.

Event Loop

Run to completion

각 메세제의 처리는 다른 메세지의 처리를 시작하기 전에 완전히 끝남.

메세지를 처리할 때 너무 오래 걸리면 클릭이나 스크롤 같은 사용자 상호작용을 처리 할 수 없으며 브라우저에서는 '응답 없음' 대화 상자를 표시해 이 문제를 완화함.
최적화를 위해서 하나의 메세지를 여러 개로 나누어야 함.

setTimeout의 지연시간

setTimeout의 지연시간은 '최소' 지연 시간으로 반드시 해당 시간 뒤에 동작하는 것을 보장하지 않음.
콜스택에 이미 처리 중인 작업이 있거나 큐에 대기 중인 다른 메세지가 있다면 기다려야함.
아래 예제는 500ms 지연시간을 입력했지만 바로 실행되지 않는 예제임

const seconds = new Date().getTime() / 1000;

setTimeout(function () {
  console.log(`${new Date().getTime() / 1000 - seconds}초 후 실행됩니다.`); // "2.0199999809265137초 후 실행됩니다."
}, 500);

while (true) {
  if (new Date().getTime() / 1000 - seconds >= 2) {
    console.log("좋아요, 2초간 반복했습니다.");
    break;
  }
}

비동기 API와 try-catch

setTimeout 뿐만 아니라 다른 비동기 함수들(addEventListener, XMLHttpRequest)등 모든 비동기 방식의 API들은 이벤트 루프를 통해 콜백 함수를 실행한다.

아래 예시를 보자

document.querySelector("#btn").addEventListener("click",function(res){ // A
	try {
    	fetch(url)
        .then((res)={ //B
        
        })
    }
    catch (e){
    	console.log(e);
    }
})

순서는 아래와 같다.
1. 콜백 A가 실행될 때 fetch로 비동기 요청을 보내고 콜스택에서 제거
2. 이후 서버에서 응답 받은 브라우저는 콜백 B를 큐에 추가
3. B는 이벤트 루프에 의해 실행되며 콜 스택에 추가
4. 이때 A는 이미 콜스택에서 제거된 이후로 콜스택에는 B만 존재
5. 그러므로 A 내부의 try-catch 문의 영향을 받지 않음

이를 해결하기 위해서는 콜백 B 내부에서 try-catch를 실행해야한다.
(이렇게 해도 네트워크, 서버 에러는 잡을 수 없으므로 에러 콜백 별도로 추가 필요)

프라미스(Promise)와 이벤트 루프

여기서 마이크로 태스크라는 용어가 또 등장한다.
아래 코드를 보자

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

Promise.resolve().then(function(){
	console.log("b");
}).then(function(){
	console.log("c");
})

b->c->a 순으로 콘솔에 찍힌다.

그이유는 Promise는 마이크로 태스크를 사용하기 때문이다.
마이크로 태스크는 우리가 지금까지 계속 얘기해오던 태스크보다 더 높은 우선순위를 갖는 태스크다. 즉, 태스크 큐에 대기중인 태스크가 있더라도 마이크로 태스크가 먼저 실행된다.
자세한 내용은 이 글 참고

마이크로 태스크가 계속돼서 실행될 경우 일반 태스크인 UI 렌더링이 지연되는 경우가 바생할 수 있으므로 마이크로 태스크, 일반 태스크를 잘 구분해야할 것이다.

마치며

이제 이 gif가 이해되는가??

자바스크립트의 비동기적 특성을 잘 활용하기 위해서는 이벤트 루프를 제대로 이해하는 것이 중요하다. 이벤트 루프, 태스크 큐, 마이크로태스크 큐에 대해 알아야 최적화 할 수 있고 필요할 때 중간에 렌더링을 할 수 있을 것이다.

참고자료
https://meetup.nhncloud.com/posts/89(⭐⭐⭐)
https://ko.javascript.info/event-loop(⭐⭐)
https://chanmi-lee.github.io/articles/2020-06/JavaScript-Visualized-Event-Loop
https://velog.io/@dami/JS-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84Event-Loop-%ED%83%9C%EC%8A%A4%ED%81%AC-%ED%81%90Task-Queue

profile
경험을 현명하게 사용한다면, 어떤 일도 시간 낭비는 아니다.

0개의 댓글

관련 채용 정보