최근 자바스크립트의 비동기 처리와 동시성에 대해 공부를 하고 있는데, 관련 자료를 읽다 보니 “자바스크립트 런타임 환경”과 “자바스크립트 엔진”에 대한 언급이 자주 등장했다. 마침 자바스크립트 딥다이브를 공부하면서 자바스크립트 코드가 어떻게 동작하는 건지에 대한 궁금증이 생겨서, 이 둘이 자바스크립트의 동작에서 각각 무슨 역할을 하고 있는 건지 정리해 보려고 한다! 🧐
자바스크립트 엔진은 자바스크립트 코드를 해석하고 실행하는 소프트웨어를 의미한다. 브라우저나 Node.js 같은 런타임 환경 안에서 사용된다.
브라우저가 서로 다른 엔진으로 자바스크립트 코드를 실행하더라도, 같은 코드에 대해 같은 결과를 가질 수 있도록 자바스크립트 스펙을 표준화해서 ECMAScript를 정하게 되었다.
하지만 내부적인 실행 방식과 최적화 여부는 서로 다르기 때문에 브라우저마다 엔진에 따라 성능 차이가 발생할 수 있다!

엔진의 주요 구성요소로는 메모리 힙과 콜 스택이 있는데, 이 구조 안에서 코드 실행과 데이터가 관리된다.
💡 자바스크립트의 변수 식별자
우리가 변수에 값을 할당할 때, 할당하려는 값은 메모리 힙 안의 특정 위치에 저장된다. 그리고 변수는 이 값이 저장된 주소값을 가짐으로써 변수를 참조할 때 할당된 값을 반환하게 된다.
💡 실행 컨텍스트?
코드가 실행될 때 제공할 환경 정보를 갖고 있는 객체이다. 예를 들어 특정 코드 블록에서 사용 가능한 식별자 정보 등이 포함된다.
자바스크립트는 하나의 콜 스택을 갖고 있기 때문에, 한 번에 하나의 일만 할 수 있는 싱글스레드 언어인 것이다.
한 번에 하나만 할 수 있는데 자바스크립트는 어떻게 동시성을 가질 수 있을까? 런타임 환경까지 이해하고 나니 이 질문이 해소됐다.
위에서 자바스크립트 엔진이 런타임 환경 안에서 사용된다고 언급했다. 예시로 든 모든 엔진 역시 브라우저나 Node.js 안에서 동작하고 있다. 여기서 브라우저, Node.js가 런타임 환경에 해당한다.
런타임 환경은 자바스크립트 엔진이 코드를 실행할 수 있도록 추가적인 환경을 제공한다. 여기에는 이벤트 루프, 콜백 큐, (브라우저 환경의 경우) Web API 등이 포함된다.

런타임 환경에서 제공하는 이벤트 루프, 콜백 큐를 통해 자바스크립트는 비동기적으로 작업을 처리할 수 있게 된다. 비동기적으로 실행된 콜백 함수들이 콜백 큐에 들어 있다가, 선입선출 방식에 따라 콜 스택이 비어 있을 때(= 현재 다른 작업이 없을 때) 콜 스택으로 이동해서 실행되게 된다.
콜백 큐는 작업의 성격에 따라 다른 종류로 나눠져 있고(Promise, setTimeOut 등), 각자 우선순위가 다르다. 이때 콜 스택이 비어 있는지 확인하고, 현재 우선순위가 가장 높은 작업을 콜 스택으로 보내 주는 역할을 수행하는 게 이벤트 루프이다.
또한 브라우저와 Node.js는 똑같이 자바스크립트 엔진을 통해 자바스크립트를 실행시킬 수 있지만, 제공하는 환경에는 차이가 있다.
브라우저 환경에서는 Web API를 제공하고, Node.js 환경에서는 이를 사용할 수 없다. 단 Node.js 환경에서도 libuv를 통해 비동기 처리가 가능하며, Node.js는 추가로 내장 파일 시스템을 제공한다.
자바스크립트 엔진이 코드를 실행하는 방식과 런타임 환경이 이를 보조하는 구조를 알아보면서 자바스크립트의 동작 원리를 조금 더 이해할 수 있었다. 이 내용을 바탕으로 다음에는 동시성에 대한 글도 작성해 봐야겠다!
이미지 출처 How JavaScript works