JS/JavaScript

#24 자바스크립트 async/await

인생아 2024. 9. 6. 13:05
반응형

비동기 프로그래밍은 자바스크립트에서 매우 중요한 개념입니다. 네트워크 요청, 파일 입출력, 타이머 설정 등 시간이 걸리는 작업을 처리할 때 비동기 작업은 사용자 경험을 향상시키는 데 큰 역할을 합니다. 특히 async/await는 자바스크립트의 비동기 작업을 보다 직관적이고 쉽게 처리할 수 있도록 도와주는 ES6 이후 추가된 기능입니다. 이 글에서는 **async/await**의 개념과 그 사용법을 예제와 함께 설명하겠습니다.

async/await란?

async/await는 자바스크립트에서 비동기 코드를 동기 코드처럼 작성할 수 있게 해줍니다. 비동기 작업을 처리하는 기존의 Promise콜백 함수보다 가독성이 좋으며, 코드의 유지보수성도 높아집니다.

  • async 함수: 함수 앞에 async 키워드를 붙이면, 해당 함수는 항상 Promise를 반환합니다. 함수 내에서 명시적으로 Promise를 반환하지 않으면, **Promise.resolve()**로 처리됩니다.
  • await 키워드: **await**는 Promise가 해결될 때까지 해당 작업을 기다립니다. 이 키워드는 반드시 async 함수 내부에서만 사용할 수 있습니다.

기본 예제

async function fetchData() {
    return '데이터를 성공적으로 가져왔습니다!';
}

fetchData().then(result => console.log(result)); 
// 출력: 데이터를 성공적으로 가져왔습니다!

위 예제에서 fetchData() 함수는 **async**로 정의되었으므로, 해당 함수는 Promise를 반환합니다. then() 메서드를 사용하여 결과를 처리할 수 있습니다.

async/await의 실제 활용

다음은 실제로 **async/await**을 활용하여 비동기 네트워크 요청을 처리하는 예제입니다. 이 예제에서는 데이터 요청 전 일정 시간(2초) 동안 기다리게 한 후, 데이터를 처리합니다.

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function fetchData() {
    console.log('데이터를 가져오는 중...');
    await delay(2000); // 2초 대기
    return '데이터가 준비되었습니다!';
}

async function displayData() {
    const result = await fetchData(); 
    console.log(result);
}

displayData();
// 출력:
// 데이터를 가져오는 중...
// (2초 후)
// 데이터가 준비되었습니다!

async/await의 장점

  1. 가독성 향상: 비동기 코드도 동기 코드처럼 작성할 수 있어, 코드가 더 명확하고 읽기 쉬워집니다.
  2. 에러 처리 용이: try/catch 구문을 사용하여 에러를 처리할 수 있습니다.
  3. 콜백 지옥 해소: 콜백 함수나 Promise 체인을 지나치게 중첩하지 않고 깔끔한 코드 작성이 가능합니다.

에러 처리

async/await를 사용할 때 발생하는 에러는 try/catch 구문을 통해 쉽게 처리할 수 있습니다. 다음 예제는 데이터를 가져오는 도중 발생하는 에러를 핸들링하는 방법을 보여줍니다.

async function fetchData() {
    try {
        let response = await fetch('https://jsonplaceholder.typicode.com/posts');
        let data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('에러 발생:', error);
    }
}

fetchData();

위 예제에서는 비동기 요청 중에 발생할 수 있는 네트워크 오류나 기타 예외 상황을 catch 블록에서 처리하고 있습니다.

async/await vs Promise 체인

async/await은 기존의 Promise를 기반으로 더 간결한 문법을 제공하지만, 두 방식 모두 동일한 비동기 처리를 수행합니다. 다음은 Promise 체인 방식과 async/await 방식의 비교입니다.

Promise 체인 방식

function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve('데이터가 준비되었습니다!'), 2000);
    });
}

fetchData()
    .then(data => console.log(data))
    .catch(error => console.error('에러:', error));

async/await 방식

async function fetchData() {
    try {
        await new Promise(resolve => setTimeout(resolve, 2000));
        console.log('데이터가 준비되었습니다!');
    } catch (error) {
        console.error('에러:', error);
    }
}

fetchData();

async/await 방식이 더 간결하고 읽기 쉬운 구조를 제공합니다.

async/await의 단점

  1. 성능 이슈: 여러 개의 비동기 작업을 await로 순차적으로 처리할 경우 성능 저하가 발생할 수 있습니다. 비동기 작업을 병렬로 처리하는 것이 더 효율적일 때는 **Promise.all()**을 사용해야 합니다.
  2. 에러 처리 복잡성: 비동기 함수마다 별도의 try/catch를 사용해야 하므로, 코드가 길어질 수 있습니다.

성능 최적화를 위한 병렬 처리

async/await를 사용할 때 성능을 최적화하려면 **Promise.all()**을 사용해 비동기 작업을 병렬로 처리할 수 있습니다.

async function fetchDataInParallel() {
    const [data1, data2] = await Promise.all([
        fetch('https://jsonplaceholder.typicode.com/posts/1'),
        fetch('https://jsonplaceholder.typicode.com/posts/2')
    ]);
    console.log('두 개의 데이터를 병렬로 가져왔습니다.');
}

fetchDataInParallel();

위 코드에서는 두 개의 네트워크 요청이 병렬로 처리되어, 성능이 향상됩니다.

async/await 사용 시 주의할 점

  1. 병렬 처리 여부: 여러 개의 비동기 작업을 순차적으로 처리해야 하는 경우가 아니라면, **Promise.all()**을 사용하여 병렬로 처리하는 것이 성능상 이점이 큽니다.
  2. 에러 처리: 비동기 함수에서 발생하는 모든 에러는 try/catch로 명확히 처리해야 하며, 예외가 발생할 수 있는 모든 비동기 작업에 대해서는 철저히 대비해야 합니다.
  3. 블록킹 위험: await는 Promise가 해결될 때까지 실행을 일시 중지하기 때문에, 불필요하게 많은 await을 사용하면 동시 처리의 이점을 살리지 못하고 코드가 블록킹될 수 있습니다.

결론

async/await은 자바스크립트의 비동기 프로그래밍을 더 간결하고 직관적으로 처리할 수 있는 방법입니다. Promise 체인 방식에 비해 가독성이 뛰어나며, 에러 처리도 더욱 명확해집니다. 그러나 성능 최적화를 위해 병렬 처리가 필요한 경우 **Promise.all()**과 같은 방법을 사용해야 하고, 코드의 흐름을 충분히 고려하여 사용해야 합니다.

반응형