Juni_Dev_log

(node.js) [Part.4] 노드의 기본 기능 알아보기 - 이벤트 이해하기 본문

Theorem (정리)/node.js

(node.js) [Part.4] 노드의 기본 기능 알아보기 - 이벤트 이해하기

Juni_K 2020. 12. 3. 15:14

노드는 대부분 이벤트를 기반으로 하는 비동기 방식으로 처리한다.

그리고 비동기 방식으로 처리하기 위해서 서로 다른 이벤트를 전달한다.

예를 들어, 어떤 함수를 실행한 결과물도 이벤트로 전달한다. 이벤트는 한쪽에서 다른 쪽으로 알림 메세지를 보내는 것과 비슷하다. 즉, '지금 이쪽의 상태는 이렇다' 는 정보를 다른 쪽으로 보내는 것이다.

 

노드에서는 이런 이벤트를 보낼 수 있도록 EventEmitter 라는 것이 만들어져 있다.

EventEmitter 를 통해서 이벤트를 주고 받는 방법을 알아보자.

 

이벤트를 주고 받는 방법

이벤트 보내고 받기

노드의 객체는 EventEmitter를 상속받을 수 있으며, 상속받은 후에 EventEmitter 객체의 on() 과  emit() 메소드를 사용할 수 있다.

on() 메소드는, 이벤트가 전달된 객체에 이벤트 리스너를 설정하는 역할을 한다. 이 리스너 함수는 객체로 전달된 이벤트를 받아서 처리할 수 있다. 

보통은 노드 내부에서 미리 만들어 제공하는 이벤트를 받아 처리하지만, 필요할 때는 직접 이벤트를 만들어 전달할 수 있다.

 

 on() 메소드 외에 once() 메소드를 사용할 수 있다.

once() 메소드를 사용할 때는 이벤트 리스너 함수가 한 번이라도 실행하고 나면 자동으로 제거되므로 이벤트를 딱 한 번만 받아서 처리할 수 있다.

 

이벤트를 다른 쪽으로 전달하고 싶다면 emit() 메소드를 사용한다.

 

메소드 이름 설명
on(event, listener) 지정한 이벤트의 리스너를 추가한다.
once(event, listener) 지정한 이벤트의 리스너를 추가하지만 한 번만 실행한 후에는 자동으로 리스너가 제거된다.
removeListener(event, listener) 지정한 이벤트에 대한 리스너를 제거한다.

ch04_test2.js 파일을 새로 추가한 후, 다음 코드를 입력한다.

1
2
3
4
5
6
7
8
9
10
process.on('exit'function(){
    console.log('exit 이벤트 발생함.');
});
 
setTimeout(function(){
    console.log('2초 후에 시스템 종료 시도함.');
    
    process.exit();
},2000);
 
cs

process 객체는 노드에서 언제든지 사용할 수 있는 객체인데, 이미 내부적으로 EventEmitter를 상속하도록 만들어져 있어서 on() 과 emit() 메소드를 바로 사용할 수 있다.

process 객체의 on() 메소드를 호출하면서 이벤트 이름을 exit 로 지정하면 프로세스가 끝날 때를 알 수 있다.

그 아래 코드는 setTimeout() 메소드를 호출하여 2초 후 프로그램을 끝낸다. 이를 실행하면 콘솔 창에 결과가 출력된다.

2초 후에 시스템 종료 시도함.
exit 이벤트 발생함.

 

그렇다면, 미리 정의되어 있는 이벤트가 아니라 우리가 직접 만든 이벤트는 어떻게 처리할 수 있을까?

앞에서 입력한 것과 비슷한 방식으로 다음 코드를 입력한다.

 

1
2
3
4
5
6
7
8
9
process.on('tick',function(count){
    console.log('tick 이벤트 발생함 : %s',count);
});
 
setTimeout(function(){
    console.log('2초 후에 tick 이벤트 전달 시도함.');
    
    process.emit('tick','2');
},2000);
cs

tick 이벤트를 직접 만들고 2초 후에 setTimeout() 메소드를 사용해 process.emit() 메소드를 호출하면서 tick 이벤트를 process 객체로 전달했다.

process.on() 메소드를 호출하여 이벤트를 등록하면 이 메소드를 호출하면서 파라미터로 전달한 tick 이벤트가 발생했을 때 그 다음에 나오는 콜백함수가 실행된다.

