← JavaScript 강의 목록으로
🌀
비동기
중급 · 선수: 15_Promise

16. async / await

`async` 키워드가 붙은 함수는 반환값이 자동으로 Promise 로 감쌉니다.

asyncawait비동기에러 처리
소요 시간
약 1.5시간
난이도
📊 중급
선수 조건
🎯 단원 15
결과물
`async` 키워드가 붙은 함수는 반환값이 자동으로 Promise 로 감쌉니다.

이 강의에서 배우는 것

  • 1`async` 함수가 항상 Promise 를 반환함을 안다.
  • 2`await` 로 Promise 의 값을 동기처럼 받아낼 수 있다.
  • 3`try/catch` 로 비동기 에러를 처리한다.
  • 4병렬 실행과 순차 실행의 차이를 안다.
  • 5`Promise.all` 과 `await` 을 조합하여 효율적으로 처리한다.

소개

`async` 키워드가 붙은 함수는 반환값이 자동으로 Promise 로 감쌉니다.

핵심 개념

1. async 함수

`async` 키워드가 붙은 함수는 반환값이 자동으로 Promise 로 감쌉니다.

javascript
async function f() {
  return 42;
}
f().then((v) => console.log(v)); // 42

2. await

`await` 는 Promise 가 결정될 때까지 함수 실행을 일시정지합니다. `async` 함수 내부에서만 쓸 수 있습니다(최상위 모듈 제외).

javascript
async function main() {
  const value = await Promise.resolve(10);
  console.log(value); // 10
}

3. try / catch

비동기 에러는 try/catch 로 잡습니다.

javascript
async function load() {
  try {
    const data = await fetchData();
    console.log(data);
  } catch (err) {
    console.error(err);
  }
}

4. 병렬 vs 순차

연속된 `await` 은 앞 작업이 끝나야 다음이 시작되므로 느립니다. 독립적인 작업은 `Promise.all` 로 병렬화하세요.

javascript
// 느림 (순차)
const a = await fetchA();
const b = await fetchB();

// 빠름 (병렬)
const [a, b] = await Promise.all([fetchA(), fetchB()]);

핵심 예제

파일다루는 내용
01_async_basic.jsasync 함수와 await 기본
02_try_catch.jstry/catch 로 에러 처리
03_promise_all.jsawait + Promise.all
04_parallel.js병렬 vs 순차 시간 비교

src/01_async_basic.js

javascript
/**
 * async 함수와 await 의 기본 동작.
 */
function delay(ms, value) {
  return new Promise((resolve) => setTimeout(() => resolve(value), ms));
}

async function main() {
  console.log("시작");
  const value = await delay(200, "안녕!");
  console.log("받음:", value);
  console.log("끝");
}

main();

src/02_try_catch.js

javascript
/**
 * try/catch 로 비동기 에러를 처리합니다.
 */
function fetchData(ok) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (ok) resolve({ id: 1 });
      else reject(new Error("네트워크 실패"));
    }, 100);
  });
}

async function run() {
  try {
    const data = await fetchData(false);
    console.log("성공:", data);
  } catch (err) {
    console.error("에러:", err.message);
  } finally {
    console.log("정리");
  }
}

run();

src/03_promise_all.js

javascript
/**
 * await 과 Promise.all 을 조합해 병렬 결과를 받습니다.
 */
function fetchValue(label, ms) {
  return new Promise((resolve) => setTimeout(() => resolve(label), ms));
}

async function loadAll() {
  const [a, b, c] = await Promise.all([
    fetchValue("A", 100),
    fetchValue("B", 200),
    fetchValue("C", 150),
  ]);
  console.log("모든 값:", a, b, c);
}

loadAll();

src/04_parallel.js

javascript
/**
 * 순차 await 와 병렬 await(Promise.all)의 실행 시간을 비교합니다.
 */
function work(label, ms) {
  return new Promise((resolve) => setTimeout(() => resolve(label), ms));
}

async function sequential() {
  const start = Date.now();
  await work("A", 200);
  await work("B", 200);
  await work("C", 200);
  console.log("순차:", Date.now() - start, "ms");
}

async function parallel() {
  const start = Date.now();
  await Promise.all([work("A", 200), work("B", 200), work("C", 200)]);
  console.log("병렬:", Date.now() - start, "ms");
}

(async () => {
  await sequential();
  await parallel();
})();

자주 하는 실수

  1. `async` 가 아닌 함수에서 `await` 사용 → SyntaxError.
  2. 독립적인 작업을 연속 `await` 으로 작성하여 시간 낭비.
  3. `try/catch` 없이 await 하여 unhandled rejection.
  4. `forEach((x) => await ...)` 는 동작하지 않음(콜백이 async 가 아님).
  5. async 함수의 반환값을 then 으로 풀지 않고 그대로 사용.

FAQ

Q1. await 을 모듈 최상위에서 사용할 수 있나요?

ES2022 의 top-level await(ESM 한정)에서 가능합니다.

Q2. async 함수가 throw 하면?

반환된 Promise 가 rejected 상태가 됩니다.

Q3. await 와 .then 중 무엇이 좋은가요?

가독성은 보통 await 가 좋습니다. 분기/조합이 단순할 땐 .then 도 충분합니다.

과제

  1. async 함수로 사용자와 게시글을 차례대로 가져오기.
  2. 여러 URL 을 Promise.all 로 병렬 호출 시뮬레이션.

homework/README.md

## 1. 사용자 + 게시글 가짜 `fetchUser(id)` 와 `fetchPosts(userId)` 를 작성하고, async 함수에서 차례로 호출해 결과를 출력하세요.

## 2. 병렬 요청 3개의 URL 에 해당하는 가짜 요청을 Promise.all 로 동시에 시작하고 시간을 측정하세요.

답안은 `answer/` 디렉터리를 참고하세요.

homework/answer/homework_01.js

javascript
/**
 * 사용자를 가져온 뒤 그 사용자의 게시글을 가져옵니다.
 */
function fetchUser(id) {
  return new Promise((resolve) => {
    setTimeout(() => resolve({ id, name: "지민" }), 100);
  });
}

function fetchPosts(userId) {
  return new Promise((resolve) => {
    setTimeout(() => resolve([{ id: 1, userId, title: "첫 글" }]), 100);
  });
}

async function main() {
  try {
    const user = await fetchUser(1);
    const posts = await fetchPosts(user.id);
    console.log(user.name, "의 게시글:", posts);
  } catch (err) {
    console.error(err);
  }
}

main();

homework/answer/homework_02.js

javascript
/**
 * 세 URL 의 가짜 요청을 병렬로 보내고 총 시간을 측정합니다.
 */
function fakeFetch(url, ms) {
  return new Promise((resolve) => setTimeout(() => resolve(`${url} OK`), ms));
}

async function main() {
  const start = Date.now();
  const results = await Promise.all([
    fakeFetch("/a", 200),
    fakeFetch("/b", 250),
    fakeFetch("/c", 150),
  ]);
  console.log("결과:", results);
  console.log("총 시간:", Date.now() - start, "ms");
}

main();

다음 단원

[17_DOM_선택과_조회](../../05_DOM/17_DOM_선택과_조회/) — 브라우저에서 HTML 요소 다루기

예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