콜스택 (Call Stack)

33-js-concepts를 스터디하며 정리한 포스트 입니다.

스택(Stack)이란?

스택(Stack)은 후입선출(Last In First Out, LIFO)을 기본으로하는 자료구조다.
기본적인 보통 연산은 pop, push, peek, is_empty가 존재한다.

  • pop : 스택의 출력 연산
  • push : 스택의 입력 연산
  • peek : 스택의 가장 상단의 데이터를 확인하는 연산
  • is_empty : 스택이 비어있는지 확인하는 연산

스택(Stack)의 사용 사례

  • 콜스택 (함수의 재귀호출)
  • 웹 브라우저 방문기록
  • 실행 취소 (undo)
  • 괄호 검사
  • 후위 표기법 계산

자바스크립트에서의 콜스택

자바스크립트는 하나의 스레드로 단 1개의 동시성만 다루는 언어다.
이것은 자바스크립트가 한 번에 1개의 작업만 다룰 수 있다는 뜻이다.
자바스크립트는 , 와 함께 구성하는 단일 콜스택을 갖는다.

콜스택이란?

자바스크립트 엔진이 구동되면서 실행 중인 코드를 추적하는 공간이 콜스택이다.
함수(function)의 호출(call)을 기록하는 스택(stack)자료구조다.

코드로 이해하기

아래의 간단한 코드를 이용해 Call Stack을 설명해보겠습니다.

function foo() {
  console.log('function foo is called')
  throw new Error('oops!')
}

function bar() {
  console.log('function bar is called')
  foo()
}

function baz() {
  console.log('function baz is called')
  bar()
}

baz()

아래와 같이 foo, bar, baz라는 3개의 함수를 작성했습니다.
3개의 함수는 아래와 같은 역할을 한다.

  • baz함수 : bar함수를 호출(call)
  • bar함수 : foo함수를 호출(call)
  • foo함수 : Error를 던짐(throw)

이미지로 이해하기

  1. baz함수 호출

1

baz함수가 호출되고 콜스택에 baz함수가 push된다.

  1. bar함수 호출

2

bar함수가 호출되고 콜스택에 bar함수가 push된다.

  1. foo함수 호출

3

foo함수가 호출되고 콜스택에 foo함수가 push된다.

  1. 최종 콜스택

4

모든 콜스택이 push되고 문제가 없는 경우 상단에 존재하는 함수부터
하나씩 pop되게되어 콜스택이 비어 있게 되면 해당 프로그램이 종료되는 것이다.
위의 경우 가장 상단에 있는 foo에서 오류가 발생해 프로그램이 비정상 종료된다.

콘솔로 이해하기

작성한 자바스크립트 파일을 실행시켜 보았다.

5

baz, bar, foo함수가 순서대로 호출되는 것을 확인할 수 있다.
Error가 던져진 이후의 아래의 로그를 보면 콜스택(Call Stack)을 확인할 수 있다.

6

에러가 발생한 이후의 로그를 확인해보면 위의 콜스택(Call Stack)이미지와 같이
foo, bar, baz 순서로 쌓여있는 것을 확인할 수 있다.

콜스택 오버플로우

아래와 같이 overflow함수를 재귀호출하는 코드를 작성해보았다.

function overflow() {
  overflow()
}

overflow()

실행 결과는 아래의 이미지와 같다.

7

Maximum call stack size exceeded와 같이 콜스택 사이즈가 초과되었다는 오류를 볼 수 있다.

8

콜스택의 사이즈를 초과하면 더 이상 함수를 실행할 수 없고 오류가 발생하고 종료된다.

자바스크립트 엔진이 구동되면서 번수, 함수 같은 정보를 저장하는 곳이 메모리 힙(Memory Heap)이다.

let n = 123
let s = 'string'

let o = {
  a: 1,
  b: null,
}

let a = [1, null, 'string']

function f(a) {
  return a + 2
}

위와 같이 자바스크립트 코드에서 변수, 함수를 선언하게 되면 에 저장되는 것이다.

큐는 선입선출(First In First Out, FIFO)의 특징을 갖는 자료구조다.
자바스크립트의 런타임 환경의 이벤트 큐는 처리할 메세지 목록실행할 콜백 함수들을 갖는다.
setTimeOut과 같은 비동기 함수는 Web API를 호출하며 Web API콜백 함수를 큐에 삽입한다.

setTimeOut(function() {
  console.log('First Log')
}, 0)

console.log('Second Log')

자바스크립트의 이벤트 큐이벤트 루프를 잘 모르고 위의 코드를 실행시켰다면
코드의 실행결과가 First Log, Second Log 순서대로 출력되는 것을 기대했을 것이다.

9

코드를 실행시켜보면 위와 같이 Second Log가 먼저 출력되게 된다.

10

setTimeOut함수의 2번째 인자에 0ms를 주었다고 바로 실행되는 것이 아니다.
Web API에 의해 호출된 First Log가 출력되는 콜백 함수는 이벤트 큐에 삽입된다.
이것은 0ms뒤에 함수를 실행시키라는 의미가 아니라 이벤트 큐에 삽입하라는 의미다.

11

따라서 console.log("Second Log");콜스택에 삽입 된다.

12

콜스택에 있는 모든 함수 실행이 끝나고 삭제되어 콜스택이 비어있게 된다.

13

즉 스택이 비어있는 시점에 setTimeOut함수의 콜백함수로 들어간
console.log("First Log")가 큐에서 나오며 실행되는 것이다.


Written by@Minsu Kim
Software Engineer at KakaoPay Corp.