개발 공부/javascript

브라우저에서 자바스크립트의 동작 원리: Call Stack

짹뚜 2021. 12. 14. 17:49

해당 글은 모든 자바스크립트 개발자가 알아야 하는 33가지 개념에서 첫 번째인 Call Stack 항목을 공부하면서 간단하게 작성한 글이다.

자바스크립트 런타임

자바스크립트 런타임이란 자바스크립트가 구동되는 환경을 말하는데 주로 웹브라우저나 node.js를 얘기한다. 자바스크립트 런타임 안에 자바스크립트 엔진이 있고, 그중에 크롬과 node.js에서 사용하는 자바스크립트 엔진이 V8 엔진이다. V8은 자바스크립트를 바이트코드로 컴파일하고 실행한다. V8 엔진 안에 하나의 Heap과 하나의 Call Stack이 있다.

 

  • Heap(힙): 변수와 객체의 메모리 할당이 이루어지는 곳
  • Call Stack(콜 스택): 코드를 읽고 함수의 실행 순서를 기록하는 곳. 함수가 호출되면 스택의 가장 위에 함수를 넣고 (push) 해당 함수에서 return을 하게 되면 스택의 가장 위에서 꺼내게 된다 (pop).

자바스크립트를 싱글 스레드 프로그래밍 언어라고 하는데 이 말은 Call Stack이 하나만 존재한다는 뜻이다. 그러므로 한 번에 하나의 코드만 실행할 수 있다.

function foo3(){
  console.log("I am foo1");
  return;
}

function foo2(){
  foo3();
  return;
}

function foo1(){
  foo2();
  return;
}

foo1();

자바스크립트가 실행되면 Call Stack에 제일 먼저 Anonymous 즉 메인 함수가 들어가고 그다음에 호출된 foo3 함수가 들어간다. foo3 함수는 foo2 함수를 호출하기 때문에 foo2 함수가 들어가고 foo2 함수는 foo1 함수를 호출하기 때문에 foo1 함수가 들어간다.

이제 각 함수마다 retrun을 하게 되면 Call Stack 위에서부터 pop하게 된다.

 

간혹가다 재귀 함수를 구현할 때 "Maximum call stack size exceeded"와 같은 에러가 발생할 때가 있다. Call Stack에는 제한된 크기가 있는데 그 크기를 넘어가게 되면 해당 에러를 발생시킨다.

function foo1(){
  foo1();
}

foo1();

//Maximum call stack size exceeded

WEB APIs

V8 엔진을 보면 비동기적으로 실행하는 DOM, AJAX 요청, setTimeout 등 이러한 메서드들을 제공하지 않는다. 그래서 사실 자바스크립트는 비동기적으로 요청을 처리할 수가 없다. 이러한 메서드들은 자바스크립트 런타임 웹 브라우저의 Web APIs에서 제공한다. 그리고 이벤트 루프와 Callback Queue(콜백 큐)를 이용해서 자바스크립트 엔진의 Call Stack에 넣어서 비동기 요청의 결과들을 실행하게 한다.

 

Callback Queue(콜백 큐)

 

Web APIs의 비동기 요청들의 결괏값을 저장하는 공간이다. 예를 들어, setTimeout(remove, 1000)을 호출하면 Web APIs에서 타이머를 실행시키고 1초 후, Callback Queue에 remove 함수를 넣는다.

 

이벤트 루프

 

이벤트 루프가 하는 일은 단순하다. 계속해서 Call Stack과 Callback Queue를 주시해서 만약 Call Stack이 비어있다면 Callback Queue의 첫 번째 함수를 가져와서 Call Stack에 넣는다.