JAVASCRIPT

자바스크립트 동작 원리

ture403 2023. 3. 5. 17:18

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90
반응형

자바스크립트 동작 원리

자바스크립트는 싱글 쓰레드 언어입니다.

이 의미는 쉽게 풀어쓰면 한 번에 한 가지 일 밖에 처리할 수 없다는 것을 의미합니다. (어려운 용어로는 Call stack이 하나라고 표현 합니다)

현재 실행하고 있는 함수가 있는 경우에 다른 일을 할 수가 없고, 다른 일들이 블락되게 됩니다. 이렇게 되면 브라우저에서 오래 걸리는 작업이 실행될 경우, 웹 페이지의 UI는 멈춰버리고, 사용자는 어떠한 행동도 할 수 없게 됩니다.

예를 들어, 크롬에서 alert 창을 띄어 보면 alert 창을 닫기 전까지는 아무것도 할 수 없는 것과 마찬가지 입니다.

1분 이상이 시간이 소요되는 오래 걸리는 작업이 있다고 가정 해보겠습니다. 자바스크립트는 머리가 하나이기 때문에, 1분 동안 아무것도 안하고 기다리면 브라우저는 아무런 행동(화면 스크롤, 버튼 클릭…)도 하지 못하게 됩니다. 그렇다면 어떻게 해야할까요? 이 때 사용하는 것이 바로 비동기 콜백입니다.

비동기 콜백을 이해하기 위해서는 JS Engine과 web API 그리고 이벤트 루프에 대한 이해가 먼저 필요합니다.

자바스크립트 코드를 실행 시켜 줘 (JS Engine)

자바스크립트 엔진은 Javascript 코드를 이해하고 실행을 도와주는 녀석입니다. 대표적인 JS engine으로 V8엔진(Chrome, Node.js에서 사용)이 있으며, 이외에도 각 브라우저 별로 여러가지 엔진들이 존재합니다. 자바스크립트 엔진은 크게 Memory Heap과 Call Stack으로 이루어져 있습니다.

Memory Heap

데이터를 임시 저장하는 곳으로, 함수나 변수, 함수를 실행할 때 사용하는 값들을 저장합니다.

Call Stack

코드가 실행되면 코드의 내부의 실행 순서를 기록해 놓고, 하나씩 순차적으로 진행할 수 있도록 도와주는 곳입니다.

자바크스립트 엔진

자바스크립트 런타임

자바스크립트 런타임

자바스크립트 런타임은 자바스크립트 엔진을 비롯해서 브라우저의 Web API들, 이벤트 루프(Event Loop), 콜백 큐(Callback Queue)으로 구성됩니다. 이제 다시 자바스크립트 엔진으로 돌아가서 콜스택(Call Stack)이 있습니다.

콜 스택 (Call Stack)

자바스크립트는 싱글 쓰레드(Single Thread) 기반 언어입니다. 이 말은 하나의 콜스택을 가지고 있다는 말인데요. 따라서 한 번에 한 가지 일 밖에 처리하지 못합니다.

콜 스택은 기본적으로 프로그램 상에서 우리가 어디에 위치하고 있는지 기록하는 자료구조(Data Structure)입니다. 어떤 함수가 실행될 때, 그 함수는 자바스크립트 엔진의 콜스택 가장 위에 쌓입니다. 그리고 함수 내부에서 return이 발생하면 호출 스택에서 사라지게 됩니다.

 

예시)

function multiply(x, y) {
	return x * y;
}

function printNumber(x) {
	var n = multiply(x, x);
	console.log(n);
}

printNumber(5);

위의 함수가 실행되는 순간에는 콜스택이 비워져 있습니다. 이후에 아래의 그림으로 단계적으로 실행됩니다.

 

콜스택 실행 순서

콜스택에 쌓이는 각각의 entry를 스택 프레임(Stack Frame)이라고 합니다.

코드를 실행하다가 오류가 발생하면, 오류가 발생한 함수가 스택의 가장 위에 쌓여 있었다는 것을 알 수 있습니다.

콜스택이 수용할 수 있는 스택 프레임의 사이즈에는 한계가 있습니다. 만약 콜스택에 스택 프레임이 꽉 차게되면 어떻게 될까요? 브라우저가 스택을 날려버리는 스택 날려 버리기 (Blowing the stack)가 일어납니다.

 

함수안에서 자기 자신을 재참조하여 호출하는 것을 재귀호출(Recursive Call)이라고 합니다.

function foo {
  foo();
}
foo();

처음에 foo 함수가 실행이되면 break가 없기 때문에 계속해서 콜스택에 스택 프레임이 쌓이게 됩니다.

결국 콜스택의 수용 한계를 넘게 되는데요. 이 때 브라우저는 스택을 날려버리고 아래와 같은 오류를 발생시킵니다.

Uncaught RangeError: Maximum call stack size exceeded

그렇다면 이러한 문제를 방지하기 위해서 매 함수의 실행이 끝나기를 기다려야 할까요? 우리는 다양한 기능을 가지면서 빠르게 동작하는 앱을 만들어야하는데 말이죠. 다행히 이러한 싱글 쓰레드 (Single Thread)의 한계를 보완해줄 방법이 있습니다. 바로 비동기 콜백(asynchronous callback)을 이용하는 것입니다.

 

이벤트 루프(Event Loop)

이벤트루프는 자바스크립트 앱 안에서 동시에 여러 가지 일이 실행되도록 핸들링 역할을 합니다.

지금 자바스크립트 앱 실행 중에 서버에서 필요한 데이터를 가지고 오는 비동기 요청이 있다고 가정해보겠습니다. 이 때 이벤트 루프는 브라우저에 이렇게 말할겁니다.

“브라우저야, 지금 이 콜백함수를 실행하면 데이터가 준비되는 시간만큼 너가 다른 일을 못하게 될테니, 네크워크 통신이 끝나고 데이터가 준비되면 그 때 내가 함수를 다시 호출(callback)할게.”

이 과정은 이벤트 루프가 콜스택(Call Stack)과 콜백 큐(Callback Queue)를 모니터링함으로써 이뤄집니다.

이벤트 루프와 콜백 큐

자바스크립트 코드 실행 중 이벤트를 만나면 콜백 큐(Callback Queue)에 순서대로 쌓입니다. 그리고 콜스택(Call Stack)이 비면, 콜백 큐(Callback Queue)에서 첫 번째 이벤트를 가지고 와서 밀어넣습니다. 이벤트 루프는 이 작업을 반복(loop)합니다.