본문 바로가기
개발/Javascript

[JavaScript] Event Loop(이벤트 루프)

by 그레이웅 2022. 10. 7. 22:34
반응형

 

Event Loop(이벤트 루프)

자바스크립트는 단일 스레드 기반의 인터프리터 언어이다.

스레드가 하나라는 말은 하나의 작업을 처리하면 다른 작업은 하지 못한다.

하지만 자바스크립트는 동시에 여러 작업이나 이벤트를 보여줄 수 있다. 어떻게 단일 스레드 기반에서 동시에 요청과 이벤트들을 처리하는 것일까? 

 

자바스크립트에서는 이벤트 루프(Event Loop)라는 개념을 사용해 여러 이벤트들을 처리할 수 있다.

이벤트 루프(Event Loop) 비 동기 방식을 지원해 동시에 처리할 수 있다.

 

비동기(Asynchronous , 동시에 일어나지 않는)

비 동기는 요청과 결과가 동시에 일어나지 않을 거라는 약속이다.
보통은 요청이 온 뒤 결과가 나타나는 방식인데 
비 동기방식은 요청을 보낸 후 결과가 오는지 안오는지에 상관없이 요청을 더 보낼 수 있다.

 

 


이벤트 루프(Event Loop)를 설명하기 이전에 자바스크립트의 특징을 먼저 살펴보아야 한다.

자바스크립트의 함수가 실행되는 방식을 보통 "Run to Completion"이라고 한다.

하나의 특정 함수의 실행이 끝나기 전까지는 다른 어떤 작업도 끼어들지 못한다.

 

자바스크립트는 엔진은 하나의 호출 스택만을 사용하고, 실행되는 함수가 호출 스택에 쌓이게 되면, 다른 함수는 호출 스택이 제거되어야만 실행할 수 있다.

 

스택(Stack)

자료 구조(Data Structure) 중 하나로 LIFO(Last In First OUT) 방식을 따른다.
아래와 같이 책이 쌓여있는 이미지를 떠올리면 될것이다.

 

스택과 같은 예시 책을 쌓고 책을 치우려면 위쪽부터 치워야 되는 사진

 

이벤트 루프(Event Loop), 테스크 큐(Task Quene)

이벤트 루프는 이 가상 코드로 설명할 수 있는데

while(queue.waitForMessage()){
  queue.processNextMessage();
}

queue.waitForMessage() 함수는 현재 처리할 메세지가 없으면 새로운 메시지가 올 때까지 동기적으로 대기하게 된다.

 

현재 실행하고 있는 공간을 테스크 큐라고 하며, 이벤트 루프는 현재 테스크 큐가 비어있는지 실행되는지 계속 루프를 돌면서 확인하는 방식이다.

 

이벤트 루프는 현재 테스크 큐가 비었는지 있는지 확인한 뒤 테스크 큐의 첫 번째 테스크를 꺼내와서 실행하게 된다.

 

큐(queue)

스택과 마찬가지로 자료 구조(Data Structure)의 하나로 먼저 집어넣은 데이터가 먼저나오는
FIFO(Frist In First Out) 구조로 저장하는 형식이다.

기차가 터널로 들어가서 나오는 형태를 떠올리면 된다.
기차의 머리부분이 터널로 먼저 들어가지만 나올때는 먼저 머리부분부터 나온다.

 

예제

 

function delay() {
    for (var i = 0; i < 100000; i++);
}
function foo() {
    delay();
    console.log('foo!');
}
function bar() {
    delay();
    console.log('bar!');
}
function baz() {
    delay();
    console.log('baz!');
}

setTimeout(foo, 10);
setTimeout(bar, 10);
setTimeout(baz, 10);

위의 예제를 실행하면 

우선 setTimeout 함수가 먼저 세 번 호출되고, 호출 스택이 비워지게 된다. (setTimeout은 먼저 바로 호출된다.)

그리고 10초 후 foo, bar, baz 함수가 순차적으로 테스크 큐에 추가된다.

현재 호출 스택은 비어있으므로 이벤트 루프는 foo 함수를 먼저 호출 스택에 추가한다.

foo 함수의 실행이 끝나고, 호출 스택이 비워지면 이벤트 루프는 테스크 큐에 존재하는 bar함수를 가져와 실행한다.

bar함수의 실행이 끝나고, 호출 스택이 비워지면 이벤트 루프는 테스크 큐에 존재하는 baz함수를 가져와 실행한다.

모두 실행이 완료하게 되면 호출 스택이 비워지게 되고, 이벤트 루프는 새로운 테스크가 나타날 때까지 대기상태를 지속한다.

 

SetTimeout을 0 으로 설정

setTimeout 함수는 실행 시 바로 테스크 큐에서 실행되어 호출 스택에서 제거되게 된다.

setTimeout(fn, 0) 처럼 0초를 설정하고 실행한다면 바로 즉시 실행하는 것이 아닌 다른 결과를 가져온다.

setTimeout함수를 0초로 설정해도 바로 콜백 하는 게 아닌 테스크 큐에 담고 실행하게 된다.

 

아래의 예제는 다음과 같은 결과를 도출하게 된다.

(function() {

  console.log('시작');

  setTimeout(function cb() {
    console.log('콜백 1: 콜백 메시지');
  }); // has a default time value of 0

  console.log('평범한 메시지');

  setTimeout(function cb1() {
    console.log('콜백 2: 콜백 메시지');
  }, 0);

  console.log('종료');

})();

// "시작"
// "평범한 메시지"
// "종료"
// "콜백 1: 콜백 메시지"
// "콜백 2: 콜백 메시지"

원래 보통의 생각이라면 setTimeout이 0초로 설정되어있기에 바로 실행할 줄 알았지만,  "시작" 출력 후 "콜백 1: 콜백 메시지가" 출력되어야 할 것 같지만,

 

테스크 큐는

setTimeout() -> "시작" -> "평범한 메세지" -> "종료" -> "콜백1" -> "콜백2" 순서로 호출하게 된다. 

 



정리하자면 

이벤트 루프(Event Loop)는 테스크 큐를 바라보고서 계속 테스크 큐를 확인하는 역할을 하며, 

테스크 큐가 비어있고, 실행할 이벤트가 있으면 다시 테스크 큐에 넣어주게 된다.

계속 지속적으로 테스크 큐를 확인하며, 이벤트나 메시지를 처리해주는 역할을 한다.

 

- https://meetup.toast.com/posts/89

- https://developer.mozilla.org/ko/docs/Web/JavaScript/EventLoop

 

 

 

※ 수정할 사항이나 잘못된 사항이있을 시 댓글로 남겨주세요:) 

 

 

반응형

'개발 > Javascript' 카테고리의 다른 글

[Javascript] 자바스크립트의 메모리관리  (0) 2022.10.17
[JavaScript] 호이스팅(Hoisting)  (0) 2022.10.06
[JavaScript] 클로저(Closure)  (1) 2022.10.06
WebStorage API  (0) 2022.09.30
Babel과 polyfill  (1) 2022.09.29

댓글