3.7 이벤트 이해하기
스트림을 할 때 on('data', 콜백) 또는 on('end', 콜백)을 사용했다.
바로 data라는 이벤트와 end라는 이벤트가 발생할 때 콜백 함수를 호출하도록 이벤트를 등록한 것이다.
createReadStream같은 경우 내부적으로 이벤트를 호출하지만 직접 이벤트를 만들 수도 있다.
const EventEmitter = require('events');
const myEvent = new EventEmitter();
myEvent.addListener('event1', () => {
console.log('이벤트 1');
});
myEvent.on('event2', () => {
console.log('이벤트 2');
});
myEvent.on('event2', () => {
console.log('이벤트 2 추가');
});
myEvent.once('event3', () => {
console.log('이벤트 3');
}); // 한 번만 실행됨
myEvent.emit('event1'); // 이벤트 호출
myEvent.emit('event2'); // 이벤트 호출
myEvent.emit('event3');
myEvent.emit('event3'); // 실행 안 됨
myEvent.on('event4', () => {
console.log('이벤트 4');
});
myEvent.removeAllListeners('event4');
myEvent.emit('event4'); // 실행 안 됨
const listener = () => {
console.log('이벤트 5');
};
myEvent.on('event5', listener);
myEvent.removeListener('event5', listener);
myEvent.emit('event5'); // 실행 안 됨
console.log(myEvent.listenerCount('event2'));
/* 실행 결과
이벤트 1
이벤트 2
이벤트 2 추가
이벤트 3
2
*/
on(이벤트명, 콜백): 이벤트 이름과 이벤트 발생 시의 콜백을 연결한다. 이렇게 연결하는 동작을 이벤트 리스닝이라고 한다. event2처럼 이벤트 하나에 이벤트 여러 개를 달아줄 수도 있다.
addListener(이벤트명, 콜백): on과 기능이 같다.
emit(이벤트명): 이벤트를 호출하는 메서드이다. 이벤트 이름을 인수로 넣으면 미리 등록해뒀던 이벤트 콜백이 실행된다.
once(이벤트명, 콜백): 한 번만 실행되는 이벤트이다.
removeAllListeners(이벤트명): 이벤트에 연결된 모든 이벤트 리스너를 제거한다.
removeListener(이벤트명, 리스너): 이벤트에 연결된 리스너를 하나씩 제거한다.
off(이벤트명, 콜백): 노드 10 버전에서 추가된 메서드로, removeListener와 기능이 같다.
listenerCount(이벤트명): 현재 리스너가 몇 개 연결되어 있는지 확인한다.
3.8 예외 처리하기
예외란 보통 처리하지 못한 에러를 말한다.
이러한 예외들은 실행 중인 노드 프로세스를 멈추게 만든다.
멀티 스레드 프로그램에서는 스레드 하나가 멈추면 그 일을 다른 스레드가 하지만 노드의 메인 스레드는 하나뿐이므로 메인 스레드가 멈춘다는 것은 서버가 멈춘다는 뜻과도 같다.
setInterval(() => {
console.log('시작');
try {
throw new Error('서버를 고장내주마!');
} catch (err) {
console.error(err);
}
}, 1000);
/* 실행 결과
시작
Error: 서버를 고장내주마!
...
시작
Error: 서버를 고장내주마!
*/
에러를 강제적으로 발생시켰다.
에러는 발생하지만 try/catch로 잡을 수 있고 멈추기 전까지 계속 실행된다.
이렇게 에러가 발생할 것 같은 부분을 try/catch로 미리 감싼다.
const fs = require('fs');
setInterval(() => {
fs.unlink('./abcdefg.js', (err) => {
if (err) {
console.error(err);
}
});
}, 1000);
/* 실행 결과
[Error: ENOENT: no such file or directory, unlink 'C:\Users\zerocho\abcdefg.js'] {
errno: -4058,
code: 'ENOENT',
syscall: 'unlink',
path: 'C:\\Users\\zerocho\\abcdefg.js'
}
[Error: ENOENT: no such file or directory, unlink 'C:\Users\zerocho\abcdefg.js'] {
errno: -4058,
code: 'ENOENT',
syscall: 'unlink',
path: 'C:\\Users\\zerocho\\abcdefg.js'
}
*/
fs.unlink로 존재하지 않는 파일을 지운다. 에러가 발생하지만 노드 내장 모듈의 에러는 실행 중인 프로세스에서 멈추지 않는다.
process.on('uncaughtException', (err) => {
console.error('예기치 못한 에러', err);
});
setInterval(() => {
throw new Error('서버를 고장내주마!');
}, 1000);
setTimeout(() => {
console.log('실행됩니다');
}, 2000);
process 객체에 uncaughtException 이벤트 리스너를 달았다.
처리하지 못한 에러가 발생했을 때 이벤트 리스너가 실행되고 프로세스가 유지된다.
만약 이 부분이 없으면 setTimeout이 실행되지 않고 에러가 발생해 멈추게된다.
따라서 uncaughtException은 단순히 에러 내용을 기록하는 정도로 사용하고, 에러를 기록한 후 process.exit()으로 프로세스를 종료하는 것이 좋다.
3.8.1 자주 발생하는 에러들
node: command not found: 노드를 설치했지만 이 에러가 발생하는 경우 환경 변수가 제대로 설정되어 있지 않은 것이다.
ReferenceError: 모듈 is not defined: 모듈을 require했는지 확인한다.
Error: Cannot find module 모듈명: 해당 모듈을 require했지만 설치하지 않았다.
Error [ERR_MODULE_NOT_FOUND]: 존재하지 않는 모듈을 불러오려 할 때 발생한다.
Error: Can't set headers after they are sent: 요청에 대한 응답을 보낼 때 응답을 두 번 이상 보냈다. 요청에 대한 응답은 한 번만 보내야 한다.
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed- JavaScript heap out of memory: 코드를 실행할 때 메모리가 부족해서 스크립트가 정상적으로 작동하지 않는 경우이다.
UnhandledPromiseRejectionWarning: Unhandled promise rejection: 프로미스 사용 시 catch 메서드를 붙이지 않으면 발생한다.
EADDRINUSE 포트 번호: 해당 포트 번호에 이미 다른 프로세스가 연결되어 있다.
// 윈도에서 프로세스 종료하기
$ netstat -ano | findstr 포트
$ taskkill /pid 프로세스아이디 /f
// 맥, 리눅스에서 프로세스 종료하기
$ lsof -i tcp:포트
$ kill -9 프로세스아이디
EACCES 또는 EPERM: 노드가 작업을 수행하는 데 권한이 충분하지 않다.
EJSONPARSE: package.json 등의 JSON 파일에 문법 오류가 있을 때 발생한다.
ECONNREFUSED: 요청을 보냈으나 연결이 성립하지 않을 때 발생한다.
ETARGET: package.json에 기록한 패키지 버전이 존재하지 않을 때 발생한다.
ETIMEOUT: 요청을 보냈으나 응답이 시간 내에 오지 않을 때 발생한다.
ENOENT: no such file or directory: 지정한 폴더나 파일이 존재하지 않는 경우이다.
'Programming > NodeJS' 카테고리의 다른 글
Node.js 교과서 [npm] #5 (0) | 2024.02.10 |
---|---|
Node.js 교과서 [요청과 응답] #4 (1) | 2024.02.04 |
Node.js 교과서 [파일 시스템] #3.3 (0) | 2024.02.04 |
Node.js 교과서 [노드 내장 모듈] #3.2 (0) | 2024.02.04 |
Node.js 교과서 [REPL, 모듈, 노드 내장 객체] #3 (1) | 2024.02.04 |