오늘도 커밋하는 북극곰

점점 이도저도 아닌 개발자가 되어가는중

개발/JavaScript

async/await

미니백곰 2024. 9. 10. 22:25

async/await

비동기 코드를 더 쉽게 작성할 수 있도록 돕는 기능입니다. 이 두 가지는 자바스크립트의 Promise와 함께 동작하며, 비동기 작업을 마치 동기 코드처럼 작성할 수 있게 해 줍니다.

 

1. async 함수

async 키워드는 함수 앞에 붙여서 해당 함수를 비동기로 만듭니다. 비동기 함수는 항상 Promise를 반환하며, 반환된 값이 Promise 객체로 감싸집니다. 즉, 함수 내부에서 값을 반환하면 그 값은 자동으로 Promise.resolve()를 통해 처리되고, 에러가 발생하면 Promise.reject()가 호출됩니다.

async function fetchData() {
    return "데이터가 성공적으로 로드되었습니다!";
}

fetchData().then(result => console.log(result));  // "데이터가 성공적으로 로드되었습니다!"

 

이 코드에서 fetchData 함수는 async 함수로 선언되어 있습니다. 이 함수는 문자열을 반환하지만, 실제로는 Promise가 반환됩니다. 이를 .then()을 통해 처리할 수 있습니다.

 

2. await

await은 async 함수 안에서만 사용할 수 있으며, Promise가 처리될 때까지 기다리게 합니다. awaitPromise가 해결될 때까지 해당 코드를 일시 중지하고, Promise의 결과를 반환합니다. 이를 통해 복잡한 .then() 체인을 피하고, 더 직관적인 코드 작성을 가능하게 합니다.

async function fetchData() {
    let result = await new Promise((resolve) => {
        setTimeout(() => resolve("데이터 로드 완료"), 2000);
    });
    console.log(result);  // "데이터 로드 완료" (2초 후 출력)
}

fetchData();

 

여기서 await은 Promise가 완료될 때까지 기다립니다. setTimeout을 이용해 2초 후에 “데이터 로드 완료”라는 값이 출력됩니다.

 

async와 await의 장점

- 가독성 향상: 콜백 함수나 .then() 체인을 사용하는 대신, 마치 동기 코드처럼 직관적으로 비동기 코드를 작성할 수 있습니다.

- 에러 처리: try/catch 구문을 사용해 비동기 코드에서 발생하는 에러를 간단하게 처리할 수 있습니다.

async function fetchData() {
    try {
        let result = await new Promise((_, reject) => {
            setTimeout(() => reject(new Error("데이터 로드 실패")), 2000);
        });
    } catch (error) {
        console.log(error.message);  // "데이터 로드 실패" (2초 후 출력)
    }
}

fetchData();

 

위 코드에서 await를 통해 비동기 작업의 결과를 기다리지만, 에러가 발생했을 때 try/catch를 이용해 에러를 처리할 수 있습니다.

 

간단한 예시

async function getUserData() {
    try {
        let response = await fetch('https://api.example.com/user');
        let data = await response.json();
        console.log(data);
    } catch (error) {
        console.log("API 호출 중 에러 발생:", error);
    }
}

getUserData();

 

이 코드에서 fetch API를 호출한 후, await을 사용하여 응답이 올 때까지 기다린 후에 JSON으로 파싱 합니다. 이렇게 하면 비동기적인 API 호출을 동기적인 코드처럼 다룰 수 있어 훨씬 읽기 쉬운 코드를 작성할 수 있습니다.

 

async, await의 단점

 

1. 동시성 문제

asyncawait은 기본적으로 코드가 동기적으로 실행되는 것처럼 보이도록 만들지만, 실제로는 코드가 비동기로 작동합니다. 하지만, await 키워드를 사용하면 해당 작업이 완료될 때까지 다음 코드가 실행되지 않기 때문에 성능 상의 병목이 발생할 수 있습니다.

async function fetchData() {
    let data1 = await fetch('https://api.example.com/data1');
    let data2 = await fetch('https://api.example.com/data2');
    return [data1, data2];
}

 

위 코드는 두 개의 비동기 작업(data1, data2)이 차례대로 실행됩니다. 하지만 이 경우, 첫 번째 fetch 요청이 완료된 후에야 두 번째 요청이 시작되기 때문에 병목 현상이 발생할 수 있습니다. 두 비동기 작업을 동시에 처리하기 위해서는 Promise.all()을 사용할 수 있습니다.

async function fetchData() {
    let [data1, data2] = await Promise.all([
        fetch('https://api.example.com/data1'),
        fetch('https://api.example.com/data2')
    ]);
    return [data1, data2];
}

 

2. 에러 핸들링의 한계

asyncawait을 사용할 때는 일반적으로 try/catch를 통해 에러를 처리합니다. 하지만, 특정한 에러가 발생한 위치나 맥락을 알기 어렵거나, 비동기적으로 여러 개의 await를 처리하는 경우, 에러가 어디서 발생했는지 추적하기가 어려울 수 있습니다.

async function fetchData() {
    try {
        let data1 = await fetch('https://api.example.com/data1');
        let data2 = await fetch('https://api.example.com/data2');
    } catch (error) {
        console.log("에러 발생:", error);
    }
}

 

이 코드에서는 두 fetch 요청 중 어느 쪽에서 에러가 발생했는지 알기 어렵습니다. 좀 더 세밀한 에러 처리가 필요할 수 있습니다.

 

3. 비동기 작업 중단 어려움

async/await은 실행 중인 비동기 작업을 쉽게 중단할 수 없습니다. 예를 들어, 타이머나 장기 실행 작업을 도중에 취소하려는 경우, Promise에는 취소 메커니즘이 존재하지 않기 때문에 이를 별도로 처리해야 합니다. 취소 기능이 내장된 라이브러리나 추가적인 논리가 필요합니다.

 

4. 디버깅 어려움

async/await는 코드가 동기적으로 보이지만 실제로는 비동기적으로 동작하기 때문에, 디버깅이 조금 어려울 수 있습니다. 특히, 비동기 함수가 중단된 지점이나 호출 스택을 추적하는 것이 다소 복잡할 수 있습니다.

 

콜백 함수나 Promise를 사용할 때와 달리 비동기 흐름이 어디서 어떻게 멈추는지 명확하지 않을 수 있습니다.

브라우저의 디버거는 비동기 함수의 흐름을 완벽하게 추적하지 못하는 경우가 있을 수 있습니다.

 

5. 무분별한 await 사용

async/await의 사용은 단순하지만, 모든 비동기 작업에 무분별하게 await를 사용하는 경우 성능이 저하될 수 있습니다. 모든 비동기 작업을 기다리도록 작성할 경우, 비효율적인 코드가 될 가능성이 높습니다.

 

결론

async/await은 자바스크립트의 비동기 작업을 간결하고 직관적으로 처리할 수 있게 하는 매우 강력한 도구입니다. 하지만 성능 최적화, 에러 처리의 명확성, 작업 중단 및 동시성 처리와 같은 문제는 여전히 신경 써야 할 부분입니다. 올바른 패턴과 적절한 도구를 함께 사용하면 이러한 단점들을 극복하면서 효율적인 비동기 코드를 작성할 수 있습니다.

'개발 > JavaScript' 카테고리의 다른 글

var와 let의 스코프 차이  (0) 2024.09.11
스코프(Scope)  (0) 2024.09.11
Promise  (0) 2024.09.10
콜백 함수(callback)  (0) 2024.09.10
비동기 처리(Asynchronous Processing)  (0) 2024.09.10