콜 스택과 함수 호출 순서
자바스크립트 엔진이 현재 실행 중인 함수와 반환 위치를 관리하는 자료구조. 에러 메시지의 스택 트레이스는 이 콜 스택을 출력한 것이다.
Seobway · · 6분
문제 상황
c() 가 반환되면 b() 의 다음 줄로, b() 가 반환되면 a() 의 다음 줄로 실행이 돌아가야 한다.
엔진은 이 반환 위치를 콜 스택(call stack) 으로 관리한다.
function a() { b(); console.log("a 끝"); }
function b() { c(); console.log("b 끝"); }
function c() { console.log("c 실행"); }
a();
// c 실행
// b 끝
// a 끝 (호출 순서의 역순으로 종료)
호출은 a → b → c 순서로 일어나고, 종료는 c → b → a 순서로 일어난다.
동작 원리
콜 스택은 실행 중인 함수 호출을 저장하는 후입선출(LIFO) 자료구조다.
함수를 호출하면 해당 호출의 실행 컨텍스트가 스택에 push 되고,
함수가 반환되면 pop 된다.
스택 최상단의 컨텍스트가 현재 실행 중인 함수다. 자바스크립트 엔진은 하나의 스레드에서
하나의 콜 스택으로 코드를 실행하므로, 한 시점에 실행되는 함수는 하나다.
인터랙티브 다이어그램: a() → b() → c() 호출과 반환 (단계별로 재생할 수 있다)
- a() 를 호출한다. 스택 맨 아래에 push 된다.
- a 안에서 b() 를 호출한다. a 위에 push 된다.
- b 안에서 c() 를 호출한다. 최상단은 c 이고, 현재 실행 중인 함수다.
- c 가 출력 후 반환한다. 최상단에서 pop 된다.
- 최상단이 다시 b 가 된다. b 가 나머지 코드를 실행하고 반환한다.
- a 도 나머지 코드를 실행하고 반환한다. 스택이 비었다.
- 스택이 비면 이벤트 루프가 대기 중인 작업을 확인한다.
스택 트레이스
에러 발생 시 출력되는 스택 트레이스는 에러가 발생한 시점의 콜 스택을 최상단부터 나열한 것이다.
Uncaught TypeError: Cannot read properties of undefined
at c (app.js:9) (에러 발생 위치)
at b (app.js:5) (c 를 호출한 위치)
at a (app.js:1) (b 를 호출한 위치)
위에서 아래 순서로 에러 발생 지점과 그 호출자가 나온다. 디버깅할 때는 첫 줄부터 확인하고,
라이브러리 내부 프레임은 건너뛰어 직접 작성한 코드의 프레임을 찾는다.
예제
콜 스택의 크기는 제한되어 있다. 종료 조건이 없는 재귀를 실행하면 한계에 도달한다.
function depth(n = 1) {
return depth(n + 1); // 반환하지 않으므로 호출이 계속 push 된다
}
try {
depth();
} catch (e) {
console.log(e.constructor.name + ":", e.message);
}
// 최대 호출 깊이 측정
let count = 0;
function measure() {
count++;
measure();
}
try { measure(); } catch { console.log("최대 깊이 약", count);
}
최대 깊이는 엔진, 브라우저, 프레임 크기에 따라 달라진다.
자주 하는 실수
정리
콜 스택은 실행 중인 함수 호출을 저장하는 후입선출 구조이고, 자바스크립트 엔진의 메인 스레드에는
하나만 존재한다. 따라서 한 시점에 하나의 함수만 실행되며, 비동기 콜백은 스택이 빈 뒤에 실행된다.
-
a 끝이c 실행보다 나중에 출력되는 이유를 설명할 수 있다 - 스택 트레이스를 위에서 아래로 읽는 방법을 안다
-
Maximum call stack size exceeded의 의미를 안다
참고
- [1] Call stack — MDN Web Docs 용어 사전
- [2] RangeError: Maximum call stack size exceeded — MDN Web Docs
- [3] Executable Code and Execution Contexts — ECMAScript 사양
관련 글
- 실행 컨텍스트의 구성과 생성 과정 → (스택에 쌓이는 단위)
- 이벤트 루프 동작 과정 → (스택이 빈 뒤의 처리)
- javascript
- 콜스택
- 실행