JavaScript 비동기 에러 핸들링 - async/await의 try-catch 패턴
문제 상황
API 호출 코드를 Promise 체이닝에서 async/await으로 리팩토링하던 중, 에러 핸들링 코드가 지나치게 반복되는 문제가 생겼다. 모든 함수마다 try-catch를 감싸니 보일러플레이트가 늘어났다.
기존 코드
function fetchUserData(userId) {
return fetch(`/api/users/${userId}`)
.then(res => res.json())
.catch(err => {
logger.error(err);
throw err;
});
}
async/await 전환 후
async function fetchUserData(userId) {
try {
const res = await fetch(`/api/users/${userId}`);
return await res.json();
} catch (err) {
logger.error(err);
throw err;
}
}
해결 방법
고차 함수를 만들어 에러 핸들링을 분리했다.
const asyncHandler = (fn) => async (...args) => {
try {
return await fn(...args);
} catch (err) {
logger.error(err);
throw err;
}
};
const fetchUserData = asyncHandler(async (userId) => {
const res = await fetch(`/api/users/${userId}`);
return await res.json();
});
Express 라우터에서도 활용했다.
router.get('/users/:id', asyncHandler(async (req, res) => {
const user = await User.findById(req.params.id);
res.json(user);
}));
결과
- 비즈니스 로직과 에러 핸들링 분리
- 반복 코드 제거
- 에러 로깅을 한 곳에서 관리
다만 특정 에러만 처리하고 싶을 때는 여전히 try-catch를 직접 써야 한다. 상황에 맞게 선택해서 사용하면 될 것 같다.