전성빈의 사리사욕

[JavaScript]동시성 모델과 Event Loop 본문

백엔드 로드맵따라가기/Language

[JavaScript]동시성 모델과 Event Loop

Been2 2020. 8. 14. 00:55
728x90

JavaScript는 Event loop을 기반으로한 concurrency모델이다. 이벤트 루프는 코드 실행, 이벤트 수집과 처리, 큐에 존재하는 하위 작업들을 처리 한다.

 

런타임 개념

Js는 싱글 스레드를 기반으로 작동하고 있어 한번에 하나의 작업만 처리할 수 있다. 하나의 함수가 실행되면 수행중인 함수가 끝날때 까지 다른 작업은 수행할 수 없다. 이러한 방식을 Run to Completion이라 한다.

 

Js에 존재하는 Stack, Heap, Queue가 하는일은 다음과 같다.

 

Stack

Js의 스택은 Call stack이라고도 불리우며 실행한 함수를 스택에 쌓아 관리하다.

 

Heap

힙은 대부분 구조화되지 않은 메모리 영역을 나타내며 객체들이 이 공간에 할당 된다.

 

Queue(Event Loop)

처리해야하는 메세지 목록인 메시지 대기열이다.  메시지에는 메시지를 처리하기 위해 호출되는 관련 함수가 있습니다.

 

이벤트 루프는 대기열에서 가장 오래된 메시지부터 처리하기 시작하는데 이를 위해 메시지는 큐에서 제거되고 해당 수행을 위한 함수가 Call stack에 생성됩니다. 함수의 처리는 스택이 다시 비워 질 때 까지 계속됩니다.


Event Loop

 

Js에서 큐가 Event Loop라는 이름을 갖는 이유는 마치 loop같이 동작하기 때문입니다. 간단하게 코드로 하면 아래와 같습니다.

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

queue.waitForMessage()는 아직 처리할 수 없거나 준비가 덜 된 이벤트들을 포함하여 처리 가능한 메시지가 도착할때까지 동기적으로 기다립니다.

 

Run-to-Completion

 

js는 한번 함수를 실행하면 수행이 끝날때 까지 진행됩니다. 따라서 각각의 메시지는 다른 메시지가 실행 되기전에 수행이 종료됩니다. 이러한 방식은 프로그램을 추리하기에 굉장히 좋은 특징입니다. 함수가 실행되는 동안에는 언제든지 데이타를 수정할 수 있고(critical section 회피) 다른 코드가 실행되기 전에는 함수의 실행이 완료됩니다. 이러한 점이 C와는 다른점입니다. 예로 함수가 쓰레드에서 실행되는 과정중 어떤 함수를 수행중이건간에 멈출 수 있습니다.

 

Run-to-completion모델의 단점으로는 메시지를 완료하기 까지 오래 걸릴경우 웹은 다른 작업, 예를 들어 사용자의 클릭이나 스크롤을 처리할 수 없습니다. 브라우저는 "a script is taking too long to run"이란 창을 띄우며 해당 불편사항을 완화시킵니다. 이런 단점을 해결하기 좋은 방법은 메시지가 처리할 내용을 축소시켜 만들거나 가능하다면 처리할 내용을 나눠서 여러개의 메시지로 만드는 것입니다.

 

 

Adding message

 

브라우저에서 이벤트가 발생할 때마다 메시지가 추가되고 event listener가 첨부됩니다. 만약 event listener가 없다면 event는 소멸됩니다. 따라서, click이벤트 리스너가 있는 요소를 클릭하면 메시지가 추가가 됩니다.

 

 

Zero delays

 

setTimeout이나 interval를 위해 delay를 설정할 때 값으로 0을 넣는다고 즉시 실행되지 않습니다.

이는 callback 함수를 실행시키기 위한 minimum delay가 필요하기 때문입니다. 따라서 딜레이를 한없이 0에 가깝게 설정한다해도 이는 보장되지 않습니다.

 

기본적으로 setTimeout은 event loop에 있는 모든 메시지들이 완료되는것을 기다려야 합니다.

 

여러 실행환경의 통신

 

iframe같은 경우 본인의 stack, heap, message queue를 갖고 있습니다. 두개의 뚜려한 실행환경에서 통신하는 방법은 postMessage를 통해 메시지를 주고받는것 밖에 없습니다. 이러한 방법은 어떤 환경에서 메시지 이벤트를 받고있으면 다른 환경에 메시지를 추가합니다.

 


Never blocking

 

Js에서는 다른 언어들과는 다르게 절대로 block되지 않습니다. I/O들을 수행할 때도, DB에 쿼리를 날려 기다릴때도, XHR의 응답을 기다릴때도 사용자의 input을 받을 수 있습니다. 고질적인 예외로는 alert의 존재나 동기 XHR같은 경우이지만 이러한 것들은 피할 수 있으니 만들지 않는 좋은 습관을 가지면 됩니다.

 

 

 

 

 

출처 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

728x90

'백엔드 로드맵따라가기 > Language' 카테고리의 다른 글

[JavaScript]메모리 모델  (0) 2020.08.14