Front-end/JavaScript

JS 동작원리 5편 - 런타임 (Event Loop, Callback Queue, 비동기)

파리외 개발자 2022. 11. 3. 01:07

지금까지 JS가 V8엔진을 통해 어떻게 기계어로 번역되고 실행되는지 알아봤다.

하지만 JS가 브라우저에서 동작할 때는 다른 얘기가 된다.

 

Node.js

위 사진은 노드 js의 전체 시스템 아키텍처이다.

JS를 읽고 처리하는 V8엔진은 한 부분만을 차지하고 그 외에 더 넓은 환경이 있다고 일단 이해해보자

JS문서가 어떤 명령을 내릴지에 대해 적어뒀다면

V8엔진은 JS를 해석한다.

마지막으로 런타임은 JS를 V8이 해석한 내용을 토대로 브라우저를 실질적으로 동작시키는 환경이다.

실제로 node.js 설치 페이지에 가보면 확실하게 적어뒀다.

노드 js는 자바스크립트 런타임 환경이라고

순수 JS는 언어로써 입출력을 하거나 알고리즘 문제를 푸는 등의 행동은 가능하지만 비동기 처리 등의 브라우저 환경에서의 동작을 하려면 Node.js라는 런타임 환경이 필요하다.

 

비동기 처리

JS는 기본적으로 동기적 처리 언어이다.

JS엔진 동작원리를 생각해보면 한 줄씩 콜 스택에 쌓이고 순차적으로 처리되었다.

이는 JS가 싱글 스레드(하나의 작업씩 밖에 못함)이기 때문인데,

브라우저에서 이러한 방식은 문제가 있다.

한번 개발자 콘솔에 alert를 띄워보자

해당 알림 창을 닫기 전까진 검색창이나 다른 모든 행동이 불가능해진다.

그래서 node는 웹에서 동시적 처리가 가능하게 하기 위해 비동기 처리를 지원한다.

참고로 여기서 alert는 비동기 함수가 아님

 

런타임

위 코드의 실행 순서를 생각해보자.

1, 3이 순차적으로 출력되고 1초 후 2가 출력된다.

그렇다면 setTime의 값을 0초로 설정해보자

그래도 결과는 마찬가지이다.

아무리 setTimeout이라 해도 0초면 바로 실행되어야 하는데 3 이후에 

2가 출력되는 이유는 setTimeout은 비동기로 처리가 되기 때문이다.

여기 비동기 처리가 어떻게 이루어지는지 쉽게 볼 수 있는 사이트가 있다. << 링크 클릭

콜 스택은 지난 글에서 설명했으니 넘어가겠다.

엔진이 JS파일을 읽을 때 모든 함수는 마찬가지로 콜 스택에 호출된다.

여기서 '비동기'인 함수들은 콜 스택에서 바로 처리하지 않고

Web Apis로 넘기는 것을 볼 수 있을 것이다.

비동기 함수는 정해져 있다, setTimeout, fetch, promise 등등으로 이러한 비동기 함수들은 순수 JS환경에서는 동작하지 않는다. (따로 패키지를 설치해주거나 추가 세팅을 하면 가능)

여기서 비동기인 함수들이 콜 스택에서 api로 넘어가는 동안 콜 스택은

이 비동기 함수를 콜 스택에서 지우고 다음을 호출하게 된다.

또한 setTimeout의 지정된 1초가 지나면 콜백 큐로 이동하는데

콜백 큐는 콜 스택이 모두 완료되어야 이벤트 루프에서 호출한다.

모든 비동기 처리는 api를 거쳐 콜백 큐로 이동하고 큐에 쌓인 것들은 콜 스택이 끝나기 전까지 이벤트 루프를 실행하지 않는다.
콜백 큐도 종류가 크게 세 가지 정도 있고 서로 간의 우선순위도 있지만 여기서 자세하게 다루진 않겠다.
브라우저 환경에서의 Node.js런타임으로 동작하는 JS에는 비동기 처리가 지원되고 비동기는 콜 스택의 동작이 모두 끝난 후 콜백 큐에서 재차 실행된다.