이벤트 디멀티플렉싱은 무엇인가?

이 매커니즘은 감시된 일련의 리소스들로부터 들어오는 I/O 이벤트를 수집하여 큐에 넣고 처리할 수 있는 새 이벤트가 있을 때까지 차단함.

socketA,pipeB
wahchedList.add(socketA, FOR_READ); // [1]
while(events = demultiplexer.watch(watchedList)){ //[2]
	foreach(event in events){
		//read는 블록되지 않으며 비어있을지언정, 항상 데이터를 반환함.
		data = event.resource.read();
		if(data === RESOURCE_CLOSED) demultiplexer.unwatch(event.resource);
		else resolve(data);
	}
}

[2]에서 디멀티플렉서에 감시할 것들을 추가. 이 호출은 동기식이며, 감시 대상 중 하나라도 데이터를 리턴하기 전까지 차단됨. 이때 이벤트 디멀티플렉서는 호출로부터 복귀하여 새로운 이벤트들을 처리할 수 있게됨(비동기)

[3]에서 디멀티플렉서가 반환한 이벤트가 처리됨. 여기를 Event Loop라고 부르며, 이곳에 도달했다는 것은 역으로 읽기 작업이 완료되었다는 것이므로 차단되지 않은 상황이라고 보증됨.

구체적으로, 바로 값을 가져올 수 없는 작업형 함수를 만날 경우(I/O) 일단 약속된 상수 값을 리턴시키고 해당 함수를 디멀티플렉서에 추가함. 이때 완료 후 호출될 핸들러(callback)와 이벤트가 디멀티플렉서에 들어감. 이벤트가 완료될 경우 디멀티플렉서가 이벤트를 반환함. 반환된 이벤트는 큐에 push되고, 이벤트 루프는 이벤트 큐를 순회하며 각각의 이벤트들에 대한 핸들러를 실행합니다.

출처 : 이벤트 디멀티플렉싱과 Reactor 패턴 그리고 Node.js의 구조

이벤트 디멀티플렉싱 패턴을 사용하면 Busy-waiting을 사용하지 않고도 단일 스레드 내에서 여러 I/O 작업을 처리할 수 있습니다. 기존의 동기식 블로킹 I/O가 스레드를 만들어 다중 I/O 작업을 처리했다면 이는 하나의 스레드만 사용하여 시간에 따라 작업을 분리해 처리합니다. 따라서 위의 그림처럼 유휴시간(파란색)을 최소로 줄일 수 있습니다. 또한 프로세스 간의 경쟁 혹은 여러 스레드들의 동기화 걱정이 없는 훨씬 간단한 동시성 전략을 사용할 수 있습니다.

반응자 패턴 (Reactor Pattern)

리엑터 패턴의 핵심은 각 I/O 작업과 관련된 핸들러(callback)를 갖는 것입니다. 이 핸들러는 이벤트 루프에 의해 처리되는 즉시 호출됩니다. 리엑터 패턴은 위에서 설명한 이벤트 디멀티플렉싱을 활용하는 패턴입니다.

출처 : 이벤트 디멀티플렉싱과 Reactor 패턴 그리고 Node.js의 구조

 

  1. 애플리케이션이 요청을 이벤트 디멀티플렉서에 제출하여, 새로운 IO 작업을 생성한다. 애플리케이션은 또한 작업이 완료되면 호출할 핸들러(콜백)를 지정한다. 새로운 요청을 이벤트 디멀티플렉서에 제출하는 것은 논블로킹 요청으로, 즉시 애플리케이션에 통제권을 반환한다.
  2. IO 작업 세트가 완료되면, 이벤트 디멀티플렉서가 해당 이벤트 세트를 이벤트 큐로 푸시 한다.
  3. 이 때, 이벤트 루프는 이벤트 큐 항목에서 반복된다.
  4. 각 이벤트에 연결된 핸들러가 호출된다.
  5. a. 애플리케이션 코드의 일부인 핸들러(콜백) 실행이 완료되면, 이벤트 루프를 다시 제어한다. 5b. 콜백이 실행되는 동안, 새로운 비동기 작업을 요청할 수 있으며, 이는 이벤트 디멀티플렉서에 새로운 항목 추가를 야기한다.
  6. 이벤트 큐의 모든항목이 처리되면, 이벤트 루프는 이벤트 디멀티플렉서를 다시 차단하며, 이 경우 새로운 이벤트가 가능해질 때 다시 트리거한다.

즉, 리엑터 패턴은 관찰 대상 리소스가 반응(콜백)하면 해당 이벤트의 핸들러를 추적해 실행하는 디자인 패턴입니다. 노드의 전신이라 할 수 있는 패턴입니다.

출처 : 이벤트 디멀티플렉싱과 Reactor 패턴 그리고 Node.js의 구조

Node.js는 Reactor 패턴을 사용하며 JS Core API, V8 및 libuv에 의존하는 구조라고 할 수 있습니다.

  • Binding: libuv 외 로우레벨 기능들을 JS에 랩핑하고 사용 가능하게 만들어 줌.
  • V8: 구글에서 만든 크롬용 JS 엔진. V8 덕에 Node.js 가 매우 빠르고 효율적으로 작동한다.
  • JS Core API: Node.js API 를 구현하는 자바스크립트 코어

 

참고 사이트 : Plus Ultra

'Web > JavaScript' 카테고리의 다른 글

JavaScript란?  (0) 2024.03.05
Node.js 란?  (0) 2024.03.05
[Javascript] 얕은 복사와 깊은 복사  (0) 2024.02.05

+ Recent posts