이거 어디까지 쌓이는 거에요?

Haizel·2023년 11월 15일
1
post-thumbnail

재귀함수란 특정 조건이 만족할 때까지 자기 자신을 호출하는 함수를 말한다. 재귀함수는 특정 조건을 만족할 때까지 계속 호출하기 때문에 반드시 탈출 조건이 필요한데, 만약 재귀 함수가 자기자신을 계속 호출하고 또 호출하고, 또 호출한다면, 어떤일이 일어날까?

이 글은 JavaScript 알고리즘 & 자료구조 마스터클래스를 참고하여 작성되었습니다.

📚 Call Stack

자바스크립트 엔진은 메모리 힙(Memory Heap)과 호출 스택(Call Stack), 이렇게 두 가지 구성 요소로 이루어져 있다.

메모리 힙(Memory Heap)
변수와 객체에 대한 모든 메모리 할당이 발생한다.

호출 스택(Call Stack)
코드가 실행될 때, 즉 호출된 함수가 이곳에 쌓인다. Stack은 선입후출(FILO, Firsr In Last Out) 구조로, 맨 마지막으로 들어온 데이터가 가장 먼저 나가게 된다.

즉 함수를 호출하면 호출한 순서대로 Call Stack에 쌓이게 되는데, 맨 위에 쌓인 함수부터 제거되어 가장 마지막에 있는 함수는 모든 함수가 반환(Return)될 때까지 기다렸다가 가장 마지막에 제거된다.

예시코드를 크롬 콘솔창에 디버깅하여 Call Stack이 어떻게 쌓이고 제거되는지 직접 살펴보자!

🔎 Practice

여기 아침 직장인의 모습을 담은 예시 코드가 있다.

맨 처음 wakeUp 함수를 호출하면 takeShower 함수가 호출되고 리턴되어 제거된다. 그 후 eatBreakfast 함수를 호출하는데, 해당 함수 내부에서 cookFood 함수를 호출하고 있다. 그 후 마지막으로 console.log가 출력되며 wakeUp 함수가 제거된다.

그럼 Call Stack엔 어떻게 쌓이고 제거되는지 확인해보자.

function takeShower() {
    return "Showering!"
}

function eatBreakfast() {
    let meal = cookFood();
    return `Eating ${meal}`
}

function cookFood() {
    let items = ["Oatmeal", "Eggs", "Protein Shake"]
    return items[Math.floor(Math.random()*items.length)];
}
function wakeUp() {
    takeShower();
    eatBreakfast();
    console.log("Ok ready to go to work!")
}

wakeUp();

1. wakeUp 함수

Line20에 중단점을 추가하고 wakeUp 함수를 호출하면 Call stack에 wakeUp 함수가 추가된다.

2. takeShower 함수

그 후 아직 wakeUp 함수가 완료(return)되지 않았기 때문에 Call Stack에 제거되지 않고 다음 함수인 takeShower가 호출되어 Call stack에 추가된다.

takeShower 함수가 값을 return하면,

함수가 종료되었기 때문에 Call stack에서 takeShower 함수가 제거된다.

3.eatBreakfast 함수

wakeUp 함수는 그대로 Call stack에 있는 채로 다음 함수인 eatBreakfast 함수가 호출된다.

eatBreakfast 함수 내부에서 cookFood 함수를 호출하고 있으므로 Call stack에 cookFood 함수가 추가된다.
이때 wakeUpeatBreakfast 는 아직 완료(return)되지 않았기 때문에 Call stack에 남아 있다.

4. cookFood 함수

cookFood는 값을 리턴하고 Call stack에서 제거된다.

3. eatBreakfast 함수

cookFood에서 전달받은 값을 리턴한 후, 완료되어 eatBreakfast함수는 Call stack에서 제거된다.

1. wakeUp 함수

마지막으로 Call stack 남아있던 함수인 wakeUp의 마지막 코드인 console.log가 실행되면 Call stack에 모든 함수가 제거된다.



🤔 Call Stack엔 몇 개까지 쌓을 수 있을까?

모든 것엔 한계가 존재한다. 단편적인 예로 number타입이 표현할 수 있는 최대값은 1.7976931348623157e+308이며 그 이상의 수는 Infinity로 표현된다. Call Stack도 마찬가지로, 스택의 사이즈는 한계가 존재하여 재귀함수 등을 통해 함수를 지속적으로 호출하여 스택이 계속 쌓이게 되면...

콜스택은 나 이제 한계야 ^^ 하고 오류를 뱉게 된다.

이것이 바로 유명한 STACK OVERFLOW이다.

스택 오버플로우(Stack Overflow)란 '스택이 넘쳐 흐른다'라는 의미 그대로,
스택 영역을 벗어나 다른 메모리 영역을 사용하지 못하도록 하는 것을 의미한다. 주로 재귀함수가 무한히 호출될 때 발생하며, 프로그램이 오작동하거나 종료될 수 있고, 보안상 취약점이 노출될 수 있어 발생하지 않도록 조심하는 것이 좋다.


💡 3줄 정리

  1. 함수가 호출되면 Call Stack에 쌓이고 Call Stack은 가장 마지막에 들어온 함수부터 제거된다.
  2. 함수는 완료(return)되면 Call Stack에서 제거된다.
  3. Call Stack은 한계가 존재하므로 너무 많은 함수를 호출할 경우, Stack Overflow가 발생할 수 있다.
profile
한입 크기로 베어먹는 개발지식 🍰

0개의 댓글

관련 채용 정보