자바스크립트 Promise 체이닝과 에러 처리 패턴
문제 상황
레거시 코드에서 여러 API를 순차적으로 호출하는 부분이 콜백 중첩으로 가독성이 떨어졌다. 에러 처리도 각 콜백마다 흩어져 있어 유지보수가 어려웠다.
getUser(userId, (err, user) => {
if (err) return handleError(err);
getProfile(user.id, (err, profile) => {
if (err) return handleError(err);
getSettings(profile.id, (err, settings) => {
if (err) return handleError(err);
// 최종 처리
});
});
});
Promise 체이닝으로 개선
Promise를 사용하면 체이닝으로 순차 처리를 평탄하게 표현할 수 있다.
getUser(userId)
.then(user => getProfile(user.id))
.then(profile => getSettings(profile.id))
.then(settings => {
// 최종 처리
})
.catch(error => {
handleError(error);
});
중간 에러 복구 패턴
특정 단계에서 에러가 나도 기본값으로 계속 진행하고 싶을 때가 있다.
getUser(userId)
.then(user => getProfile(user.id))
.catch(err => {
// 프로필 조회 실패 시 기본값 반환
return { id: null, name: 'Unknown' };
})
.then(profile => getSettings(profile.id))
.catch(handleError);
첫 번째 catch는 getProfile 에러만 처리하고, 두 번째 catch는 전체 체인의 에러를 처리한다.
Promise.all로 병렬 처리
독립적인 API 호출은 병렬로 처리해 성능을 개선했다.
Promise.all([
getUser(userId),
getNotifications(userId),
getRecentPosts(userId)
])
.then(([user, notifications, posts]) => {
// 모두 완료 후 처리
})
.catch(handleError);
하나라도 실패하면 catch로 넘어가므로, 일부 실패를 허용하려면 각 Promise에 catch를 붙여야 한다.
결론
Promise 체이닝으로 코드 가독성이 크게 개선됐다. async/await가 Stage 3이라 프로덕션에선 아직 사용하지 않지만, Babel로 트랜스파일하면 쓸 수 있을 것 같다. 다음엔 async/await 패턴을 테스트해볼 예정이다.