자바스크립트 async/await와 코드 최적화

최근 몇 년 동안, 자바스크립트에서 비동기 프로그래밍을 효율적으로 다루는 방법이 크게 개선되었습니다. async/await는 JavaScript에 추가된 기능 중 하나로, 비동기 작업을 처리하는 것을 간편하게 만들어줍니다. 이 기능은 코드를 깔끔하고 가독성이 좋게 작성할 수 있는 장점을 제공하며, 동시에 코드의 성능을 개선하는 방법도 제공합니다.

async/await란?

async/await는 비동기 코드를 동기식으로 작성할 수 있도록 해주는 자바스크립트의 기능입니다. 이 기능은 Promise와 함께 사용되며, 비동기 작업을 순차적으로 처리해주는 구문입니다. 다음은 간단한 예시 코드입니다.

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.log(error);
  }
}

함수 선언문 앞에 async 키워드를 붙여 async 함수로 선언할 수 있습니다. 그리고 함수 내부에서 await 키워드를 사용하여 Promise가 처리될 때까지 기다릴 수 있습니다. 이를 통해 비동기 코드를 순차적으로 처리할 수 있습니다.

코드 최적화

async/await는 비동기 코드를 작성하기 쉽게 만들어주지만, 잘못 사용하면 코드의 성능을 저하시킬 수 있습니다. 몇 가지 코드 최적화 방법을 살펴보겠습니다.

1. 병렬 실행을 고려하세요

async/await는 코드를 순차적으로 실행하기 때문에, 각 비동기 작업이 이전 작업의 완료를 기다릴 때까지 대기합니다. 이를 통해 가독성을 높이는 동시에 코드의 복잡성을 줄일 수 있지만, 대규모 비동기 작업의 경우 성능이 저하될 수 있습니다.

비슷한 작업을 병렬로 실행하고 결과를 한 번에 처리하는 것이 더 효율적인 경우도 있습니다. 이를 위해 Promise.all 메서드를 사용해 여러 비동기 작업을 하나로 묶을 수 있습니다.

async function fetchAllData() {
  try {
    const [response1, response2] = await Promise.all([
      fetch('https://api.example.com/data1'),
      fetch('https://api.example.com/data2'),
    ]);
    
    const data1 = await response1.json();
    const data2 = await response2.json();
    
    console.log(data1);
    console.log(data2);
  } catch (error) {
    console.log(error);
  }
}

위 코드에서 Promise.all은 병렬로 요청을 보내며, 모든 요청이 완료되기를 기다립니다. 이렇게 병렬로 실행된 작업의 결과를 받아와 순차적으로 처리하면 성능을 향상시킬 수 있습니다.

2. 에러 처리 주의하기

async/await를 사용하면 예외 처리를 간결하게 작성할 수 있습니다. 하지만 모든 async 함수에서 예외를 처리할 필요는 없습니다. async 함수 내부에서 발생한 예외를 처리하지 않으면, 해당 함수를 호출한 부분에서 처리할 수 있습니다. 예를 들어, async 함수를 호출하는 곳에서 try-catch 블록을 사용하여 예외를 처리할 수 있습니다.

async function fetchData() {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  return data;
}

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

processData();

3. 자원의 정리

async/await를 사용하여 비동기 작업을 처리하는 경우, 자원의 정리를 잊지 않아야 합니다. 예를 들어, 파일을 읽거나 쓰는 작업을 하는 경우에는 비동기 작업이 완료된 후에 파일을 닫아주어야 합니다.

async function writeFile(filePath, content) {
  let fileHandle;
  try {
    fileHandle = await fs.promises.open(filePath, 'w');
    await fileHandle.write(content);
  } catch (error) {
    console.log(error);
  } finally {
    if (fileHandle) {
      await fileHandle.close();
    }
  }
}

위 코드에서 finally 블록을 사용하여 파일 핸들을 닫아주었습니다. 이렇게 자원의 정리를 제대로 해주면 메모리 누수와 같은 문제를 예방할 수 있습니다.

마무리

자바스크립트 async/await는 비동기 작업을 더욱 쉽고 직관적으로 다룰 수 있도록 해주는 기능입니다. 하지만 알맞지 않게 사용하면 코드의 성능을 저하시킬 수 있으므로 주의해야 합니다. 병렬 실행과 에러 처리, 자원의 정리 등을 고려하여 최적화된 async/await 코드를 작성하면 좋은 결과를 얻을 수 있습니다.