탕구리's 블로그

Call stack & Event loop 본문

javascript

Call stack & Event loop

탕구리당 2019. 5. 28. 16:49
반응형

오늘의 주제

오늘은 자바스크립트의 개념을 처음부터 다시 정리하면서 공부하였던 내용을 하나둘씩 정리하기 위해서 작성하게 되었습니다. 첫 번째 주제로 javascript에서 기본적으로 알아야 하는 구동 원리인 CallStack과 Event Loop에 대해서 작성하게 되었습니다.

 

 

자바스크립트의 메모리 구조

자바 스크립트의 메모리 구조는 크게 Heap memory, CallStack Task Queue로  생각해 볼 수 있습니다. 각 영역에서는 무슨 일을 담당하고 이루어질까요? 자바스크립트의 동작은 아래 그림을 통해서 간략하게 알아볼 수 있습니다.

 

메모리 구조와 이벤트 루프

Call Stack

function call에 대한 관리를 하는 역할을 하며, 이름에서 보듯이 Stack 구조를 통해 function call을 관리합니다. 흔히들 자바스크립트가 싱글 스레드로 작동한다는 내용은 자바스크립트에서 관리하는 CallStack이 하나만 존재한다는 것입니다.

 

 

Heap Memory

변수나 객체에 대한 메모리 할당을 관리합니다.

 

 

Task Queue(callback queue) 

WebAPI를 통해 발생한 Callback function에 대한 처리를 진행합니다. callback이 발생한 경우 TaskQueue에서 대기하며 Callstack이 비우게 되면 차례대로 함수를 실행해 나갑니다. 브라우저에서 제공하는 Web Apis에는 대표적으로 Ajax(XMLHttpRequest), DOM, Timer 등이 있습니다.

 

 

위에서 각각의 영역이 무슨 역할을 하는지 알아보았습니다. 그럼 조금 더 자세하게 각각 영역에서 어떻게 일을 수행하는지 알아봅시다.

 

 

Call Stack

위에서 말한 것처럼 Function Call이 발생하게 되면 Call Stack에 차례대로 쌓여 LIFO(Last In First Out)을 통해 하나씩 함수를 해결해 나갑니다.

 

function test1() {
  console.log('here is test1 function');
  test2();
}

function test2() {
 console.log('here is test2 function');
}

test 1();

// here is test 1 function
// here is test2 function

위와 같은 명령을 실행했을 때  Call Stack이 작동하는 방식은 다음과 같습니다.

 

CallStack 작동 과정

 

실행되는 순서대로 Call Stack에 Function이 하나씩 쌓이고(push) 실행이 완료된 Function은 차례대로 Stack에서 제거(pop)를 실행합니다. 이렇게 Call Stack은 Stack 구조를 통해 function call을 관리합니다.

 

 

Heap Memory

힙 메모리에는 동적으로 객체를 생성 시 메모리가 할당되고 해당 객체가 참조 제거가 되면 가비지 컬렉터(garbage collertor)에게 회수되어 메모리를 반환합니다.

 

메모리 낭비를 위해 참조를 제거하는 방법은 다음과 같습니다.

 

- 사용하지 않은 객체, 변수는 모두 null 로 초기화

- 이벤트 핸들러를 바인딩했다면, 모두 언바인딩

- DOM을 동적으로 생성했다면, 불필요한 객체, 속성(값)을 DOM에 삽입하지 말자.

- 크롬 개발자 도구의 Performace탭에서 timeline 확인해보자

 

 

Task Queue(Callback Queue)

task queue에는 런타임 환경을 통해 발생한 Task들이 call stack이 비워지기 전까지 대기를 하는 영역이라고 생각하시면 될 거 같습니다. 여기서 말하는 런타임 환경을 통해 발생한  Task들이란 비동기로 호출되는 함수들, Web Apis를 통해 발생되는 함수들을 말합니다.

 

 

예를 들어 Web apis에 있는 Timer 함수(SetTimeout)를 이용하여 보겠습니다.

 

function test1()  {
  console.log('test1');
  test2();
}
function test2() {
 setTimeout(function check() {
  console.log('tttt');
 }, 0);
  test3();
}
function test3() {
  console.log('test3);
}

test1():

결과는?
// test1
// test3
----1000ms later----
// test2

 

예제 코드를 보았으니 이제 어떻게 구동되는 건지 그림을 통해서 알아보도록 합시다.

 

1. 호출된 함수들은 차례대로 Call Stack에 쌓여 갑니다.

 

2. test2()의 setTimeout()이 발생하게 되면, setTimeout()은 WebApi의 함수이기 때문에 Timer에서 지정된 시간 후에 실행을 하게 됩니다.

 

3. 지정된 시간이 흐른 후 Check()는 Task Queue에 들어가 Call Stack에 쌓인 함수들이 모두 실행되기를 기다립니다.

 

4. 쌓인 함수들이 모두 실행되고 Call Stack이 빈 상태가 되면 Task Queue에서 대 기준인 함수들이 Event Loop에 의해 Call Stack으로 이동되고 실행됩니다.

 

 

 

이 부분을 공부하면서 중요하게 봐야 할 것은 Task Queue에 존재하는 함수들은 CallStack의 함수들이 전부 실행되고 나서 수행된다는 점입니다. 위의 코드에서 setTimeout(cb, 0)처럼 대기 시간을 0ms로 설정하였지만, setTimeout은 Web APIs의 Timer를 통해서 관리되기 때문에 최종적으로 Task Queue를 거쳐 나중에 실행 되게 됩니다.

 

 

반응형

'javascript' 카테고리의 다른 글

Primitive Type & Reference Type  (0) 2019.05.29
javascript Call & Apply, Bind  (0) 2018.09.13
ES6 화살표함수(arrow function) & thisArg  (0) 2018.09.13
Comments