본문 바로가기

Javascript

Event Loop

자바스크립트의 큰 특징 중 하나는 싱글 스레드(단일 스레드) 기반으로 동작한다는 것이다.

 

자바스크립트를 해석하는 엔진은 크게 3가지 영역으로 나뉘는데 (V8 기준으로 작성)

1. Call Stack(호출 스택)

2. Task Queue (Event Queue)

3. Memory Heap

+ 그리고 추가적으로 Event Loop가 존재한다.

이벤트 루프는 Task Queue에 들어가는 task들을 관리하게 된다.

동작원리 1
동작원리 2

그림이 2개인 것은 Queue 가 자바스크립트 엔진에 들어가냐 마냐 의견이 분분하여 (찾아봤는데 정확히 명시된 곳이 없다.)

일단 그림을 2개 넣어보았다.

 

Call Stack

자바스크립트는 단 하나의 호출스택을 사용한다. 이러한 특징 때문에 자바스트립트 함수가 실행되는 방식을 "Run to Completion" 라고도 한다. 이는 하나의 함수가 실행되면 이 함수의 실행이 끝날 때까지 다른 어떤 Task도 수행을 할 수 없다는 의미이다. 따라서 한번에 하나의 일만 할 수 있다.

 

Heap (메모리 할당이 일어나는 영역)

동적으로 생성된 객체(인스턴스)는 Heap에 할당된다. 

 

Task Queue(Event Queue)

처리해야하는 Task들을 임시 저장하는 대기 큐가 존재한다. Call Stack이 비워져 있을때 먼저 대기열에 들어온 순서대로 수행된다.

이벤트루프는 호출 스택이 비워질 때마다 큐에서 콜백 함수를 꺼내와서 실행하는 역할을 해 준다.

 

글로만 설명을 하면 어려우니 코드로 예제를 들어 보겠다.

function test(){
    setTimeout(function(){
        console.log("타임아웃 실행");
    }, 1500);
    
    for(var i=0;i<3;i++){
    	somthingFunc(); // 매번 1초가 걸리는 작업
        console.log(i);
    }
    
    console.log("3초 걸리는 for문 끝");
}

test();

console.log("main 끝");

예제를 보면 test() 함수를 실행시키면 콘솔이 찍히는 순서가 어떻게 될 것 같은가?

[0, 1, "타임아웃 실행", 2, "3초 걸리는 for문 끝", "main 끝"]

이렇게 찍힐것같으면 오산이다.

 

결과는 [0, 1, 2, "3초 걸리는 for문 끝", "main 끝", "타임아웃 실행"] 이다.

setTimeout 함수는 3초뒤에 실행이 된다.

 

그림을 그려보자면


1. 맨 처음 호출 스택이 비워진상태

=> 이벤트 루프가 감지하여 큐 대기열에 들어온 순서대로 스택에 push


2. main() 함수 실행


3. test() 함수실행

setTimeout(function(){
        console.log("타임아웃 실행");
}, 1500);

=> 처음 setTimeout() 을 먼저 실행하는데 자바스크립트에서 실행되는 setTimeout 함수는 

브라우저에서 제공하는 Web API의 Timer에서 실행이 된다.(외부)

[관련링크]https://developer.mozilla.org/ko/docs/Web/API

 

Web API

웹 코드를 작성한다면 많은 API를 사용할 수 있습니다. 아래 목록은 웹 앱이나 웹 사이트를 만들 때 사용할 수 있는 모든 인터페이스(객체의 유형)입니다.

developer.mozilla.org


4. for문을 돌며 콘솔을 찍는다. 

for(var i=0;i<3;i++){
     somthingFunc(); // 매번 1초가 걸리는 작업
     console.log(i);
}

=> 2번째 somethingFunc() 를 실행할때 약 1.5초가 지났을때 이벤트 루프가 큐에 넣는다.

=> 콜스택에서는 실행되고 있기에 setTimeout() 함수는 바로 수행 할 수가 없다. 하던 일은 끝까지 한다. (싱글스레드)

=> for() 문을 빠져나온 뒤의 콘솔을 찍는다. console.log("3초 걸리는 for문 끝");


5. test() 함수 리턴

=> test() 함수 끝나고 실행되는 콘솔 찍음

console.log("main 끝");


6. main 리턴

=> 콜스택이 비워지고 나서야 setTimeout() 을 꺼내서 실행


7. 마지막 로그 출력 (약 3초뒤)

console.log("타임아웃 실행");

=> Timer는 x초 뒤에 실행되는 애가 아니고 x초 뒤에 큐로 집어넣는다.


8. setTimeout() 리턴


사실 console.log()도 함수니 stack안에 넣어줘야 했지만 길어질까봐 생략하였다.

 

 

마치며

이벤트 루프호출 스택이 비워질 때마다 큐에서 콜백 함수를 꺼내와서 실행하는 역할을 한다는 것이고 부가적으로 자바스크립트 엔진의 동작원리를 자세하게 몰랐는데 이벤트 루프를 공부하다보니 스택, 큐, web api와 연관이 되어있는 걸 알았고, 어떤식으로 동작하는지를 알게되었다.

 

 

'Javascript' 카테고리의 다른 글

[JS] Array 중복제거  (0) 2024.07.24
number만큼 array for문 돌리기  (0) 2020.06.23
로컬스토리지 세션스토리지 차이점  (0) 2020.01.20
dynamic form 전송해서 새창열기  (0) 2019.10.30