[JavaScript] 자바스크립트의 async와 await

하롭·2025년 3월 16일
post-thumbnail

오늘은 자바스크립트의 asyncawait에 대해 공부하면서 정리한 내용을 공유해보려고 한다. 자바스크립트에서 비동기 처리를 할 때 자주 겪는 콜백 지옥(callback hell)을 해결하고, 코드를 더 명확하게 작성할 수 있는 방법이다.

1. ⁉️ 비동기 처리란?

자바스크립트는 한 번에 하나의 작업만 처리할 수 있는 싱글 스레드 언어이다. 만약 네트워크 요청이나 파일 읽기처럼 시간이 오래 걸리는 작업을 기다리고 있으면 다른 작업을 할 수 없다. 그래서 이런 작업을 기다리지 않고 다른 작업을 계속 진행할 수 있도록 비동기 처리를 사용한다.

예전에는 setTimeout, XMLHttpRequest(XHR), Promise 등을 써서 비동기 작업을 처리했는데, 최근에는 asyncawait을 사용하면 마치 동기적인 코드처럼 더 간결하고 이해하기 쉽게 작성할 수 있어서 좋았다.


2. ✨ async와 await 이해하기

🔹 async 키워드

async를 함수 앞에 붙이면 그 함수는 항상 Promise를 반환한다.

async function sayHello() {
    return "Hello, Async!";
}

sayHello().then(console.log); // "Hello, Async!"

이렇게 쓰면 자동으로 Promise.resolve("Hello, Async!") 형태로 반환된다.

🔹 await 키워드

await는 반드시 async 함수 내부에서만 사용할 수 있고, 비동기 작업(Promise)의 결과가 나올 때까지 기다리게 해준다.

async function fetchMessage() {
    let response = await new Promise(resolve => setTimeout(() => resolve("비동기 작업 완료!"), 2000));
    console.log(response);
}

fetchMessage();
// 2초 후 "비동기 작업 완료!" 출력

이렇게 하면 코드 흐름이 중간에 멈추는 것처럼 보이지만, 실제로는 비동기로 처리되고 있다.


3. 📌 async/await를 사용하는 이유

async/await를 사용하면 다음과 같은 장점이 있다.

1️⃣ 코드가 깔끔하고 이해하기 쉽다

기존의 Promise 방식은 .then()이 연달아 붙어서 코드를 복잡하게 만든다.

Promise 방식

fetch("https://jsonplaceholder.typicode.com/users/1")
    .then(res => res.json())
    .then(user => fetch(`https://jsonplaceholder.typicode.com/posts?userId=${user.id}`))
    .then(res => res.json())
    .then(posts => console.log(posts))
    .catch(err => console.error(err));

async/await 방식

async function fetchUserAndPosts() {
    try {
        let userResponse = await fetch("https://jsonplaceholder.typicode.com/users/1");
        let user = await userResponse.json();

        let postsResponse = await fetch(`https://jsonplaceholder.typicode.com/posts?userId=${user.id}`);
        let posts = await postsResponse.json();

        console.log(posts);
    } catch (error) {
        console.error("에러 발생:", error);
    }
}

fetchUserAndPosts();

코드가 위에서 아래로 순서대로 흘러가서 읽기 쉽다.

2️⃣ 에러 처리가 간편하다

async/await는 일반적인 try...catch 방식으로 에러 처리가 가능해서, 어디서 에러가 발생했는지 쉽게 확인할 수 있다.

3️⃣ 디버깅이 쉽다

async/await로 작성된 코드는 일반 동기 코드처럼 디버깅이 간단해진다. Promise 방식에 비해 문제의 원인을 빠르게 찾을 수 있다.


4. 🔄 여러 작업을 병렬로 처리하기

비동기 작업이 여러 개라면 Promise.all()을 사용해서 병렬로 처리할 수 있다. 한 번에 여러 요청을 보내고, 더 빠르게 결과를 받을 수 있다.

async function fetchMultipleData() {
    let [user, posts] = await Promise.all([
        fetch("https://jsonplaceholder.typicode.com/users/1").then(res => res.json()),
        fetch("https://jsonplaceholder.typicode.com/posts?userId=1").then(res => res.json())
    ]);

    console.log("사용자:", user);
    console.log("게시물:", posts);
}

fetchMultipleData();

5. ⚠️ 주의할 점

  • await은 반드시 async 함수 내부에서만 사용할 수 있다.
  • 비동기 작업을 순차적으로 처리하면 속도가 느려질 수 있다. 이럴 때는 Promise.all()을 활용해서 병렬 처리를 해야 한다.

6. then/catch와 async/await의 성능 비교

성능상 두 방식에 큰 차이는 없다. 하지만 async/await이 가독성과 유지보수 측면에서 더 유리하므로, 코드가 복잡해질 때는 적극적으로 사용하는 것이 좋다.


7. 정리

  • async: 비동기 함수로 만들어 항상 Promise를 반환한다.
  • await: 비동기 작업의 완료를 기다린다.
  • try...catch: 에러 처리가 쉽다.
  • Promise.all(): 여러 작업을 동시에 처리할 수 있다.

콜백 지옥을 해결함과 동시에 더 명확하고 유지보수하기 쉬운 비동기 코드를 작성할 때 async/await을 활용하면 큰 도움이 될 것 같다.

profile
휘발 방지 로그

0개의 댓글