- Different Types of Errors
- Handling Errors
- 에러가 발생했다고 무조건 app 이 멈출 필요는 없다
- 적절하게 에러를 처리하면 된다.
- Technical / Network Errors
- eg. MongoDB 서버 다운
- 해결 방법 : 유저에게 에러 페이지를 보여준다
- '예상된 에러'
- eg. 파일을 읽을 수 없거나 데이터베이스에서 파일을 읽을 수 없음
- 해결 방법 : 유저에게 알리고 가능하면 다시 시도하게 유도한다.
- Bugs / Logical 에러
- eg. 유저 객체가 존재하지 않을 때 사용하려고 한다.
- 해결 방법 : 개발중에 고친다
- 전반적인 에러 처리 흐름

-
시작하기 전에
node.js의 에러 핸들링 기능 살펴보기-
node.js는
throw new Error()를 사용해서 에러 처리가 가능하다.const sum = (a, b) => { if (a && b) { return a + b; } throw new Error('Invalid arguments'); }; console.log(sum(1)); /*C:\Users\kooks\Desktop\StudyInGit\AllaboutNode\Project1-2\test.js:5 throw new Error('Invalid arguments'); ^ Error: Invalid arguments at sum (C:\Users\kooks\Desktop\StudyInGit\AllaboutNode\Project1-2\test.js:5:9) at Object.<anonymous> (C:\Users\kooks\Desktop\StudyInGit\AllaboutNode\Project1-2\test.js:7:13) at Module._compile (internal/modules/cjs/loader.js:776:30) ... */
위와 같이 에러를 만들 수 있다.
-
try catch이용해서 에러 처리하기... try { console.log(sum(1)); } catch (erorr) { console.log('Error occurred!'); } console.log('Continue!');
try catch를 사용하게 되면 코드 실행을 멈추지 않고 계속해서 실행한다. 따라서 'Continue!' 라는 로그를 볼 수 있다.
-
-
app.js 아래 코드에 있는
catch문은 기술적 오류만 잡아 낼 수 있으므로 데이터베이스에user가 존재 하지 않을 때 오류를 걸러낼 수 없다. 이를 수정하기.app.use( session({ secret: 'my secret', resave: false, saveUninitialized: false, store: store }) ); app.use(csrfProtection); app.use(flash()); app.use((req, res, next) => { if (!req.session.user) { return next(); } User.findById(req.session.user._id) .then(user => { // user가 존재하지 않으면 아래 코드 건너 뛰기 if (!user) { return next(); } req.user = user; next(); }) .catch(err => { throw new Error(err); }); });
-
controllers/admin.js
postAddProduct수정하기MongoDB에 문제가 발생하면 전체 app이 멈춘다. 이 문제를 해결하기 위해
catch구문 수정하기exports.postAddProduct = (req, res, next) => { const title = req.body.title; const imageUrl = req.body.imageUrl; const price = req.body.price; const description = req.body.description; const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(422).render('admin/edit-product', { pageTitle: 'Add Product', path: '/admin/add-product', editing: false, hasError: true, product: { title: title, imageUrl: imageUrl, price: price, description: description }, errorMessage: errors.array()[0].msg }); } const product = new Product({ title: title, price: price, description: description, imageUrl: imageUrl, userId: req.user }); product .save() .then(result => { // console.log(result); console.log('Created Product'); res.redirect('/admin/products'); }) .catch(err => { res.redirect('/500') }); };
-
controllers/error.js
get500추가하기exports.get500 = (req, res, next) => { res.status(500).render('500', { pageTitle: '에러 ㅠㅠ', path: '/500', isAuthenticated: req.session.isLoggedIn }); };
-
app.js
500에러 페이지 라우팅 하기app.use('/500', errorController.get500);
익스프레스는 위에서 부타 아래로 실행된다는 것을 기억해야 한다. 오류 미들 웨어을 다른 모든 미들웨어의 뒤에 정의해야 한다. 그렇지 않으면 오류 처리기는 호출되지 않는다.
-
app.js 에러 처리 미들웨어 작성하기
// 보통 여기 미들웨어 까지 올 수 없지만 4개의 인자를 넣어주면 바로 // 여기로 도달하게 된다. app.use((error, req, res, next) => { res.redirect('/500'); });
-
각 catch 블락에 에러 코드 넣기
.catch(err => { // 500 서버사이드 오류 추가해주기 // res.redirect('/500'); const error = new Error(err); error.httpStatusCode = 500; // 다른 모든 미들웨어를 건너뛰고 error 처리 미들웨어로 이동한다. return next(error); });
- 200 번대 : 성공
- 300 번대 : Redirect
- 400 번대 : Client - side Error
- 500 번대 : Server - side Error