[Node] EventEmitter 객체에 대해서

Kim Tae Won·2022년 1월 12일
0
post-thumbnail

비동기 프로그래밍을 하는 또다른 방법으로 이벤트를 사용하는 방법이 있다.

Node.js에서의 Event가 중요한 이유

Node.js 에서의 이벤트란 어떤 일이 발생했음을 알리는 신호 이다.
이벤트를 이해하는 것이 Node.js에서 매우 중요하다

  • 대부분의 노드의 core API들은 이벤트 기반 구조 위에서 작성되었고, 그 구조에서는 특정 객체가 이벤트를 발생시키면, 해당 이벤트에 대한 call-back(listener)가 실행된다.

  • 서드파티 모듈이든 직접 만든 모듈이든 대부분의 모듈을 core 모듈을 사용하게 되는데, 이러한 core 모듈에서 제공되는 많은 객체들이 이벤트 기반으로 작동하게 되므로 이벤트에 대한 이해가 중요하다

  • Event를 발생시키는 모든 객체는 모두 EventEmitter 클래스의 객체이다. 매우 핵심적인 내용이다.

즉, 노드에서는 이벤트를 발생시키기 위해선 EventEmitter 객체를 사용하게 된다.
사용방법은 다음과 같다.

const EventEmitter = require('events');

events 모듈은 EventEmitter라는 class 하나를 공개하게 된다.
EventEmitter는 한국말로 이벤트 발생기 정도로 해석할 수 있는데, 해당 클래스의 객체가 있어야만 Event를 발생시킬 수 있게 된다.

const myEmitter = new EventEmitter();

위 코드처럼 myEmitter에 객체를 만들고 사용하게 된다.

한 가지 유의할 점은, 이벤트를 발생시키고, 해당 이벤트에 대한 콜백이 실행되는 연산은 하나의 EventEmitter 객체 내에서만 이루어진다. 다시 말하자면, 하나의 EventEmitter객체가 발생시키는 이벤트는 해당 객체 내에서만 유효하는 점이다.

  • 예를 들어, EventEmitter 객체 myEmitter1myEmitter2가 있을 때, myEmitter1이 발생시키는 이벤트는 myEmitter1의 콜백 함수만 실행하게 된다는 얘기이다. 즉, 하나의 EventEmitter 객체에 설정된 콜백이 다른 EventEmitter 객체에 이벤트에 반응하지 않는다는 얘기다.

EventEmitter 객체 자세히 알아보기

EventEmitter 객체에는 여러 메소드들이 존재하는데, 하나씩 알아보자.

1. on() : 어떤 이벤트가 발생했을 때, 실행할 콜백을 등록하는 메소드(이벤트 핸들러를 설정하는 메소드, addLinster메소드와 역할과 인자가 동일함)

// 'test'라는 이벤트가 발생하면 'Success'가 출력되도록 한 것
myEmitter.on('test', () => {
  console.log('Success');
});
//* 하나의 이벤트에 대해 여러가지 콜백도 적용할 수 있다
myEmitter.on('test', () => {
  console.log('Success2');
});

2. emit() : 인위적으로 이벤트를 발생시키는 메소드

  • 직접 나만의 EventEmitter 객체를 만들지 않은 이상 사용할 일이 거의 없음
  • 대부분 이벤트에 대한 콜백이 등록되면, 해당 이벤트가 발생했을 때 노드가 발생시켜주게 됨
// 'test'라는 이벤트를 발생시키는 함수
myEmitter.emit('test');

3. once() : 특정 이벤트에 대한 이벤트 핸들러를 등록하지만, 딱 한 번만 반응해서 실행되도록 하는 메소드

myEmitter.once('test', () => {
  console.log('Success');
});

myEmitter.emit('test');
myEmitter.emit('test');
myEmitter.emit('test');
  • once()에 콜백 메소드를 등록하였기 때문에, 위 코드의 실행 결과는 Success가 한 번만 출력되게 된다.

4. listeners() : 특정 이벤트에 대한 이벤트 핸들러들의 배열을 출력해주는 메소드

myEmitter.once('test', () => {
  console.log('A');
});

myEmitter.once('test', () => {
  console.log('B');
});

myEmitter.once('test', () => {
  console.log('C');
});

console.log(myEmitter.listeners('test'));
결과 : [ [Function], [Function], [Function] ]

5. off() : 이벤트 핸들러를 해제하는 메소드 (해제할 이벤트 핸들러를 정확하게 지정해줘야 함)

  • 단순히 콜백 함수의 생김새가 같다고 해서 같은 함수가 아니다. 아래 예시를 보자. 이를 실행하면 'Success'가 그대로 출력된다. 그 이유는 A와 B의 콜백함수가 생김새는 같지만 완전히 다른 함수이기 때문이다. 그럼 어떻게 해야 될까?
myEmitter.on('test', () => { // --- (A)
  console.log('Success');
});

myEmitter.off('test', () => { // --- (B)
  console.log('Success');
});

myEmitter.emit('test');
  • 나중에 참조할 수 있도록 따로 변수에 할당해주거나 이벤트 핸들러가 여러개인 경우 배열로 관리를 해야 한다.

  • 변수에 할당

    const callback = () => {
      console.log('Success');
    };
    
    myEmitter.on('test', callback);
    
    myEmitter.off('test', callback);
    
    myEmitter.emit('test');
    // 아무것도 출력되지 않는다.
  • 배열로 관리

    const cbArr = [];
    
    cbArr[0] = () => {
      console.log('A');
    };
    
    cbArr[1] = () => {
      console.log('B');
    };
    
    myEmitter.on('test', cbArr[0]);
    myEmitter.on('test', cbArr[1]);
    
    myEmitter.off('test', cbArr[0]);
    myEmitter.off('test', cbArr[1]);
    
    myEmitter.emit('test');

참고

  • 코드잇
profile
꿈이 너무나 큰 평범한 컴공 대딩에서 취업 성공!

0개의 댓글