2초 후에 tick 이벤트 전달 시도함.
tick 이벤트 발생함 : 2

계산기 객체를 모듈로 만들어 보기

지금까지 실행해 본 코드만으로 한쪽에서 이벤트를 만들어 전달할 수 있고, 다른 쪽에서 그것을 받아서 처리할 수 있다는 것으 알게 되었다.

그런데 항상 process 객체를 사용해 이벤트를 전달한다면 같은 이름의 이벤트를 사용하는 경우에 충돌이 발생할 수 있다.

이 때문에 별도의 모듈 파일을 만들고 그 안에서 이벤트를 처리하도록 만드는 것이 좋다.

그러면 앞에서 다룬 모듈 구성 방법을 잘 생각하면서 새로운 모듈을 만들어본다.

 

계산기 객체를 모듈로 만들기 위해서 calc3.js 파일을 만들고 코드를 작성한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var util = require('util');
var EventEmitter = require('events').EventEmitter;
 
var Calc = function(){
    var self = this;
    
    this.on('stop'function(){
        console.log('Calc에 stop event 전달됨.');
    });
};
 
util.inherits(Calc,EventEmitter);
 
Calc.prototype.add = function(a,b){
    
    return a+b;
}
 
module.exports = Calc;
module.exports.title = 'calculator';
cs

EventEmitter 는 events 모듈 안에 정의되어 있다. 따라서, require() 메소드를 호출하여 events 모듈을 불러들인 후 그 안에 속성으로 들어 있는 EventEmitter 객체를 참조한다.

 

Calc 객체는 계산기 객체로서 function 키워드를 사용해 프로토타입 객체(Prototype Object)로 만든다.

프로토타입 객체 안에서는 this 키워드를 이용해 자기 자신을 가리킬 수 있으며, 그 객체 안에 정의된 속성에 접근할 수 있다. 

그런 다음 Calc 객체가 이벤트 처리를 할 수 있도록 EventEmitter를 상속하도록 만든다. 상속은 util 모듈에 있는 inherits() 메소드를 사용하면 쉽게 정의할 수 있다.

코드의 가장 위쪽에서 require()메소드를 호출하여 util 모듈을 불러왔기 때문에 util.inherits() 메소드를 호출하는 코드를 넣어도 오류는 발생하지 않는다.

 

Calc 객체 안에 들어있는 prototype 객체의 속성으로 add 함수를 추가하면 new 연산자를 이용해 Calc 객체의 인스턴스 객체를 만들었을 때, add()함수를 사용할 수 있다.

코드으이 마지막 부분에는 calc3.js 파일에 정의한 모듈을 불러들이는 쪽에서 Calc 객체를 참조할 수 있도록 module.exports  에 Calc 객체를 지정한다.

추가적으로 title 속성 값으로 calculator 라는 이름을 설정한다.

이 계산기 객체로 전달되는 stop 이벤트를 처리하기 위해서 Calc 객체 안에서 on() 메소드를 호출하는 부분도 눈여겨볼 수 있다.

 

이렇게 만든 모듈을 사용하는 코드는 다음과 같이 별도의 파일에 입력한다.

1
2
3
4
5
6
var Calc = require('./calc3');
 
var calc = new Calc();
calc.emit('stop');
 
console.log(Calc.title + '에 stop 이벤트 전달함.');
cs

require() 메소드를 호출하면서 ./calc3 을 파라미터로 전달하면 별도의 모듈 파일에 정의해둔 Calc 객체를 변수로 사용할 수 있다.

Calc 객체는 프로토타입 객체로 계산기 기능을 정의한 것이므로 먼저 new 연산자를 이용해 인스턴스 객체를 만든다.

Calc 객체가 EventEmitter 를 상속하므로 인스턴스 객체의 emit() 메소드를 호출하여 stop 이벤트를 전달한다.

 

Calc에 stop event 전달됨.
calculator에 stop 이벤트 전달함.

 

stop 이벤트가 정상적으로 전달된 것을 볼 수 있다.

 

프로그램을 만들 때는 이벤트를 받아서 처리하는 경우가 많다. 그러므로 지금 만들어 본 코드에 들어있는 on() 과 emit() 메소드에 대해서 잘 알아두는 것이 좋다.

Comments