💻 프로그래밍

async/await

Async Await

비동기 코드를 동기처럼 작성하는 문법. JavaScript, Python, Rust에서 지원. Promise 기반.

📖 상세 설명

async/await는 비동기 프로그래밍을 동기 코드처럼 직관적으로 작성할 수 있게 해주는 문법입니다. JavaScript, Python, Rust, C# 등 현대 프로그래밍 언어에서 광범위하게 지원되며, 콜백 지옥이나 복잡한 Promise 체이닝 문제를 해결합니다.

async 키워드는 함수를 비동기 함수로 선언하며, 해당 함수는 항상 Promise(또는 해당 언어의 Future 타입)를 반환합니다. await 키워드는 async 함수 내에서만 사용 가능하며, Promise가 resolve될 때까지 함수 실행을 일시 중지합니다.

내부적으로 async/await는 제너레이터와 Promise를 조합한 것과 유사하게 동작합니다. await를 만나면 현재 실행 컨텍스트를 저장하고 이벤트 루프에 제어권을 넘깁니다. Promise가 완료되면 저장된 지점부터 실행을 재개합니다.

에러 처리도 동기 코드처럼 try-catch 블록을 사용할 수 있어 코드 가독성이 크게 향상됩니다. 다만 비동기 함수의 특성상 실행 순서와 에러 전파 방식을 정확히 이해하고 사용해야 예상치 못한 버그를 방지할 수 있습니다.

💻 코드 예제

JavaScript
// async/await 기본 사용법
async function fetchUserData(userId) {
    try {
        const response = await fetch(`/api/users/${userId}`);
        if (!response.ok) {
            throw new Error('사용자를 찾을 수 없습니다');
        }
        const userData = await response.json();
        return userData;
    } catch (error) {
        console.error('에러 발생:', error.message);
        throw error;
    }
}

// 여러 비동기 작업 병렬 처리
async function loadDashboard(userId) {
    const [user, posts, notifications] = await Promise.all([
        fetchUserData(userId),
        fetch(`/api/posts?userId=${userId}`).then(r => r.json()),
        fetch('/api/notifications').then(r => r.json())
    ]);

    return { user, posts, notifications };
}

// 사용 예시
loadDashboard(123)
    .then(data => console.log(data))
    .catch(err => console.error(err));

🗣️ 실무 대화 예시

시니어 개발자
"이 API 호출 부분을 async/await로 리팩토링하면 어떨까요? then 체이닝이 세 단계나 되어서 가독성이 떨어지네요."
주니어 개발자
"동의합니다. 그런데 여러 API를 순차적으로 호출하는 부분은 Promise.all과 함께 사용하면 성능도 개선될 것 같아요."
시니어 개발자
"좋은 생각이에요. 병렬로 처리해도 되는 요청들은 Promise.all로 묶고, 의존성 있는 요청만 await로 순차 처리하죠."
면접관
"async/await와 Promise.then()의 차이점을 설명해주시고, 각각 어떤 상황에서 사용하시는지 말씀해주세요."
지원자
"둘 다 Promise를 다루지만 async/await는 동기 코드처럼 읽히므로 복잡한 흐름에서 가독성이 좋습니다. 반면 단순한 단일 비동기 작업이나 배열 메서드와 함께 쓸 때는 then()이 더 간결할 수 있어요."
면접관
"async 함수 내에서 await 없이 Promise를 반환하면 어떻게 되나요?"
지원자
"Promise가 자동으로 언래핑되어 반환됩니다. async 함수는 항상 Promise를 반환하므로 중첩되지 않고 단일 Promise로 처리됩니다."
리뷰어
"이 for 루프 안에서 await를 쓰면 각 요청이 순차 실행됩니다. 서로 독립적인 요청이라면 Promise.all로 병렬 처리하는 게 좋겠어요."
작성자
"아, 맞네요. map으로 Promise 배열을 만들고 Promise.all로 감싸면 훨씬 빠르겠네요. 수정하겠습니다."
리뷰어
"그리고 에러 처리도 추가해주세요. 하나가 실패해도 나머지는 처리해야 한다면 Promise.allSettled를 고려해보세요."

⚠️ 주의사항

🔗 관련 용어

📚 더 배우기