본문 바로가기
JavaScript

자바스크립트 개발자가 알아야할 33가지 개념(#01. 콜스택)

by 쾌횽 2022. 5. 7.
반응형

 

 

프론트엔드 개발자라면 자바스크립트를 끝임없이 공부해야한다 생각한다.

자바스크립트를 심도 있게 이해하기 위해 자바스크립트 개발자가 알아야할 33가지 개념(https://github.com/yjs03057/33-js-concepts)의 항목들을 알아보고 블로그 글을 정리하며 공부하기로 했다.

 

자바스크립트 엔진

가장 대중적인 자바스크립트의 엔진은 구글의 V8엔진이다.

V8 엔진은 크롬과 노드 안에서 동작한다.

자바스크립트 엔진은 다음과 같이 두 가지 주요 구성 요소로 이루어져 있다.

 

  • 메모리 힙(Memory Heap) - 메모리 할당이 일어나는 곳
    • 힙(Heap) - 구조화되지 않은 넓은 메모리 영역
      객체(변수, 함수 등)들이 담긴다.
  • 콜 스택(Call Stack) - 실행될 코드의 한 줄 단위로 할당되어 실행이 되는 자료구조.

 

 

Call Stack 순서

  1. first() 호출
  2. first함수 내부에서 second() 호출
  3. second함수 내부에서 third() 호출
  4. third함수에 있는 console.log('세 번째')가 실행  -> 호출스택에서 빠져나간다.
  5. second함수에 있는 console.log('두 번째')가 실행  -> 호출스택에서 빠져나간다.
  6. first함수에 있는 console.log('첫 번째')가 실행  -> 호출스택에서 빠져나간다.
  7. third()호출
  8. third함수에 있는 console.log('세 번째')가 실행  -> 호출스택에서 빠져나간다.
  9. second()호출
  10. second함수 내부에서 third() 호출
  11. third함수에 있는 console.log('세 번째')가 실행  -> 호출스택에서 빠져나간다.
  12. second함수에 있는 console.log('두 번째')가 실행  -> 호출스택에서 빠져나간다.

 

실행환경(Runtime)

브라우저는 단순 엔진 하나만으로 구성되어 있지 않다. DOM, AJAX, setTimeout 등의 브라우저에서 제공하는 Web API라고 하는 것들이 있다. 또한 이러한 Web API의 호출을 통제하기 위한 Event QueueEvent Loop도 존재한다.

 

  • Web APIs - 비동기 처리를 담당한다.
  • Callback Queue (Task Queue, Event Queue 등 다양한 형태로 설명된다.) - 비동기 처리가 끝난 후 실행 되어야 할 콜백 함수가 차례로 할당된다.
  • Event Loop - Queue에 할당된 함수를 순서에 맞춰 Call Stack에 할당해준다.

 

스택 오버플로우

이름 그대로 스택의 사이즈를 초과 했을 때 발생하는 오류이다.

스택 오버플로우는 생각보다 쉽게 일어난다. 특히 재귀를 호출했을때 많이 발생한다.

 

 

종료 조건없이 자신을 계속 호출하고 있다.

함수의 스택 프레임이 계속해서 호출 스택에 쌓이게 된다.

 

콜스택마다 한계점을 초과하면 해당 에러를 띄우면서 프로그램이 종료된다.

 

 

단일 호출 스택의 문제점

단일 스레드에서 코드를 실행하는 것은 멀티 스레드 환경에서 발생하는 복잡한 시나리오를 고려할 필요가 없으므로 매우 쉽다.

그러나 단일 스레드에서 실행하는 것도 상당히 제한적이다. 자바스크립트는 하나의 호출 스택만 있기 때문에, 하나의 함수 처리가 엄청 느려서 다른 함수 실해에 지장을 줄 때는 어떻게 해야 할까?

 

비동기 콜백(Asynchronous Callbacks)

가장 쉬운 해결책은 비동기 콜백을 사용하는 것이다.  자바스크립트 실행환경은 이벤트 큐를 가지고 있다. 이는 처리할 메세지 목록과 실행할 콜백 함수들의 리스트이다.

 

 

 

 

위 이미지를에 대입하여 코드를 살펴볼때 Call Stack에 처음 console.log('시작')이 들어가고 실행이 되면서 콘솔에 출력이된다. 그리고 호출 스택에서 빠져나온다. 다음에 비동기 함수인 setTimeout함수가 호출 스택에 쌓이고 실행이 되면서 Web API에 들어가게 된다.

마지막으로 console.log('끝')이 호출 스택에 쌓이고 실행하며 출력이 된다. setTimeout함수의 시간이 지나고 콜백함수는 Callback Queue에 넘어간다. 그러면 Event Loop는 Call Stack이 비워져 있으면 Call Stack으로 넘겨준다. 콜백함수 내부에 console.log('중간')이  호출 스택에 쌓고 출력한다.

 

그러면 setTimeout함수에 0초가 할당되면 어떻게 동작할까?

위에 코드와 동일하게 콜 스택이 쌓이게 된다.  setTimeout함수에 0초가 할당되어도  Web API 거쳐 Callback Queue에 있다가 Call Stack이 비워져 있으면 Event Loop를 통해 Call Stack으로 넘겨준다.

 

 

Promise함수가 있을때는 어떻게 동작할까?

우선 결과부터 보면 시작, 끝, 프로미스, 중간 순으로 콘솔에 출력된다.

선입선출(FIFO)방식으로 setTimeout의 Callback Queue가 먼저 Call Stack에 올라가야 할 것 같지만  Event Loop에는 우선순위가 존재한다. Callback Queue에는 Task Queue(Event Queue), Microtask Queue(Job Queue), Animation Frames로 이루어져 있다.

 

 

또한 우선순위는 

Microtask Queue(Job Queue) > Animation Frames > Task Queue(Event Queue) 이다.

 

Microtask Queue에 속하는 Promise함수가 먼저 Call Stack에 올라가고 Task Queue인 setTimeout함수가 나중에 올라간다.

 

 


참고 및 출처

반응형

댓글