[JS] 콜스택이란 ?!

sanghun Lee·2020년 11월 4일
0

Today I Learned

목록 보기
56/66

면접으로 바쁜나날이라 다양한 정리들을 노션으로 간단하게 진행하고 있는 요즘이다.

그럼에도 불구하고 이 글을 쓰는 이유는 면접에서 꼭 찾아보면 좋다고 하셔서 필수 기본지식 중 하나라여겼기 때문이다🧐.

일단 MDN을 찾아봤다.

MDN에서는

호출스택(call stack)은 여러 함수들을 호출하는 스크립트에서 해당 위치를 추적하는 interpreter를 위한 메커니즘이라고 설명되어있다.

문제는 난 인터프리터가 뭔지 모르므로 ? 또 찾아봤다.

1. 인터프리터, 컴파일러

인터프리터 언어란 프로그래밍언어의 소스코드를 바로 실행하는 컴퓨터 프로그램 또는 환경을 말한다고 한다.
적어도 아래의 세가지 조건을 만족해야한단다.

  1. 소스코드를 직접 실행한다.
  2. 소스코드를 효율적인 다른 중간코드로 변환하고, 변환한 것을 바로 실행한다.
  3. 인터프리터 시스템의 일부인 컴파일러가 만든, 미리 컴파일된 저장 코드의 실행을 호출 한다.

쉽게 말해서 컴파일러는 고급언어(프로그래멍언어 같은 것들 그러니까 서버로 부터 가까운 것 보다 유저로 부터 가까운 언어라고 말하면 되려나.. 이런 언어)
로 작성된 원시코드 명령어들을 한번에 한줄씩 읽어 들여서 실행하는 프로그램이다.


출처: 네이버 지식백과

2. 그래서 콜스택은...

그래서 호출스택은 아래와 같은 작동 순서를 가진다고 한다.

  • 스크립트가 함수를 호출한다.
  • 인터프리터는 이를 호출스택에 추가한 다음 함수를 수행하기 시작한다.
  • 함수에 의해 호출되는 모든 함수는 호출스택에 추가 되며 호출이 도달하는 위치에서 실행한다.
  • 메인함수가 끝나면 인터프리터는 스택을 제거한다.
  • 메인코드목록에서 중단된 실행을 다시시작한다.
  • 스택이 할당된 공간보다 많은 공간을 차지하면 "stack overflow" 가 발생한다.
    function greeting(){
    	//codecode1
        sayHi();
        //codecode2
    }
    function sayHi(){
    	return "Hi!";
    }
    //greeting 함수 호출
    greeting();
    //codecode3

예시를 통해 이해를 해보겠다.
일단 기명함수로 greeting() 과 sayHi()가 있다.
greeting()이 호출되어있다.

greeting이 호출되니 greeting 이라는 함수를 호출 스택리스트에 추가하게 된다.

이때 호출스택리스트에는 greeting이 존재한다.

이제 greeting이 추가되고 난 다음 함수 내부의 모든 코드를 실행한다.

  • 실행과 호출이라는 단어를 비교하며 꼭 생각하자

여기서 sayHi 함수가 호출이 된다.
그럼 호출스택리스트에는 sayHi가 추가된다.

이때 호출스택리스트에는 greeting, sayHi가 존재한다.

sayHi함수의 끝까지 실행을 하게 된다(함수 내부의 모든 코드 실행)
sayHi가 호출된 라인(codecode1과 2의 사이)로 돌아온다.
그리고 남아있는 greeting()함수를 계속 실행한다.

호출스택리스트에서 sayHi()함수를 제거한다.

이때 호출스택리스트에는 greeting이 존재한다.

  • Q: 왜 돌아온다음 스택리스트에서 제거가 될까(제거하고 돌아가면 안되나?)

이제 greeting함수 내부의 모든 코드가 실행되었을때, 이를 호출한 라인으로 돌아와 js 코드의 나머지를 계속 실행한다.
호출스택리스트에서 greeting()함수를 제거한다.

이때 호출스택리스트는 비었다.

따라서 빈 호출스택으로 시작하여 함수를 호출할 때 마다 자동으로 호출스택에 추가되고, 해당코드가 모두 실행된 후, 호출스택에서 자동으로 제거가된다.
그래서 끝은 빈 호출스택으로 끝난다.

3. 그래서 왜쓰는거고 왜 알아야하나 ?

이유를 알기 위해서는 실행컨텍스트와 재귀함수에 대한 이해가 필요한 것 같다.

실행컨텍스트는 아주 간략하게 말해서 코드가 실행되어야 할때 이의 환경정보를 저장한 객체라고 생각하면된다.

재귀함수는 함수자신이 자신을 다시 부르는것이다.(매우간략)
재귀함수에 관해서는 다른 블로그에서 정리해보겠다.

function pow(x, n) {
  if (n == 1) {
    return x;
  } else {
    return x * pow(x, n - 1);
  }
}

alert( pow(2, 3) ); // 8

처음 하는 호출을 포함한 중첩 호출의 최대 개수는 재귀 깊이(recursion depth) 라고 합니다. pow(x, n)의 재귀 깊이는 n이다.

자바스크립트 엔진은 최대 재귀 깊이를 제한한다.

이때 콜스택을 생각하면 된다.

코어자바스크립트의 설명에 따르면

만개 정도까진 확실히 허용하고, 엔진에 따라 이보다 더 많은 깊이를 허용하는 경우도 있습니다.

하지만 대다수의 엔진이 십만까지는 다루지 못합니다.

이런 제한을 완화하려고 엔진 내부에서 자동으로 'tail calls optimization’라는 최적화를 수행하긴 하지만, 모든 곳에 적용되는 것은 아니고 간단한 경우에만 적용됩니다.

정리

정리하자면 콜스택이란 함수가 호출되면 쌓이고 실행이 끝나면 스택에서 제거된다.

콜스택은 재귀함수를 사용할 때의 경우 그 깊이가 정해져있고 대략 1만 정도까지 허용한다고 생각하자(그게 안전)

졸리니까 to be continue..

profile
알고리즘 풀이를 담은 블로그입니다.

0개의 댓글