비동기적(Asynchronous) 이란, 먼저 실행된 코드의 작업이 끝나기 전에 더 나중에 실행된 코드의 작업이 끝날 수 있음을 말한다. 즉, 동시성을 가지고 있는 코드들을 말한다. 자바 스크립트의 V8 엔진은 싱글 스레드
를 가지고 있어서 stack을 하나 밖에 가지지 못한다. 그렇다면 자바스크립트는 싱글스레드를 가지고 있음에도 불구하고 어떻게 비동기적으로 실행되는 것일까?
자바 스크립트 엔진이 싱글 스레드를 가지고 있다는 말의 뜻을 자세히 살펴 보자. 자바스크립트 엔진은 하나의 메모리힙과 단일 호출 스택(Call Stack)을 가지고 있다. 그러므로 이 엔진 구조상으로는 한번에 하나의 함수만 동기적으로 실행이 가능한 것이다. 즉, 하나의 메인스레드에서 호출되는 함수들이 콜스택에 쌓일것이고, 이 함수들은 LIFO(Last In First Out)방식으로 실행된다. 콜스택과 싱글스레드를 연관지어 생각해보면, Javascript가 싱글스레드 기반의 언어라는 말은 Javascript가 하나의 메인스레드와 하나의 콜스택을 갖고 있기 때문이다.
그렇다면, 어떻게 비동기적으로 작동하는 것일까?
사실 자바스크립트 엔진 밖에서도 자바스크립트 실행에 관여하는 요소들이 존재한다. 각각 Web API와 Task Queue, Event Loop 이다.
위 사진과 같이, Web API 는 브라우저나 nodeJS에서 제공되는 API
이며, AJAX나 Timeout 등의 비동기 작업을 실행한다. 자바스크립트에서 setTimeout 과 같은 함수를 실행하면, 자바스크립트 엔진은 Web API에 setTimeout 을 요청하고 동시에 setTimeout에 넣어준 Callback 까지 전달한다. Callstack 에서는 Web API 요청 이후 setTimeout 작업이 완료되어 제거된다.
nodeJS 와 브라우저로 구동되는 자바스크립트의 차이점은 추후에 nodeJS 관련 글에서 자세히 밝힐 것이나 여기서 조금 다루자면,
먼저, Node.js 는 javascript 기반으로 개조하여 만들어짐.
기존에 있던 Javascript는 독립적인 언어가 아니라 스크립트 언어다. 스크립트 언어는 특정한 프로그램 안에서 동작하는 프로그램이기 때문에 웹브라우저 프로그램 안에서만 작동을 하게 된다. 즉 웹브라우저(크롬, 파이어폭스, 사파리, 익스플로러 등등) 가 없으면 사용할 수 없는 프로그램 이다.
javascript를 웹 브라우저에서 독립시킨 것으로 Node.js를 설치하게 되면 터미널프로그램(윈도우의 cmd, 맥의 terminal 등)에서 node를 입력하여 브라우져 없이 바로 실행할 수 있게 되었다. 이렇게 node.js를 이용하여 웹브라우져와 무관한 프로그램을 만들 수 있게 되었고, 중요한 것은 node.js를 이용하여 서버를 만들 수 있다는 것입니다. 중요한 이유는 이전까지 server-client 웹사이트를 만들 때 웹에서 표시되는 부분은 javascript를 사용하여 만들어야만 했으며, 서버는 ruby, java 등 다른 언어를 써서 만들어야 했는데, 마침내 한가지 언어로 전체 웹페이지를 만들 수 있게 된 것이다.
+ Node는 내장된 웹 서버가 있다. 하지만 서버 규모가 커지면 결국 nginx 등의 웹 서버를 노드 서버와 연결해야 한다.
=> 예전에는 자바스크립트 런타임이 브라우저 밖에 존재하지 않았다.
하지만 그러한 한계를 극복하고 Node.js가 나왔다.※ 런타임 : 특정 언어로 만든 프로그램들을 실행할 수 있는 환경을 뜻함.
JavaScript라면 Web Browser에서 작동하는 측면이 있고
Node.js라는 환경에서 구동되는 측면이 존재한다.
여기에서의 Browser와 Node.js를 런타임이라고 볼 수 있다.
Web API는 방금 요청받은 setTimeout을 완료하고, 동시에 전달받은 Callback 을 Task Queue라는 곳에 넘겨준다. 다음으로 Task Queue와 Event Loop 에 대해 알아보자.
Task Queue 는 Callback Queue 라고도 하는데, 큐 형태로 Web API에서 넘겨받은 Callback 함수를 저장한다. 이 Callback 함수들은 자바스크립트 엔진의 Call Stack의 모든 작업이 완료되면 순서대로 Call Stack에 추가된다. 이 때 Call Stack 가 비어있지 않은지 (실행중인 작업이 존재하는지) 와 Task Queue 에 Task가 존재하는지 를 판단하고, Task Queue 의 작업을 Call Stack 에 옮기는 일을 Event Loop가 작업한다. Event Loop 는 이 작업을 처음부터 끝까지 계속 반복하여 실행한다. 그래서 Event ‘Loop’ 인것이다.
자신이 짠 코드가 어떻게 실행되는지 보고 싶다면, http://latentflip.com/loupe 해당 사이트에 방문하여 직접 코드를 작성해보자. Call Stack, Web API, Task Queue, Event Loop 이 어떻게 상호작용 하고 작동하는지 한눈에 알 수 있도록 애니메이션으로 보여준다.
참조
글 잘 읽고 갑니다~! 그리고 대박인 사이트 알아가요 공유 감사합니다~! ^^