[TIL # 23] JS 10일차

Yejin Yang·2022년 5월 9일
0

[TIL]

목록 보기
23/69
post-thumbnail

콜 스택(call stack) 이란

컴퓨터 프로그램에서 현재 실행 중인 서브루틴에 관한 정보를 저장하는 스택 자료구조이다.

작업이 요청되면(함수가 호출되면) 요청된 작업은 순차적으로 Call Stack에 쌓이게 되고 순차적으로 실행된다. 자바스크립트는 단 하나의 Call Stack을 사용하기 때문에 해당 task가 종료하기 전까지는 다른 어떤 task도 수행될 수 없다.

MDN

  • 스크립트가 함수를 호출하면 인터프리터는 이를 호출 스택에 추가한 다음 함수를 수행하기 시작합니다.
  • 해당 함수에 의해 호출되는 모든 함수는 호출 스택에 추가되고 호출이 도달하는 위치에서 실행합니다.
  • 메인 함수가 끝나면 인터프리터는 스택을 제거하고 메인 코드 목록에서 중단된 실행을 다시 시작합니다.
  • 스택이 할당된 공간보다 많은 공간을 차지하면 "stack overflow" 에러가 발생합니다.

자바스크립트 엔진

구글의 V8을 비롯한 대부분의 자바스크립트 엔진은 두 가지 주요 구성 요소로 구성된다.

  • Memory Heap: 메모리 할당이 발생하는 곳. 동적으로 생성된 객체 인스턴스가 할당되는 영역이다.

  • Call Stack: 코드가 실행될 때 스택 프레임이 있는 곳. 작업이 요청되면(함수가 호출되면) 요청된 작업은 순차적으로 Call Stack에 쌓이게 되고 순차적으로 실행된다. 자바스크립트는 단 하나의 Call Stack을 사용하기 때문에 해당 task가 종료하기 전까지는 다른 어떤 task도 수행될 수 없다.

엔진은 실제로는 더 많다. DOM, AJAX, setTimeout 등과 같은 브라우저에서 제공하는 Web API라는 것이 있다.

Callback

JavaScript는 단일 스레드 프로그래밍 언어이므로 단일 호출 스택이 있다. 따라서 한 번에 한 가지 작업을 수행할 수 있다.

콜스택은 기본적으로 프로그램에서 우리가 어디에 있는지 기록하는 데이터 구조이다. 함수로 들어가면 스택의 맨 위에 놓는다. 함수에서 반환하면 스택의 맨 위에서 튀어 나온다.(선입선출)

호출 스택의 각 항목을 "스택 프레임"이라고 한다.

예제

function multiply(x, y) {
    return x * y;
}
function printSquare(x) {
    const s = multiply(x, x);
    console.log(s);
}
printSquare(5);

위 코드를 이미지로 표현 한다면 아래와 같다.

예외가 발생했을 때 호출 스택의 상태

function foo() {
    throw new Error('SessionStack will help you resolve crashes :)');
}
function bar() {
    foo();
}
function start() {
    bar();
}
start();
function foo() {
    foo();
}
foo();

"Blowing the stack"
: 스택 날려버리기, 최대 호출 스택 크기에 도달했을 때 발생한다. 특히 코드를 매우 광범위하게 테스트하지 않고 재귀를 사용하는 경우에는 매우 쉽게 발생할 수 있다.

만약에 브라우저에서 JavaScript를 사용하여 복잡한 이미지 변환을 수행하려고 할 때를 생각해보자.

문제 발생: 콜스택이 실행할 기능이 있는 동안 브라우저가 실제로 다른 작업을 수행할 수 없기에 문제가 발생한다. 이것은 브라우저가 렌더링할 수 없고 다른 코드를 실행할 수 없고 그냥 멈춘다는 것을 의미한다.

또한, 브라우저가 콜스택에서 너무 많은 작업을 처리하기 시작하면 꽤 오랜 시간 동안 응답하지 않을 수 있다.

해결책은 비동기 콜백이다!



동시성 및 이벤트 루프

자바스크립트는 단일 스레드이지만, 실제로 동작하는 웹 애플리케이션은 많은 task가 동시에 처리되는 것처럼 느껴진다.
이처럼 자바스크립트의 동시성(Concurrency)을 지원하는 것이 바로 이벤트 루프(Event Loop)이다.

✅ 자바스크립트 엔진은 단순히 작업이 요청되면 Call Stack을 사용하여 요청된 작업을 순차적으로 실행할 뿐이다.

✅ 동시성(Concurrency)을 지원하기 위해 필요한 비동기 요청(이벤트를 포함) 처리는 자바스크립트 엔진을 구동하는 환경 즉 브라우저(또는 Node.js)가 담당한다.

Event Queue(Task Queue)
비동기 처리 함수의 콜백 함수, 비동기식 이벤트 핸들러, Timer 함수(setTimeout(), setInterval())의 콜백 함수가 보관되는 영역으로 이벤트 루프(Event Loop)에 의해 특정 시점(Call Stack이 비어졌을 때)에 순차적으로 Call Stack으로 이동되어 실행된다.

Event Loop(이벤트 루프)
Call Stack 내에서 현재 실행중인 task가 있는지 그리고 Event Queue에 task가 있는지 반복하여 확인한다. 만약 Call Stack이 비어있다면 Event Queue 내의 task가 Call Stack으로 이동하고 실행된다.

예제 코드

function func1() {
  console.log('func1');
  func2();
}

function func2() {
  setTimeout(function () {
    console.log('func2');
  }, 0);

  func3();
}

function func3() {
  console.log('func3');
}

func1();
  • 함수 func1이 호출되면 함수 func1은 Call Stack에 쌓인다.
  • 그리고 함수 func1은 함수 func2을 호출하므로 함수 func2가 Call Stack에 쌓이고 setTimeout가 호출된다.
  • setTimeout의 콜백함수는 즉시 실행되지 않고 지정 대기 시간만큼 기다리다가 “tick” 이벤트가 발생하면 태스크 큐로 이동한 후 Call Stack이 비어졌을 때 Call Stack으로 이동되어 실행된다.

tick?
이벤트 루프는 콜스택과 이벤트큐를 계속 돌아면서 실행할 게 하나라도 있는지 보면서 감시한다. 만약 콜스택이 비어있고 이벤트큐에 작업이 있으면 제일 앞에 있는 작업을 콜스택에 추가한다. 이러한 과정을 tick이라고 한다.


이벤트 루프(Event Loop)에 의한 setTimeout 콜백함수의 실행 방법



참고 자료

How JavaScript works: an overview of the engine, the runtime, and the call stack

콜스택 연습해보는 사이트
(참고로 해당 사이트에서 코드 작성할 때, 화살표 함수는 작동이안됩니다!)

https://developer.mozilla.org/ko/docs/Glossary/Call_stack

https://poiemaweb.com/js-event

profile
Frontend developer

0개의 댓글