JavaScript is an single-threded, non-blocking, asynchronous, and concurrent language.
Node.js is an asynchronous and event-driven JavaScript runtime environment.
JavaScript Engine
- 자바스크립트 실행 환경[ JavaScript Runtime Envrironment: ex) Browser, Node.js ]은 특성상 비동기 처리에 적합하게 설계되었습니다.
- 아래의 그림은 자바스크립트 엔진의 작동 원리와 그 구조를 한 눈에 파악할 수 있도록 만든 이미지입니다.
자바스크립트 엔진은 다음의 몇 가지 요소로 구성되어 있습니다.
Heap : 변수, 함수, 객체 등이 실제 저장되는 물리적 메모리 공간입니다. 자바스크립트에서는 한번 할당되었던 메모리가 C나 C++처럼 수동적으로 해제되는 것이 아니라, Garbage Collector에 의해 자동으로 할당 해제됩니다.
Stack: 함수와 API 호출이 저장되는 곳입니다. 자료 구조적으로 전형적인 stack구조(LIFO)를 가지는데, 최근 호출된 함수일 수록 stack의 상단에 위치하게 되고 함수 실행을 마치면 stack으로 부터 제거됩니다.
API: 실제 비동기 처리로 작동되는 함수들입니다. 대표적인 것으로는 setTimeout()
와 fetch()
등이 있습니다. 이 API 함수들은 호출과 동시에 call stack을 거쳐 바로 배후의 비동기처리 영역(background)으로 이동되고 그 곳에서 실행을 계속하게 됩니다. 즉 동기적 처리가 지속되는 동안에도 비동기 처리는 계속 진행되는 것입니다.
Callback Queue: 일반적으로 비동기 처리의 완료 여부는 API함수의 전달 인자인 callback 함수의 실행 완료 여부로 확인이 됩니다. 따라서 callback 함수들은 callback queue에서 call stack이 비워지기를 기다렸다가 실행이 되며, 자료 구조적으로 전형적인 queue구조(FIFO)를 가지고 있습니다.
Event Loop: call stack이 비워졌는지, 그리고 callback queue에 실행해야할 callback 함수가 남아 있는지 지속적으로 확인합니다. 그리고 call stack이 비워지게 되면 queue에서 첫 번째 callback함수를 stack에 밀어 올립니다.
자료 출처: Javascript and Asynchronous Magic — Explaining the JS Engine and Event Loop