Node.js

[NodeJS] 이벤트 디멀티플렉싱과 리액터패턴

SongMinu 2022. 8. 15. 15:54
728x90

이벤트 디멀티플렉싱

대부분의 운영체제는 논 블로킹 리소스를 효율적인 방법으로 처리하기 위한 기본적인 메커니즘인 동기 이벤트 디멀티플렉서, 이벤트 통지 인터페이스를 제공한다.

 

멀티플렉싱은 전기통신 용어로 여러 신호들을 하나로 합성하여 제한된 수용범위 내에서 매개체를 통하여 쉽게 전달하는 방법을 나타낸다.

디멀티플렉싱신호가 원래의 구성요소로 다시 분할되는 작업이다.

 

동기 이벤트 디멀티플렉서는 여러 리소스를 관찰하고 이 리소스들 중에 읽기 또는 쓰기 연산의 실행이 완료되었을 때 새로운 이벤트를 반환한다. 그리고 이점은 동기 이벤트 디멀티플렉서가 처리하기 위한 새로운 이벤트가 있을 때까지 블로킹된다는 점이다.

watchedList.add(docketA, FOR_READ); // (1)
watchedList.add(fileB, FOR_READ);
while(events = demultiplexer.watch(watchedList)) { // (2)
  //이벤트 루프
  for (event of events) { // (3)
    //블로킹 하지 않으며 항상 데이터를 반환
    data = event.resource.read();
    if (data === RESOURCE_CLOSED) {
      //리소스가 닫히고 관찰되는 리스트에서 삭제
      demultiplexer.unwatch(event.resource);
    } else {
      //실제 데이터를 받으면 처리
      consumeData(data);
    }
  }
}

(1) : 각 리소스가 데이터 구조(List)에 추가된다.

각 리소스를 특정 연산과 연결한다.

(2) : 디멀티플렉서가 관찰될 리소스 그룹과 함께 설정된다.

demultiplexer.watch()는 동기식으로 관찰되는 리소스들 중에서 읽을 준비가 된 리소스가 있을 때까지 블로킹된다.

준비된 리소스가 생기면, 이벤트 디멀티플렉서는 처리를 위한 새로운 이벤트 세트를 반환한다.

(3) : 이벤트 디멀티플렉서에서 반환된 각 이벤트가 처리된다.

이 시점에서 각 이벤트와 관련된 리소스는 읽을 준비 및 차단되지 않는 것이 보장된다.

모든 이벤트가 처리되고 나면, 이 흐름은 다시 이벤트 디멀티플렉서가 처리 가능한 이벤트를 반환하기 전까지 블로킹된다.

이를 이벤트 루프(event loop)라고 한다.

 

이 패턴을 이용하면 바쁜 대기(busy-waiting) 기술을 이용하지 않고도 여러 I/O 작업을 단일 스레드 내에서 다룰 수 있다.

단일 스레드를 사용하여 여러 리소스를 다룰 수 있게 된 것.

리액터(Reactor) 패턴

리액터 패턴의 이면에 있는 주된 아이디어는 각 I/O 작업에 연관된 핸들러를 갖는다는 것이다.

Node.js에서의 핸들러는 콜백 함수에 해당한다.

이 핸들러는 이벤트가 생성되고 이벤트 루프에 의해 처리되는 즉시 호출되게 된다.

리액터 패턴 구조

  1. 애플리케이션은 이벤트 디멀티플렉서에 요청을 전달함으로써 새로운 I/O 작업을 생성한다.
    또한, 애플리케이션은 작업이 완료되었을 때 호출될 핸들러를 명시한다.
    이벤트 디멀티플렉서에 새 요청을 전달하는 것은 논 블로킹 호출이며, 제어권은 애플리케이션으로 즉시 반환된다.
  2. 일련의 I/O 작업들이 완료되면 이벤트 디멀티플렉서는 대응하는 이벤트 작업들을 이벤트 큐에 집어 넣는다.
  3. 이 시점에서 이벤트 루프이벤트 큐의 항목들을 순환한다.
  4. 각 이벤트와 관련된 핸들러가 호출된다.
  5. 애플리케이션 코드의 일부인 핸들러의 실행이 완료되면 제어권을 이벤트 루프에 되돌려준다.(5a)
    핸들러 실행 중에 다른 비동기 작업을 요청할 수 있으면(5b),
    이는 이벤트 디멀티플렉서에 새로운 항목을 추가하는 것이다.(1)
  6. 이벤트 큐의 모든 항목이 처리되고 나면 이벤트 루프이벤트 디멀티플렉서에서 블로킹되며 처리 가능한 새 이벤트가 있을 경우 이 과정이 다시 트리거 된다.

애플리케이션은 특정 시점에 리소스로 (블로킹 없이) 접근하고 싶다는 요청과 동시에 작업이 완료되었을 때 호출된 핸들러를 제공한다.

 


(이 내용은 영진닷컴의 Node.js 디자인 패턴 바이블 책을 보다 괜찮은 내용이길래 참고하여 작성했습니다.)

반응형