JavaScript 비동기 처리, Promise에서 async/await로 전환

배경

프로젝트에서 API 호출 로직이 Promise 체이닝으로 복잡하게 얽혀있었다. 특히 여러 API를 순차적으로 호출하는 부분에서 .then()이 4~5단계로 중첩되어 가독성이 떨어졌다.

기존 코드

function getUserData(userId) {
  return fetchUser(userId)
    .then(user => {
      return fetchUserPosts(user.id)
        .then(posts => {
          return fetchPostComments(posts[0].id)
            .then(comments => {
              return { user, posts, comments };
            });
        });
    })
    .catch(error => {
      console.error('Error:', error);
      throw error;
    });
}

async/await로 전환

async function getUserData(userId) {
  try {
    const user = await fetchUser(userId);
    const posts = await fetchUserPosts(user.id);
    const comments = await fetchPostComments(posts[0].id);
    return { user, posts, comments };
  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
}

중첩이 사라지고 동기 코드처럼 읽힌다. try/catch로 에러 처리도 일관성있게 가능하다.

병렬 처리

순차 처리가 필요없는 경우 Promise.all을 함께 사용했다.

async function getMultipleUsers(userIds) {
  try {
    const users = await Promise.all(
      userIds.map(id => fetchUser(id))
    );
    return users;
  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
}

주의사항

  • forEach 내부에서 await 사용 불가 (for...of 사용)
  • 에러 처리를 빼먹으면 unhandled rejection 발생
  • Babel preset-env 설정 필요 (target 브라우저 확인)

결과

팀 내 코드 리뷰에서 가독성이 좋다는 피드백을 받았다. 신규 API 호출 로직은 모두 async/await로 작성하기로 컨벤션을 정했다.