자바스크립트는 v8엔진을 기반으로 작동한다.
v8엔진은 call stack
과 heap
으로 구성되어 있으며 v8엔진과 런타임(런타임은 프로그래밍 언어가 구동되는 환경이다. 즉 어떤 프로그램이 동작할 때, 프로그램이 동작하는 장소)이 만나 이벤트 루프가 작동한다.
자바스크립트는 Node 나 웹 브라우저와 같은 멀티 쓰레딩이 가능한 환경에서 실행된다.
따라서 "자바스크립트 (엔진)"은 싱글 스레드이지만, "자바스크립트를 실행하는 런타임" 은 완벽한 싱글 스레드가 아니라고 할 수 있다.
node는 javascript를 구동하는 하나의 프로그램이고 멀티쓰레드를 지원하는 libuv 라는 라이브러리
를 사용한다. (IOCP, epoll, select를 이용하는것으로 보아 멀티 플렉싱을 사용하는듯 함. (쓰레드 풀))
결론적으로 node는 이벤트 루프역할을 하는 메인 쓰레드와 Thread pool 이 돌아가는 형태이다.
node도 그렇고 javaScript엔진도 c++ 기반이니 멀티쓰레드를 지원하는 언어이다. 다만 싱글쓰레드로 돌아가도록 구현이 되어있고 런타임환경이 멀티쓰레드를 지원하므로
싱글쓰레드이지만 비동기프로그래밍으로 작성이 가능하다. 물론 지원하는 런타임 환경에서 구동해야 한다.
Task queue | Micortask queue |
---|---|
setTimeout() | Promise |
setInterval() | MutationObserver |
UI 렌더링 | |
requestAnimaionFrame() |
FIFO 선입선출
)console.log("시작"); setTimeout(function(){ console.log("3초후 실행"); }, 3000); console.log("끝")
- 전역 컨텍스트 main() 함수가 Call Stack에 쌓이고 console.log(“시작”) 이
Call Stack
에 쌓인다. “시작”이 콘솔에 찍힌다.- console.log(“시작”) 이 리턴되며
Call Stack
에서 제거된다.- setTimeout함수가 실행되면서
Call Stack
에 setTimeout함수가 들어간다.- setTimeout함수는 자바스크립트 엔진이 처리하지않고
Web API
가 처리하므로 Callback함수를 전달하고, setTimeout작업을 요청한다. (비동기 함수는 런타임 환경에서 구동하도록 전달해준다.)Call Stack
에서는 setTimeout작업이 제거된다.- console.log(“끝”) 이 호출되어
Call Stack
에 쌓인다. “끝”이 콘솔에 찍힌다.- console.log(“끝”) 이 리턴되며
Call Stack
에서 제거된다.- main() 함수가 리턴되며
Call Stack
에서 제거된다.- Web API는 setTimeout 작업을 실행한다. 3초를 센 후
Callback Queue의 Task Queue
로Callback 함수를
보낸다.- Event Loop는 Call Stack을 참조하고 있다가
Call Stack
이 비어있으면Callback Queue의 Task Queue
에서 함수를하나씩
꺼내Call Stack
에 넣고 실행한다.- console.log(“3초후 실행”) 이 호출되고
Call Stack
에 쌓인다. “3초후 실행”이 콘솔에 찍힌다.- console.log(“3초후 실행”) 이 리턴되고
Call Stack
에서 제거된다. Event Loop는Callback Queue
에 콜백 함수가 들어올 때까지 계속 대기한다.
setTimeout(()=>{console.log("4")})
setTimeout(()=>{console.log("5")})
console.log("1")
console.log("2")
결과는 아래와 같다.
4
5
1
2
console.log('콜 스택!');
setTimeout(() => console.log('태스크 큐!'), 0);
Promise.resolve().then(() => console.log('마이크로태스크 큐!'));
결과는 아래와 같다
콜 스택!
마이크로태스크 큐!
태스크 큐!
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');
script start
script end
promise1
promise2
setTimeout
V8 엔진에서 코드가 실행되면, Call Stack에 쌓인다.
Stack의 선입후출의 룰에 따라 제일 마지막에 들어온 함수가 먼저 실행되며,
Stack에 쌓여진 함수가 모두 실행된다.
비동기함수가 실행된다면, Web API가 호출된다.
Web API는 비동기함수의 콜백함수를 Callback Queue에 밀어넣는다.
Event Loop는 Call Stack이 빈 상태가 되면
Callback Queue에 있는 첫번째 콜백을 Call Stack으로 이동시킨다.
(이러한 반복적인 행동을 틱(tick)이라 한다.)
필립 로버츠의 event loop관련 설명
https://www.youtube.com/watch?v=8aGhZQkoFbQ
https://velog.io/@thms200/Event-Loop-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84