ES6 Promise 체이닝에서 에러 핸들링 개선하기
문제 상황
회원가입 플로우에서 여러 API를 순차적으로 호출하는 과정에서 에러가 발생했을 때, 어느 단계에서 실패했는지 파악하기 어려웠다.
fetch('/api/user')
.then(res => res.json())
.then(user => fetch(`/api/profile/${user.id}`))
.then(res => res.json())
.then(profile => updateUI(profile))
.catch(err => console.error(err));
위 코드는 어느 fetch가 실패했는지, JSON 파싱이 실패했는지 구분이 안 됐다.
해결 방법
각 단계마다 명시적인 에러 정보를 추가하고, 커스텀 에러 객체를 사용했다.
class APIError extends Error {
constructor(message, stage, response) {
super(message);
this.stage = stage;
this.response = response;
}
}
fetch('/api/user')
.then(res => {
if (!res.ok) throw new APIError('User fetch failed', 'USER_FETCH', res);
return res.json();
})
.then(user => {
return fetch(`/api/profile/${user.id}`)
.then(res => {
if (!res.ok) throw new APIError('Profile fetch failed', 'PROFILE_FETCH', res);
return res.json();
});
})
.then(profile => updateUI(profile))
.catch(err => {
if (err instanceof APIError) {
console.error(`Failed at ${err.stage}:`, err.message);
showErrorToUser(err.stage);
} else {
console.error('Unexpected error:', err);
}
});
결과
에러 로그에서 실패 지점을 즉시 파악할 수 있게 되었고, 사용자에게도 구체적인 에러 메시지를 보여줄 수 있게 되었다. Promise 체이닝이 깊어질수록 이런 패턴의 효과가 컸다.