개요
JavaScript를 공부하면서 가장 헷갈렸던 부분 중 하나는 비동기 처리였습니다.
JavaScript는 싱글 스레드로 동작한다고 배웠는데, 동시에 여러 작업을 비동기적으로 처리할 수 있다고 하니 혼란스러웠습니다.
“싱글 스레드인데 어떻게 비동기(병렬 처리)를 할 수 있을까?”
결론부터 말하자면, JavaScript에서 비동기는 병렬로 작업을 처리한다는 뜻이 아닙니다.
이 혼란은 비동기 처리의 본질을 제대로 이해하지 못한 데서 비롯됩니다.
1. JavaScript는 싱글 스레드
JavaScript는 싱글 스레드 기반 언어입니다. 즉, 한 번에 하나의 작업만 실행할 수 있습니다.
모든 JavaScript 코드는 기본적으로 메인 스레드에서 실행되며, 콜 스택(Call Stack)을 통해 하나씩 처리됩니다.
동기 작업의 실행 방식
console.log("A");
for (let i = 0; i < 1e9; i++) {} // 시간이 많이 걸리는 동기 작업
console.log("B");
위 코드는 동기적으로 실행되기 때문에, 반복문이 끝날 때까지 프로그램이 멈춥니다.
출력 결과는 다음과 같습니다:
A
B
JavaScript의 싱글 스레드 특성 때문에 반복문이 실행되는 동안 다른 작업은 대기해야 합니다.
2. JavaScript에서 비동기란?
JavaScript에서 비동기 처리는 "여러 작업을 동시에 병렬로 실행한다"는 뜻이 아닙니다.
대신 작업을 예약하고, 적절한 시점에 실행하도록 관리하는 방식입니다.
이 비동기 모델을 가능하게 하는 핵심은 이벤트 루프(Event Loop)와 태스크 큐(Task Queue)입니다.
2.1 비동기 작업은 예약을 통해 실행된다
비동기 작업은 동기 코드처럼 즉시 실행되지 않습니다.
대신 예약이 걸리고, JavaScript의 메인 스레드가 준비되었을 때 실행됩니다.
예제:
console.log("Start");
setTimeout(() => {
console.log("Timer done");
}, 2000);
console.log("End");
Start
End
Timer done
작동 방식:
- console.log("Start") → 즉시 실행.
- setTimeout 호출 → 브라우저가 타이머를 예약.
- console.log("End") → 즉시 실행.
- 타이머 완료(2초 후) → 이벤트 루프가 작업을 태스크 큐에서 가져와 실행.
이 과정에서 중요한 점은, 타이머가 완료될 때까지 JavaScript의 메인 스레드가 멈추지 않는다는 것입니다.
2.2 비동기 작업은 어떻게 예약되나?
JavaScript에서 비동기 작업은 두 가지 큐 중 하나에 예약됩니다:
- 마이크로태스크 큐(Microtask Queue):
- Promise.then, async/await 같은 작업이 등록됩니다.
- 태스크 큐보다 우선순위가 높습니다.
- 태스크 큐(Task Queue):
- setTimeout, setInterval, 이벤트 핸들러 같은 작업이 등록됩니다.
이벤트 루프는 메인 스레드(Call Stack)가 비어 있을 때, 이 큐에 있는 작업을 가져와 실행합니다.
2.3 Promise와 태스크 큐의 차이
console.log("Start");
setTimeout(() => {
console.log("Task Queue");
}, 0);
Promise.resolve().then(() => {
console.log("Microtask Queue");
});
console.log("End");
Start
End
Microtask Queue
Task Queue
이해하기:
- setTimeout은 태스크 큐에 예약.
- Promise.resolve().then은 마이크로태스크 큐에 예약.
- 동기 코드(Start, End)가 먼저 실행.
- 마이크로태스크(Microtask Queue)가 실행.
- 태스크 큐(Task Queue)가 마지막으로 실행.
3. 비동기 = 예약, 병렬 처리 ≠ 비동기
JavaScript에서 비동기는 작업을 예약하는 방식으로 동작합니다.
이는 병렬 처리(멀티스레드)가 아닌 싱글 스레드 환경에서 효율적으로 작업을 관리하는 방법입니다.
4. 정리
- JavaScript는 싱글 스레드로 동작하며, 한 번에 하나의 작업만 처리할 수 있습니다.
- 비동기 작업은 병렬 실행이 아니라, 예약을 걸고 적절한 시점에 실행되는 방식입니다.
- 이벤트 루프와 태스크 큐는 JavaScript에서 비동기 작업을 가능하게 하는 핵심 요소입니다.
- 비동기는 메인 스레드를 블로킹하지 않아 효율적이고 응답성을 높이는 설계를 제공합니다.
JavaScript에서 비동기를 이해하는 가장 좋은 방법은 이렇게 생각하는 것입니다:
“비동기 작업은 병렬 실행이 아니라, 예약된 작업을 효율적으로 관리하는 방식이다.”
'언어 > js' 카테고리의 다른 글
| JS - forEach(), reduce() (0) | 2024.07.05 |
|---|