EventEmitter 객체 사용법

맛없는콩두유·2023년 2월 14일
0
post-thumbnail

이번 노트에서는 우리가 배운 EventEmitter 객체의 메소드를 정리하고, EventEmitter 객체의 다른 메소드들도 추가로 배워보겠습니다.

1. on 메소드

const EventEmitter = require('events');

const myEmitter = new EventEmitter();

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

myEmitter.emit('test');

on 메소드는 이벤트 핸들러를 설정하는 메소드입니다. 참고로, on 메소드와 같은 용도를 가진 addListener라는 메소드도 있습니다. 아래 이미지에 나온 것처럼요.

보통 길이가 더 짧은 on 메소드를 쓰지만 다른 개발자가 addListener라고 쓴 코드를 봐도 바로 이해할 수 있도록 기억해두세요. addListener 메소드도 on 메소드와 인자 형식은 동일합니다.

2. emit 메소드

emit 메소드는 인위적으로 이벤트를 발생시키기 위해 쓰는 메소드입니다. 그런데 사실 emit 메소드는 나만의 독특한 EventEmitter 객체를 만들지 않는 이상, 사용할 일이 그리 많지는 않을 겁니다. 왜냐하면 우리는 이미 코어 모듈에 존재하는 EventEmitter 객체를 사용하는 경우가 많을텐데, 이때 이벤트를 발생시키는 건 우리가 아니기 때문입니다. 예를 들어

파일의 내용을 읽을 때, 데이터를 읽어들일 때마다 발생하는 이벤트라든지,
외부로부터의 클라이언트 요청이 발생했을 때 발생하는 이벤트 등은

우리가 emit 메소드로 직접 발생시키는 게 아니라 해당 이벤트가 실제로 발생했을 때 Node가 발생시켜주는 것이기 때문입니다. 그래도 emit 메소드는 on 메소드와 한 쌍을 이루는 메소드니까 잘 기억해두세요.

3. once 메소드

once 메소드는 특정 이벤트에 대한 이벤트 핸들러를 등록한다는 점에서 on 메소드와 유사한 메소드입니다. 하지만 한 가지 특이한 점이 있는데요. 그건 바로 그 이벤트 핸들러가 해당 이벤트에 대해서 딱 한 번만 반응해서 실행되도록 한다는 점이죠. 다음 코드를 보세요.

const EventEmitter = require('events');

const myEmitter = new EventEmitter();

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

myEmitter.emit('test');
myEmitter.emit('test');
myEmitter.emit('test');

우리가 배운 코드에서 on 메소드를 once 메소드로 바꿨습니다. 그리고 test 이벤트를 총 3번 발생시켜(emit)줬는데요. 이 코드를 실행해보면

'Success!'가 딱 한 번만 출력된 것을 알 수 있습니다. test 이벤트에 대한 이벤트 핸들러가 딱 한 번만 실행된 거죠. once 메소드로 등록된 이벤트 핸들러는 한번 실행된 후에는 삭제된다고 생각하시면 됩니다. 특정 이벤트가 어차피 한 번밖에 발생하지 않는 경우나, 이벤트 핸들러가 딱 한 번만 실행되기를 바라는 경우 이 once 메소드를 사용하세요.

4. listeners 메소드

특정 이벤트에 대한 이벤트 핸들러들을 출력해주는 메소드입니다. 이전 영상에서 하나의 이벤트에 관해 여러 개의 이벤트 핸들러를 설정할 수 있다는 점을 잘 기억하라고 했죠?

잠깐, 아래의 코드를 보면

const EventEmitter = require('events');

const myEmitter = new EventEmitter();

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

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

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

console.log(myEmitter.listeners('test'));

지금 test 이벤트에 총 3개의 이벤트 핸들러가 설정된 상황입니다. 그리고 그 후에 listeners 메소드를 호출하고 그 결과를 출력하면

이렇게 총 3개의 이벤트 핸들러(함수, Function)들이 설정돼있다는 걸 알 수 있습니다. 코드를 작성하다가 특정 이벤트에 지금 어떤 이벤트 핸들러들이 설정되어 있는지 조회하고 싶다면, 코드를 처음부터 다시 보기보다는 이 listeners 메소드를 사용하면 되겠죠?

5. off 메소드

이벤트 핸들러를 설정하는 메소드가 있으면, 이벤트 핸들러를 해제하는 메소드도 있어야겠죠? 해제하는 메소드는 바로 off 메소드입니다. 설정은 on, 해제는 off, 외우기 쉽죠?

그런데 off 메소드를 사용할 때는 주의할 점이 있습니다. 그건 바로 해제할 이벤트 핸들러를 정확히 지정해줘야 한다는 겁니다. 잠깐 아래 코드를 보세요.

const EventEmitter = require('events');

const myEmitter = new EventEmitter();

myEmitter.on('test', () => { // --- (A)
  console.log('Success!');
});

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

myEmitter.emit('test');

이 코드를 실행하면 Success!가 출력될까요, 출력되지 않을까요? 답은 바로 '출력된다'입니다.

off 메소드를 썼는데도 이렇게 이벤트에 반응한 이유는 (A) 이벤트 핸들러와 (B) 이벤트 핸들러는 똑같이 생겼지만 서로 다른 함수이기 때문입니다. 따라서 off 메소드를 사용하려면 아래 코드와 같이

const EventEmitter = require('events');

const myEmitter = new EventEmitter();

const callback = () => {
  console.log('Success!');
};

myEmitter.on('test', callback);

myEmitter.off('test', callback);

myEmitter.emit('test');

이벤트 핸들러를 나중에 off 메소드에서도 참조할 수 있도록 변수에 할당해주거나, 여러 개의 이벤트 핸들러인 경우

const EventEmitter = require('events');

const myEmitter = new EventEmitter();

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');

이렇게 배열에 넣어서 관리해줘야 합니다.

위의 두 코드들을 실행하면,

이렇게 이벤트에 반응하지 않는다는 걸 알 수 있습니다. 이벤트 핸들러가 잘 해제된 거죠. off 메소드를 사용할 때는 설정했던 이벤트 핸들러를 정확하게 off하고 있는 게 맞는 건지 꼭 확인하세요.

출처: 코드잇

profile
하루하루 기록하기!

0개의 댓글