JS How JavaScript works: an overview of the engine, the runtime, and the call stack / 자바스크립트 작동방식: 엔진, 런타임, 콜스택에 대한 개요

Jungwon Lee(Jenny)·2021년 1월 27일
0
post-thumbnail

이 링크의 글을 번역했습니다.

Javascript에 대한 영어 포스팅은 처음 번역해본거라 좀 유연하지 않은 문장도있고... 영어와 한글의 문법적인 다름으로 인한 번역체? 같은 느낌도 있어서 감안하고 봐주세요....물론 혼자 보겠지만..

Overview

거의 대부분의 사람들은 이미 V8 엔진에 대해 들어봤을 것이다. 그리고 대부분의 사람들은 이미 자바스크립트가 싱글 스레드로 작동하거나 콜백 큐를 사용한다는 것을 알 것이다.

이 포스트에서, 우리는 이와 관련된 모든 개념들에 대해 공부해보고 자바스크립트가 어떻게 작동하는지 설명할 것이다. 이 주제에 대해 자세히 알면, 당신은 제공된 API들을 올바르게 활용하며 더 나은 논블로킹 app을 만들 수 있을 것이다.

만약 당신이 Javascript에 입문한지 얼마 되지 않았다면, 이 포스트를 통해 왜 Javascript가 다른 언어들에 비해 특이한지 알 수 있을 것이다.

그리고 만약 당신이 숙련된 자바스크립트 개발자라면, 늘 사용하는 자바스크립트 런타임이 실제로 어떻게 작동하는지에 대한 신선한 깨달음을 얻어 갔으면 좋겠다.

The JavaScript Engine

자바스크립트 엔진에 대한 대표적인 예로는 구글의 V8 엔진이 있다. V8 엔진은 크롬과 Node.js 내부에서 사용된다. 다음은 그 내부가 어떻게 생긴지에 대한 설명을 담은 간단한 그림이다.

자바스크립트 엔진은 두개의 주 요소로 구성된다.

  1. 메모리 힙 - 메모리 할당을 담당하는 곳
  2. 콜스택 - 코드가 실행되면서 스택으로 쌓이는 곳

The Runtime

브라우저에는 거의 대부분의 자바스크립트 개발자들이 사용해온 API들이 있다. (예를 들면 setTImeout). 하지만 이러한 API들은 자바스크립트 엔진에서 제공된 것이 아니다.

그럼, 어디서 제공된걸까 ?

실제로는 좀 더 복잡한 구조를 가지고 있다.

자바스크립트 엔진 말고도 사실 더 많은것들이 함께 돌아간다. 예를들면 브라우저에서 제공하는 Web APIs들이 있는데, 이는 DOM, AJAX, setTImeout 등등 종류가 다양하다.

그리고, 우리에겐 그 유명한 이벤트 루프와 콜백큐가 있다.

The Call Stack

자바스크립트는 싱글스레드 프로그래밍 언어로, 하나의 콜스택을 가지고 있다. 즉, 한 번에 하나의 작업만 할 수 있다.

콜스택은 현재 프로그램의 어디쯤에 있는지에 대한 모든 정보를 기록하는 데이터구조다. 함수가 실행된다면, 스택의 맨 위에 이를 push 한다. 그리고 만약 이 함수를 반환한다면, 스택의 맨 위에서 함수를 pop 한다. 이러한 단순한 작업이 바로 스택이 하는 일이다.

그럼 예시로, 다음 코드를 살펴보자

function multiply(x,y){
		return x*y;
}
function printSquare(x){
		var s = multiply(x, x);
		console.log(s);
}

printSquare(5);

자바스크립트 엔진에서 막 코드를 실행시킬 땐 콜스택은 비어있을 것이다. 이후의 단계들은 아래와 같이 흐를 것이다.

콜스택에 들어오는 각 항목을 스택 프레임이라고 부른다.

아래 예시를 하나 더 보자. 이 예시는 예외가 발생했을때의 콜스택의 상태를 보여준다.

function foo() {
	throw new Error('SessionStack will help you resolve crashes:_');
}
function bar() {
    foo();
}
function start() {
    bar();
}
start();

이 코드가 크롬에서 실행이 된다면(파일의 이름이 foo.js라고 가정해보자), 아래와같은 스택 추적이 나타날것이다.

"Blowing the stack" — 콜스택 크기의 최대치를 넘기면 발생한다. 사실 꽤나 쉽게 발생하는 상황으로, 특히 재귀를 사용하면서도 집요하게 코드를 테스트해보지 않을 때 발생한다.

아래 예시를 보자:

function foo(){
		foo();
}

foo();

이 코드가 실행되면, "foo"라는 함수를 호출하는 것부터 시작할 것이다. 그리고 이 함수는 재귀함수로, 아무런 종료 조건 없이 계속해서 자기 자신을 반복 호출할 것이다. 그러므로 실행되는 모든 단계마다 똑같은 함수가 콜스택에 쌓이고 쌓일 것이다. 아래의 그림처럼:


콜스택에 계속해서 쌓이다가 어느 순간에 도달하면, 호출된 함수의 수가 콜스택의 최대 크기를 넘게 되고, 브라우저는 아래와 같은 에러를 던져준다.


싱글스레드 환경에서 코드를 짜는 것은 멀티스레드 환경에서 발생하는 온갖 복잡한 상황들에 대처하는 것에 비해 어찌 보면 쉽다고 느낄 수도 있다. 예를 들면 멀티스레드에선 교착상태와 같은 문제들이 발생할 수 있다.

하지만 싱글스레드 환경에서의 작업도 상당히 신경 쓸 문제가 많다. 자바스크립트는 단일 콜스택을 가지고 있는데, 이 상황에서 만약 모든 것이 느리다면 어떤 문제점이 발생할까?

Concurrency & the Event Loop

만약 콜스택에 너무 많은 함수 호출이 있어서 어떤 일을 처리되기까지 어마어마한 시간이 걸린다면 어떻게 할 것인가? 예를 들면 당신이 자바스크립트로 아주 복잡한 이미지 변환을 해야 한다고 가정해보자.

당신은 이게 왜 문제가 되는거지? 라고 의문을 가질 수도 있다. 이 의문에 대한 답으로는, 콜스택에 실행할 함수들이 쌓여있다면 브라우저는 아무것도 할수없다. 한마디로 blocked 되는 것이다. 좀 더 설명하자면, 브라우저가 렌더링 할 수 없고 그 어떤 코드도 실행할수없이 그냥 꼼짝 못한다고 보면 된다. 만약 당신이 아주 유연한 UI를 당신의 app에 제공하고 싶다면 이와 같은 문제점들은 큰 영향을 끼칠 것이다.

또 다른 문제점이 있다. 당신의 브라우저가 콜스택에 있는 너무 많은 작업을 처리하게 되면, 응답시간이 오래 걸릴 수 있다. 그렇게 되면 대부분의 브라우저들은 결국 에러를 띄우게 되며, 이 웹페이지를 종료시킬 것인지 물어보는 창을 띄운다.


이게 좋은 경험은 아니겠죠?

그럼, UI를 blocking하지않으면서, 브라우저가 응답없음을 띄우지 않는 선에서 heavy code를 어떻게 실행시킬수있을까? 이에대한 해결책으로는 비동기 콜백이 있다.

이에 대한 자세한 내용은 "How Javascript actually works" 두 번째 튜토리얼에서 이어 설명할 것이다.

profile
FE개발자가 되고싶은 말하는 감자

0개의 댓글