💻데브노트소개
🎨

자바스크립트 비동기 완벽 가이드: Promise와 async/await 제대로 쓰기

데브노트 편집팀·2026.06.19·6분 읽기
X(트위터)
ADVERTISEMENT

자바스크립트는 싱글 스레드지만, 네트워크 요청·타이머·파일 읽기 같은 작업을 멈추지 않고 처리합니다. 이를 가능하게 하는 것이 비동기(asynchronous) 처리입니다. 과거 콜백 함수가 중첩되며 생기던 '콜백 지옥'은 Promise와 async/await가 등장하며 해결됐습니다. 가장 흔한 실수는 비동기 함수의 결과를 동기처럼 다루려다 undefinedPromise {<pending>}를 만나는 것입니다.

Promise의 3가지 상태

Promise는 비동기 작업의 최종 결과를 담는 객체로, 세 가지 상태를 가집니다.

상태의미전이
pending대기 중초기 상태
fulfilled성공.then()으로 결과 처리
rejected실패.catch()로 에러 처리
function fetchUser(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id > 0) resolve({ id, name: '영희' });
      else reject(new Error('잘못된 ID'));
    }, 500);
  });
}

fetchUser(1)
  .then(user => console.log(user.name)) // '영희'
  .catch(err => console.error(err.message));

async/await: 동기 코드처럼 읽기

async/await는 Promise를 더 읽기 쉽게 만든 문법 설탕입니다. await는 Promise가 처리될 때까지 기다린 뒤 결과값을 반환합니다.

async function loadProfile(id) {
  try {
    const res = await fetch(`/api/users/${id}`);
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    const user = await res.json();
    return user;
  } catch (err) {
    console.error('불러오기 실패:', err.message);
    return null;
  }
}

주의: async 함수는 항상 Promise를 반환합니다. 따라서 호출하는 쪽에서도 await 또는 .then()을 써야 실제 값을 얻습니다.

병렬 처리: Promise.all로 속도 올리기

서로 의존하지 않는 비동기 작업을 await로 순차 실행하면 시간이 낭비됩니다. 독립적인 요청은 병렬로 처리하세요.

// 느림: 순차 실행 (총 ~2초)
const a = await fetchUser(1);
const b = await fetchUser(2);

// 빠름: 병렬 실행 (총 ~1초)
const [user1, user2] = await Promise.all([
  fetchUser(1),
  fetchUser(2),
]);
  • Promise.all: 하나라도 실패하면 전체 reject
  • Promise.allSettled: 실패해도 모든 결과를 받고 싶을 때
  • Promise.race: 가장 먼저 끝나는 하나만 (타임아웃 구현에 유용)

마무리 체크리스트

  • 비동기 함수 호출 시 await 빠뜨리지 않기 (가장 흔한 버그)
  • try/catch에러 처리 필수, fetch는 res.ok도 체크
  • 독립적인 요청은 Promise.all병렬화
  • 반복문 안에서 await를 남발하면 느려짐 → map + Promise.all 활용
  • forEach는 await를 기다리지 않으므로 비동기 반복엔 for...of 사용
#JavaScript#비동기#Promise#async
X(트위터)
ADVERTISEMENT