안녕하세요, 코린이의 코딩 학습기 채니 입니다.
[Node.js 교과서]의 책을 참고하여 포스팅한 개인 공부 내용입니다.
노드 기능 알아보기
이벤트 이해하기
event.js
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); // 반드시 listener 넣어야함
myEvent.emit("event5"); // 실행 안됨
console.log(myEvent.listenerCount("event2"));
@콘솔출력값
$ node part3/event
이벤트1
이벤트2
이벤트2 추가
이벤트3
2
- on(이벤트명, 콜백)
: 이벤트 이름과 이벤트 발생 시 콜백 연결 (이벤트 리스닝)
이벤트 하나에 이벤트 여러 개를 달아줄 수도 있음 - addListener(이벤트명, 콜백)
: on과 동일한 기능 - emit(이벤트명)
: 이벤트 호출하는 메소드, 이벤트 이름을 인수로 넣으면 등록해둔 이벤트 콜백 실행 - once(이벤트명, 콜백)
: 한 번만 실행되는 이벤트 - removeAllListeners(이벤트명)
: 이벤트에 연결된 모든 이벤트 리스너 제거 - removeListener(이벤트명, 리스너)
: 이벤트에 연결된 리스너를 하나씩 제거, 반드시 리스너를 넣어야함 - off(이벤트명, 콜백)
: removeListener와 동일한 기능 - listenerCount(이벤트명)
: 현재 리스너가 몇 개 연결되어 있는지 확인
예외 처리하기
- 예외는 처리하지 못한 에러를 의미 → 실행 중인 노드 프로세스를 멈추게 함
- 에러 로그가 기록되더라도 작업은 계속 진행 되어야 함
error1.js
setInterval(() => {
console.log("시작");
try {
throw new Error("서버를 고장내주마");
} catch (err) {
console.error(err);
}
}, 1000);
@콘솔출력값
$ node part3/error1
시작
Error: 서버를 고장내주마
at Timeout._onTimeout (/Users/parkchaeeun/project/playground-cepark/part3/error1.js:4:11)
at listOnTimeout (node:internal/timers:564:17)
at process.processTimers (node:internal/timers:507:7)
시작
Error: 서버를 고장내주마
at Timeout._onTimeout (/Users/parkchaeeun/project/playground-cepark/part3/error1.js:4:11)
at listOnTimeout (node:internal/timers:564:17)
at process.processTimers (node:internal/timers:507:7)
... 반복
setInterval를 이용해 프로세스가 멈추는 지 확인해보니, 에러가 발생해도 멈추지 않고 try/catch로 에러를 잡아 정상 실행되는 것을 확인할 수 있습니다.
error2.js
const fs = require("fs"); // 파일 시스템에 접근하는 모듈
setInterval(() => {
fs.unlink("./abcdefg.js", (err) => {
if (err) {
console.error(err);
}
});
}, 1000);
@콘솔출력값
$ node part3/error2
[Error: ENOENT: no such file or directory, unlink './abcdefg.js'] {
errno: -2,
code: 'ENOENT',
syscall: 'unlink',
path: './abcdefg.js'
}
[Error: ENOENT: no such file or directory, unlink './abcdefg.js'] {
errno: -2,
code: 'ENOENT',
syscall: 'unlink',
path: './abcdefg.js'
}
... 반복
fs.unlink로 존재하지 않는 파일을 삭제하고 있습니다.
에러가 발생하지만 노드 내장 모듈의 에러는 실행 중인 프로세스를 멈추게 하지 않아 정상 실행 되는 것을 확인할 수 있습니다.\\
error3.js
const fs = require("fs").promises;
setInterval(() => {
fs.unlink("./abcdefg.js").catch(console.error);
}, 1000);
@콘솔출력값
$ node part3/error3
[Error: ENOENT: no such file or directory, unlink './abcdefg.js'] {
errno: -2,
code: 'ENOENT',
syscall: 'unlink',
path: './abcdefg.js'
}
[Error: ENOENT: no such file or directory, unlink './abcdefg.js'] {
errno: -2,
code: 'ENOENT',
syscall: 'unlink',
path: './abcdefg.js'
}
프로미스의 에러는 반드시 catch 해야합니다. 그렇지 않으면 에러와 함께 노드 프로세스가 종료됩니다.
프로미스의 에러를 catch로 잡으니 에러는 발생 되지만 정상 실행 되는 것을 확인할 수 있습니다.
error4.js
process.on("uncaughtException", (err) => {
console.error("예기치 못한 에러", err);
});
setInterval(() => {
throw new Error("서버를 고장내주마~");
}, 1000);
setInterval(() => {
console.log("실행됩니다.");
}, 2000);
@콘솔출력값
$ node part3/error4
예기치 못한 에러 Error: 서버를 고장내주마~
at Timeout._onTimeout (/Users/parkchaeeun/project/playground-cepark/part3/error4.js:6:9)
at listOnTimeout (node:internal/timers:564:17)
at process.processTimers (node:internal/timers:507:7)
실행됩니다.
예기치 못한 에러 Error: 서버를 고장내주마~
at Timeout._onTimeout (/Users/parkchaeeun/project/playground-cepark/part3/error4.js:6:9)
at listOnTimeout (node:internal/timers:564:17)
at process.processTimers (node:internal/timers:507:7)
예기치 못한 에러 Error: 서버를 고장내주마~
at Timeout._onTimeout (/Users/parkchaeeun/project/playground-cepark/part3/error4.js:6:9)
at listOnTimeout (node:internal/timers:564:17)
at process.processTimers (node:internal/timers:507:7)
실행됩니다.
... 반복
process 객체에 uncaughtException 이벤트 리스너를 달았고, 처리하지 못한 에러가 발생 했을 때 이벤트 리스너가 실행되고 프로세스가유지되는 것을 확인할 수 있습니다.
try/catch로 에러를 잡지 않아도 코드가 제대로 실행되었습니다.
uncaughtException 이벤트 리스너로 모든 에러를 처리할 수 있을 것 같지만, 공식 문서에는 해당 방법을 최후의 수단으로 사용하라고 합니다.
해당 이벤트 발생 후 다음 동작이 제대로 동작하는지를 보증하지 않기 때문입니다.
따라서 uncaughtException은 에러 내용을 기록하는 정도로 사용하고 process.exit()로 프로세스를 종료하는 것이 좋다고 합니다.
자주 발생하는 에러들
- node: command not found
: 노드를 설치했지만, 해당 에러가 발생하는 경우 환경 변수가 제대로 설정되어 있지 않은 것
환경 변수에는 노드가 설치된 경로가 포함되어야 하고, node 외 다른 명령어도 마찬가지! - ReferenceError: 모듈 is not defined
: 모듈을 require 했는지 확인 - Error [ERR_MODULE_NOT_FOUNT]
: 존재하지 않는 모듈을 불러오려 할 때 발생 - 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 포트번호
: 해당 포트번호에 이미 다른 프로세스가 연결되어있을 때 발생
해당 프로세스를 종료하거나 다른 포트 번호 사용 - EACCES 또는 EPERM
: 노드가 작업을 수행하는 데 권한이 충분하지 않을 때 발생
파일/폴더 수정, 삭제, 생성 권한을 확인하거나 맥이나 리눅스라면 명령어 앞에 sudo를 붙이는 것도 방법 - EJSONPARSE
: package.json등의 JSON 파일에 문법 오류가 있을 때 발생 - ECONNREFUSED
: 요청을 보냈으나 연결이 성립하지 않을 때 발생 - ETARGET
: package.json에 기록한 패키지 버전이 존재하지 않을 때 발생 - ETIMEOUT
: 요청을 보냈으나 응답이 시간 내에 오지 않을 때 발생 - ENOENT: no such file or directory
: 지정한 폴더나 파일이 존재하지 않는 경우 발생
'JavaScript > Node.js' 카테고리의 다른 글
Node) http 모듈로 서버 만들기 - 쿠키와 세션, https와 http2, cluster (0) | 2022.12.28 |
---|---|
Node) http 모듈로 서버 만들기 - 요청과 응답 이해하기, REST와 라우팅 이용하기 (0) | 2022.12.27 |
Node) 노드 기능 알아보기 - 노드 내장 모듈 사용하기 (1) | 2022.12.27 |
Node) 노드 기능 알아보기 - 노드 내장 객체 알아보기 (0) | 2022.12.27 |
Node) 노드 기능 알아보기 - REPL, 모듈 사용하기 (1) | 2022.12.27 |