async/await 패턴으로 Promise 체이닝 개선하기

문제 상황

사용자 인증 후 프로필 정보를 가져오는 API 호출 로직이 Promise 체이닝으로 작성되어 있었다. 3~4단계의 체이닝이 이어지면서 코드 파악이 어려웠고, 중간 단계에서 에러가 발생할 경우 디버깅이 쉽지 않았다.

function getUserData(userId) {
  return fetchUser(userId)
    .then(user => {
      return fetchProfile(user.profileId);
    })
    .then(profile => {
      return fetchSettings(profile.settingsId);
    })
    .then(settings => {
      return { profile, settings }; // profile 참조 불가
    })
    .catch(error => {
      console.error('Error:', error);
    });
}

해결 방법

Node 8부터 정식 지원되는 async/await 패턴으로 전환했다. Babel 설정을 통해 프로젝트 전체에 적용 가능하도록 환경을 구성했다.

async function getUserData(userId) {
  try {
    const user = await fetchUser(userId);
    const profile = await fetchProfile(user.profileId);
    const settings = await fetchSettings(profile.settingsId);
    
    return { profile, settings };
  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
}

변수 스코프 문제가 해결되었고, try-catch로 에러 핸들링이 명확해졌다. 특히 중간 변수들을 자유롭게 참조할 수 있어 불필요한 클로저나 변수 전달이 사라졌다.

병렬 처리 최적화

순차 실행이 필요 없는 경우 Promise.all을 활용해 성능도 개선했다.

async function getDashboardData(userId) {
  const [user, notifications, activities] = await Promise.all([
    fetchUser(userId),
    fetchNotifications(userId),
    fetchActivities(userId)
  ]);
  
  return { user, notifications, activities };
}

기존 체이닝 방식 대비 약 40% 응답 시간이 단축되었다. 팀 내에서 async/await 패턴을 표준으로 채택하기로 결정했다.