JavaScript는 단일 스레드(single-threaded) 언어로, 한 번에 하나의 작업만 처리할 수 있습니다. 그렇다면 비동기(asynchronous) 코드가 어떻게 가능한 것일까요? 그것이 바로 JavaScript의 Event Loop 때문입니다.
비동기 자바스크립트 소개
JavaScript는 웹에서 가장 널리 사용되는 언어 중 하나입니다. 이는 대부분의 웹 브라우저에 내장되어 있으며, 서버 사이드 개발(Node.js)까지도 가능하게 합니다. JavaScript는 동기(synchronous) 코드와 비동기(asynchronous) 코드를 모두 지원합니다.
동기 코드는 순차적으로 실행되며, 각 작업이 완료될 때까지 다음 작업은 대기 상태에 있습니다. 이와 반대로 비동기 코드는 작업이 완료되기를 기다리지 않고 다음 작업으로 진행합니다.
console.log('First');
setTimeout(() => {
console.log('Second');
}, 0);
console.log('Third');
위 코드를 실행하면 'First', 'Third', 'Second' 순서로 출력됩니다. **setTimeout**이 0초로 설정되어 있음에도 불구하고 'Second'는 마지막에 출력되는데, 이는 Event Loop의 동작 방식 때문입니다.
호출 스택과 이벤트 큐
JavaScript에서 함수 호출은 Call Stack에 쌓입니다. Call Stack은 LIFO(Last In First Out) 방식으로 동작하며, 가장 나중에 들어온 작업이 가장 먼저 처리됩니다. Call Stack이 비워질 때까지 동기 코드는 계속 실행됩니다.
비동기 함수는 Event Queue로 이동합니다. 이벤트 루프는 Call Stack이 비어 있을 때 Event Queue의 작업을 Call Stack으로 이동시킵니다.
function firstFunction() {
console.log('First');
}
function secondFunction() {
setTimeout(() => {
console.log('Second');
}, 0);
}
function thirdFunction() {
console.log('Third');
}
firstFunction();
secondFunction();
thirdFunction();
위 코드는 이전과 동일한 결과를 출력하지만, 함수가 어떻게 Call Stack과 Event Queue를 통해 이동하는지 더 잘 보여줍니다.
이벤트 루프는 어떻게 작동하나요?
Event Loop는 JavaScript 엔진에서 가장 중요한 역할 중 하나를 담당합니다. Event Loop의 주된 역할은 Call Stack이 비어 있을 때 Event Queue에서 작업을 가져와 Call Stack으로 이동시키는 것입니다. 이로 인해 JavaScript는 비동기 코드를 처리할 수 있습니다.
Event Loop는 항상 Call Stack과 Event Queue를 모니터링하며, Call Stack이 비어 있을 때 Event Queue에서 작업을 가져옵니다. Event Queue에서 작업이 가져와지면 해당 작업은 Call Stack에서 실행되고, 작업이 완료되면 Call Stack에서 제거됩니다. 이 과정은 계속 반복되며, 이것이 바로 '루프(loop)'라는 이름이 붙은 이유입니다.
console.log('First');
setTimeout(() => {
console.log('Inside setTimeout');
}, 0);
console.log('Second');
위 코드에서 **console.log('First')**와 **console.log('Second')**는 동기 작업으로, 호출 순서대로 Call Stack에 쌓입니다. setTimeout 함수는 비동기 작업이므로 Event Queue에 추가되고, Call Stack이 비어 있을 때 실행됩니다. 그래서 'First', 'Second', 'Inside setTimeout' 순서로 출력됩니다.
Microtask Queue and Macrotask Queue
JavaScript에서는 두 가지 유형의 이벤트 큐가 있습니다: Microtask Queue와 Macrotask Queue.
- Macrotask Queue에는 setTimeout, setInterval, setImmediate 등의 작업이 포함됩니다.
- Microtask Queue에는 Promise, MutationObserver 등의 작업이 포함됩니다.
Event Loop는 각 반복마다 Macrotask Queue에서 하나의 작업을 처리하고, 모든 Microtask를 처리합니다. 즉, 하나의 Macrotask가 처리된 후 모든 Microtask가 처리되기 전까지는 다른 Macrotask가 처리되지 않습니다.
console.log('First');
setTimeout(() => {
console.log('Inside setTimeout');
}, 0);
Promise.resolve().then(() => console.log('Inside Promise'));
console.log('Second');
위 코드에서 'First', 'Second', 'Inside Promise', 'Inside setTimeout' 순서로 출력됩니다. **Promise**가 Microtask Queue에 있기 때문에 **setTimeout**보다 먼저 처리됩니다.
마지막으로..
JavaScript의 Event Loop는 비동기 코드를 가능하게 하는 핵심 메커니즘입니다. 이를 이해하면 JavaScript의 동작 방식을 더 잘 이해할 수 있으며, 비동기 코드를 더 효과적으로 작성할 수 있습니다. Event Loop는 JavaScript의 복잡성과 힘을 동시에 보여주는 좋은 예입니다.
'CS > 기타' 카테고리의 다른 글
실제로 내가 사용 중인 VSCode 확장 프로그램 (0) | 2024.03.25 |
---|---|
CSS 애니메이션과 JavaScript 애니메이션의 차이점 (1) | 2023.07.26 |
서버(Server)란 무엇일까? (0) | 2023.05.01 |
자바스크립트(Javascript) 비동기의 역사 (0) | 2023.04.06 |
CSS 애니메이션과 Javascript 애니메이션의 차이? (0) | 2023.04.06 |