오늘도 개발
에러/오류 핸들링 본문
1. 에러(Error) VS 예외(Exception)
에러
컴퓨터가 내는 것.
ex) 문법 에러, 통신 장애 등.
consloe.log(1)
// Uncaught ReferenceError: consloe is not defined
예외
개발자가 의도적으로 내는 것.
코드 실행은 되지만 개발자가 봤을 때 정상이 아닌 상황.
ex) 비밀번호 정책이 10자인데 5자만 들어온 경우
2. 예외 핸들링
new 키워드와 Error() 생성자 사용.
throw 예외 오브젝트는 try-catch로 핸들링하지 않으면 전역 에러가 됨 => 프로그램 실행을 멈춤
const username = 'sue'
if (username.length < 5){
throw new Error('USERNAME_INVALID')
}
console.log(1)
// Error: USERNAME_INVALID at Object.<anonymous>
return 예외 오브젝트는 함수 실행만 중단하고 프로그램 실행은 멈추지 않음
const username = 'sue'
function validateUser(user){
if (username.length < 5){
throw new Error('USERNAME_INVALID')
}
}
validateUser(username)
console.log(1)
// 1
3. try-catch
예외도 에러도 try-catch문으로 처리할 수 있다.
try-catch를 사용하면 예외나 에러가 발생해도 프로그램을 중단하지 않는다.
try에는 에러가 발생할 수도 있는 코드를 작성하고, catch에는 에러가 발생했을 때 동작을 작성한다.
try {
const username = 'sue'
if (username.length < 5){
const error = new Error('USERNAME_INVALID')
error.statusCode = 400
throw error
}
} catch(error) {
console.log(error)
}
async 함수에서도 try-catch를 사용할 수 있는데, 이 때는 await을 같이 사용해야 한다.
또는 try-catch나 await 없이 promise-catch를 사용할 수도 있다.
async 함수의 반환값을 제대로 얻으려면 await이나 promise-then을 사용해야 하는 것과 같은 이유 때문이다.
우선 async 함수에 await, promise-catch를 사용하지 않은 경우를 살펴보자.
async function example(param){
if (!param){
throw new Error('NoParameterError');
}
return param
}
try {
const someValue = example();
// someValue에는 rejected된 Promise 객체가 할당됨
console.log(someValue);
}
catch(error){
// example의 NoParmeterError가 안 잡힘
console.log('--Handling error--') // 실행 안 됨
console.log(error); // 실행 안 됨
}
console.log('프로그램 실행 끝')
// 1. Promise 객체 반환
// Promise { <rejected> Error: NoParameterError...
// 2. 프로그램을 끝까지 실행
// 프로그램 실행 끝
// 3. Promise 실행 중 에러 발생, 핸들링할 catch 구문이 없음 => 전역 에러가 됨 => 프로그램 실행 중단
// Error: NoParameterError
await을 사용하면 catch가 제대로 async 함수의 에러/오류를 잡아서 핸들링할 수 있다.
async function example(param){
if (!param){
throw new Error('NoParameterError');
}
return param
}
// await은 async 함수 내에서만 쓸 수 있으므로 함수로 감싸줌
async function caller(){
try {
const someValue = await example();
// Promise 객체 실행 중 에러 발생 => catch 블록으로 넘어감
console.log(someValue);
}
catch(error){
console.log('--Handling error--')
console.log(error);
}
}
caller()
console.log('프로그램 실행 끝')
// 프로그램 실행 끝
// --Handling error--
// Error: NoParameterError
try-catch와 await 대신 promise의 catch() 함수를 사용할 수도 있다.
async function example(param){
if (!param){
throw new Error('NoParameterError');
}
return param
}
example()
.then((result) => {
console.log(result)
})
.catch((error) => {
console.log('--Handling error--')
console.log(error);
})
console.log('프로그램 실행 끝')
// 프로그램 실행 끝
// --Handling error--
// Error: NoParameterError
4. express 미들웨어로 에러 핸들링
express에는 에러를 핸들링하는 자체 코드가 있어서
명시적으로 에러를 핸들링하지 않으면 express가 알아서 처리해준다.
// <func.js>
function example(param){
if (!param){
throw new Error('NoParameterError');
}
return param
}
async function asyncExample(param){
if (!param){
throw new Error('NoParameterError');
}
return param
}
module.exports = { example, asyncExample }
// <server.js>
const express = require('express');
const { example, asyncExample } = require('./func');
const app = express();
app.get('/example', (req, res) => {
const someValue = example();
res.json({result : someValue})
})
app.get('/async_example', async (req, res) => {
const someValue = await asyncExample();
res.json({result: someValue})
})
app.listen(8000)
// /example에 요청을 보내면 자동으로 500 에러와 에러 메시지(Error: NoParameterError)를 응답한다.
// /async_example에 요청을 보내면 응답을 보내지 않고 프로그램을 종료한다. 비동기 함수의 에러는 자동으로 핸들링할 수 없는 것 같다.
미들웨어를 추가하면 에러를 편리하게 일괄적으로 핸들링할 수 있다.
const express = require('express');
const { example, asyncExample } = require('./func');
const app = express();
app.get('/example', (req, res) => {
const someValue = example();
res.json({result : someValue})
})
app.get('/async_example', async (req, res) => {
const someValue = await asyncExample();
res.json({result: someValue})
})
app.use((err, req, res, next) => {
if (err.message === 'NoParameterError'){
res.status(400).json({message: '오류 발생! param이 없음'})
return;
}
res.status(500).json({message: '오류 발생! 원인 모름'})
})
app.listen(8000, () => {
console.log('listening at 8000')
})
// /example에 요청을 보내면 400 에러와 {message: '오류 발생! param이 없음'}을 응답한다.
// /async_example에 요청을 보내면 응답을 보내지 않고 프로그램을 종료한다.
미들웨어나 express 자체 기능을 사용하지 않고 수동으로 try-catch문을 사용할 수도 있다.
const express = require('express');
const { example, asyncExample } = require('./func');
const app = express();
app.get('/example', (req, res) => {
const someValue = example();
res.json({result : someValue})
})
app.get('/async_example', async (req, res) => {
try{
const someValue = await asyncExample();
res.json({result: someValue})
}
catch(err){
res.status(400).json({message: '오류 발생! param이 없음'})
return;
}
})
app.listen(8000, () => {
console.log('listening at 8000')
})
// async_example에 요청을 보내면 400 에러와 {message: '오류 발생! param이 없음'}을 응답함'웹 프로그래밍 > Javascript' 카테고리의 다른 글
| Node.js에서 인증, 인가 진행하기(bcrypt, jwt) (0) | 2022.09.29 |
|---|---|
| Middleware (0) | 2022.09.28 |
| 자바스크립트와 비동기 프로그래밍(콜백 함수, Promise, async/await) (0) | 2022.09.27 |
| Node.js에서 express 사용하기 - 3. dbmate로 마이그레이션하기 (1) | 2022.09.24 |
| Node.js에서 express 사용하기 - 2. TypeORM으로 데이터베이스 연결하기 (0) | 2022.09.23 |