async
에서 try-catch
로 전체 코드를 묶고 catch
문에서 throw e
하는 것과 try-catch
문을 아예 쓰지 않는것은
흐름상으로나 결과적으로나 완전히 같은 결과를 만들어냅니다.
const makeError = async () => { throw new Error('에러 클래스에 의한 에러') }
const withTryCatch = async () => {
try {
console.log('try-cath 를 사용한 async')
const result = await makeError();
console.log('withTryCatch - 에러가 발생하는 위치 아래에 있는 코드 (실행되면 안됨)');
return result;
} catch (err) {
throw err;
}
}
const withoutTryCatch = async () => {
console.log('try-cath 없는 async')
const result = await makeError();
console.log('withoutTryCatch - 에러가 발생하는 위치 아래에 있는 코드 (실행되면 안됨)');
return result;
}
withTryCatch()
.then(res => {
console.log('withTryCatch - 성공결과', res)
}).catch(err => {
console.log('withTryCatch - 실패결과', err.message)
});
withoutTryCatch()
.then(res => {
console.log('withoutTryCatch - 성공결과', res)
})
.catch(err => {
console.log('withoutTryCatch - 실패결과', err.message)
})
'try-cath 를 사용한 async'
Promise { <pending> }
'try-cath 없는 async'
Promise { <pending> }
'withTryCatch - 실패결과' '에러 클래스에 의한 에러'
'withoutTryCatch - 실패결과' '에러 클래스에 의한 에러'
try-catch
를 쓰든 안쓰든 상관없이
- 에러가 발생하는 코드 다음에 있던 코드들은 실행되지 않습니다.
- 발생한 에러는
Promise.reject
처리되어 상위 컨텍스트에서 비동기 에러로 처리됩니다.
따라서 상위 컨텍스트로 에러를 전파하기 위해 async
함수의 내부를 try-catch
로 묶을 필요는 없습니다.
try-catch 는 라우터에 의해 실행되는 최상위 실행 컨텍스트인 미들웨어 레이어에서만 수행하면 됩니다.
미들웨어에서는 에러를 상위 컨텍스트로 전달해도 받을 곳이 없으며,
에러발생시 next(error)
나 res.status(500).send
와 같이 클라이언트로 에러 결과를 응답하기 위한 로직을 수행하는게 더 바람직하기 때문입니다.
하지만 그 외의 async
함수에선 try-catch
를 매번 작성할 필요가 없습니다.
app.get('/foo', async (req, res, next) => {
try {
// 컨트롤러 로직
// 비동기 결과가 reject 라면 catch 문으로 갑니다.
const some = await something();
// 비동기 결과가 reject 라면 catch 문으로 갑니다.
const another = await anotherThing();
if (another.result > 30) {
// Promise.reject를 리턴해도 async 함수에선 에러가 던져진것과 동등한것으로 간주됩니다.
return Promise.reject({
message: '뭔가 비즈니스적으로 30을 초과하면 안되는 그런 것',
status: 403,
})
}
// 앞쪽에서 아무런 문제도 없어야 성공결과가 응답됩니다.
res.json(another);
} catch (err) {
// 여기에선 따로 throw err를 하지 않습니다.
// 상위 컨텍스트로 에러를 전파하는게 아니라 클라이언트로 에러를 응답해야 하는 레이어입니다.
res.status(err.status || 500).json({
message: err.message || 'unknown error'
})
}
});