-
이벤트 루프 (콜 스택과 힙, 콜백 큐)JavaScript 2023. 4. 3. 22:18
JavaScript는 단일 스레드 기반 언어로, JavaScript 엔진이 단일 콜 스택을 갖는다.
비동기 요청은 어떻게 진행될까??
비동기 요청은 JavaScript 실행 환경인 브라우저, Node.js가 담당한다.
이 때 JavaScript 엔진과 실행 환경을 상호 연동시켜주는 장치가 Event Loop이다.
따라서 Event Loop는 JavaScript 엔진에 있지 않고 그 환경에 속한다.
(한번에 하나의 함수만 처리할 수 있지만 이벤트 루프에 기반한 동시성 모델을 지원한다.)
Call Stack, Callback Queue의 상태를 체크하며 Call Stack이 빈 상태가 되면 Callback Queue의 첫 번째 콜백 함수를 Call Stack에 넣는다. 이러한 행위를 반복해 루프라고 한다. 또한, 이렇게 반복적인 행동은 틱이라고 부른다.
Call Stack & Heap
JavaScript엔진이 JavaScript를 실행할 때, 원시 타입 및 참조 타입을 저장하는 메모리 구조로 Call Stack과 Heap을 가진다.
- Call Stack : 원시타입 값(기본형 데이터)과 함수 호출의 실행 컨텍스트를 저장하는 곳.
- Heap : 객체, 배열, 함수와 같이 크기가 동적으로 변할 수 있는 참조타입 값을 저장하는 곳.
- 동작 원리
- 전역 실행 컨텍스트가 생성되고 원시값은 Call Stack에, 참조값은 Heap에 저장된다.
- 함수가 실행되면 새로운 함수 실행 컨텍스트가 생성되며, 동일하게 원시값은 Call Stack, 참조값은 Heap에 저장된다.
- 함수 실행이 끝나면 함수 실행 컨텍스트는 Call Stack에서 제거된다.
- 전체 코드의 실행이 끝나고 전역 실행 컨텍스트가 Call Stack에서 제거된다. 전역 실행 컨텍스트가 제거됨에 따라 Heap의 객체를 참조하는 스택의 값이 없어 가비지 컬렉터에 의해 제거된다.
비동기 과정
- JavaScript 코드가 실행되고 함수가 호출되면, 호출된 함수는 Call Stack에 쌓인다.
- Stack의 후입선출 룰에 따라 제일 마지막에 들어온 함수가 먼저 실행되며, 실행된 함수는 Call Stack에서 제거된다.
- Stack에 쌓인 함수가 모두 실행된다.
- setTimeout같은 비동기 함수가 실행된다면, Web API가 호출되고 Call Stack에서 제거된다.
- 타이머가 종료되면 setTimeout의 콜백 함수를 Callback Queue에 넣는다.
- 이벤트 루프는 Call Stack이 빈 상태가 되면 Callback Queue에 있는 첫 번째 콜백을 Call Stack으로 이동시킨다.
Callback Queue
JavaScript의 실행 환경은 두가지 큐를 가지고 있다. 각각 스크립트 실행, 이벤트 핸들러, 콜백 함수 등의 테스크가 담기는 공간이다.
이벤트 루프는 두개의 큐를 감시하다가 콜 스택이 비어있으면 콜백 함수를 꺼내 실행한다. 이때 Microtask Queue를 우선적으로 확인한다. 만약 Microtask Queue에 콜백이 있다면, 이를 먼저 Call Stack에 담는다. Microtask Queue에 처리할 콜백 함수가 없다면 Task Queue에 확인 후 처리한다.
- Task Queue : setTimeout(), setInterval(), UI렌더링, requestAnimationFrame()이 담긴다.
- Microtask Queue : Promise(then), MutaionObserver가 담긴다.
'JavaScript' 카테고리의 다른 글
실행 컨텍스트(Execution Context) (0) 2023.04.04 이벤트 Event (이벤트 버블링, 이벤트 캡쳐링, 이벤트 위임) (0) 2023.04.03 JavaScript의 데이터 타입 (원시 타입 그리고 참조 타입) (0) 2023.03.30 var & let & const (0) 2023.03.28 JavaScript 비동기 처리(Promise, async/await) (0) 2023.03.28