
3_16. 에러 처리하기 - 복습
node_study2
2022.12.28.
3_16. 에러 처리하기 - 복습
노드는 싱글 스레드이기 때문에 에러가 발생하면 프로그램이 멈출 수 있다.
항상 에러 처리를 해줘서 에러 발생시 어떻게 해야될지 정해줘야 된다.
3_16_1. 예외 처리
- 참고로 자바스크립트는 에러랑 예외랑 큰 차이가 없다.
- 다른 언어는 예외는 Exception, 에러는 Error로 다른 객체로 구분하기도 하는데, 자바스크립트는 둘 다 에러라고 생각하면 된다.
- 예외(Exception): 처리하지 못한 에러
- 노드 스레드를 멈춘다.
- 노드는 기본적으로 싱글 스레드라 스레드가 멈춘다는 것은 프로세스가 멈춘다는 것이다.
- 에러 처리는 필수다.
3_16_2. try catch 문
- 기본적으로
try catch문으로 예외를 처리한다.- 에러가 발생할 만한 곳을
try catch로 감싼다.
- 에러가 발생할 만한 곳을
setInterval(() => {
console.log('시작');
try {
throw new Error('서버를 고장내주마!');
} catch (err) {
// 위에서 강제 에러 발생시킨 것을 여기서 받는다.
// 여기 바깥에는 아무런 영향을 끼치지 않는다.
// 에러가 발생했지만 프로그램은 멀쩡하다는 뜻이다.
console.error(err);
}
}, 1000)
- 위와 같이 작성하면 에러가
catch문에서 잡혀 프로그램에 영향을 끼치지 않게 된다.
때문에 지속해서 1초마다 위 코드가 실행된다. (setInterval) - 모든 곳을
try catch로 감싸면 되나?- 그래도 되긴 하지만 그러면 에러 발생 부분이 아닌데, 과도한 에러 처리로 인해 코드가 복잡해질 수도 있다.
- 에러 처리를 해야되는 부분인지 아닌지를 구분할 수 있어야 한다.
3_16_3. 노드 비동기 메서드의 에러는 따로 처리하지 않아도 된다.
- 콜백 함수에서 에러 객체를 제공한다.
- 이미 아래와 같이 에러 객체를 넘겨주기 때문에 따로 처리하지 않아도 프로그램이 멈추지 않는다.
- 그럼에도 불구하고 아래처럼
if문에서 한번 로그에는 에러가 찍히도록 처리를 해준다.
const fs = require('fs');
const path = require('path');
setInterval(() => {
fs.unlink(path.join(__dirname, 'abcdefg.js'), err => {
if (err) {
console.error(err);
}
})
}, 1000)
3_16_4. fs.promises 의 에러는 따로 처리하지 않아도 된다.
- 버전이 올라가면 동작이 바뀔 수도 있다.
- 노드의
fs.promises - 아래
try catch를 안 붙여도 서비스가 멈추진 않는다. - 그런데 앞으로
fs.promises에try catch를 안 붙이면 강제 종료시킬 수도 있다고 공지한 상태이다. - 항상
try catch같은 예외 처리하는 습관을 들이자.
노드 버전 올라갔을 때 갑자기 프로그램이 망가질 수도 있다.
- 노드의
const fs = require('fs').promises;
const path = require('path');
setInterval(() => {
fs.unlink(path.join(__dirname, 'abcdefg.js'));
}, 1000)
3_16_5. uncaughtException - 최후의 수단으로 사용
- 콜백 함수의 동작이 보장되지 않는다.
- 따라서 복구 작업용으로 쓰는 것은 부적합하다.
- 에러 내용 기록 용으로만 쓰는 게 좋다.
모든 코드에 try catch 처리는 복잡하다.
아래처럼 한 번에 처리할 수 있는 방법도 있다. (uncaughtException)
process.on('uncaughtException', err => {
console.error('예기치 못한 에러', err);
})
setInterval(() => {
throw new Error('서버를 고장내주마!');
}, 1000);
setTimeout(() => {
console.log('실행됩니다.');
}, 2000);
3_16_6. 위와 같이 모든 에러를 한 번에 처리하는 방식이 맞는 방법일까?
이렇게 모든 에러를 한 번에 처리하는 걸 맞는 해결책이라고 생각하면 안되는게 uncaughtException 여기서 에러를 감지했다는 것은 어딘가에 에러가 있다는 것이다.
서비스 자체에 에러가 있다는 것이니깐 그 에러는 결국 해결을 해야된다.
그런데 이 uncaughtException 부분은 단순히 에러를 기록해주는 부분일 뿐이다.
process.on('uncaughtException', err => {
console.error('예기치 못한 에러', err);
})그리고 위 콜백 함수에서 모든 내용이 동작한다는 것을 보장하지 못한다고도 노드 공식 문서에 적혀있다.
그래서 에러가 났을 때 복구를 하는 코드는 위 콜백 함수에 적으면 안된다.
위 코드는 에러 알림, 기록용으로만 쓰고 에러를 인지했을 때 최대한 빨리 그 에러를 수정하는 것이 좋을 것이다.
3_16_7. 프로세스 종료하기
- 윈도우
# 내 노드 서버가 몇 번 포트를 사용하고 있는지 알기위한 명령어
> netstat -ano | findstr 포트번호
# 알아내면 노드 서버의 아이디(프로세스 아이디)가 나온다.
# 아니면 process.pid 를 통해 프로세스 아이디를 알 수 있다.
> taskkill /pid 프로세스아이디 /f- 맥, 리눅스
# 내 노드 서버가 몇 번 포트를 사용하고 있는지 알기 위한 명령어
> lsof -i tcp:포트번호
# 알아내면 노드 서버의 아이디(프로세스 아이디)가 나온다.
# 아니면 process.pid 를 통해 프로세스 아이디를 알 수 있다.
> kill -9 프로세스아이디