JavaScript의 비동기 프로그래밍

JavaScript는 기본적으로 단일 스레드에서 동작하기 때문에, 비동기 프로그래밍이 매우 중요합니다. 비동기 프로그래밍을 통해 시간 소요가 큰 작업(예: 네트워크 요청, 파일 읽기 등)을 처리하면서도 애플리케이션이 멈추지 않고 동작할 수 있습니다. 이번 글에서는 JavaScript의 비동기 프로그래밍 방법인 콜백(callback), 프로미스(Promise), async/await에 대해 살펴보고, 이들의 사용법과 차이점을 설명하겠습니다.

콜백 (Callback)

콜백 함수란?

콜백 함수는 다른 함수의 인자로 전달되어, 특정 작업이 완료된 후 호출되는 함수입니다. 비동기 작업을 처리하기 위해 널리 사용되었지만, 가독성이 떨어지고 에러 처리가 복잡해지는 단점이 있습니다.

콜백 함수 예제

function fetchData(callback) {
  setTimeout(() => {
    const data = { name: "John", age: 30 };
    callback(data);
  }, 1000);
}

function handleData(data) {
  console.log("Data received:", data);
}

fetchData(handleData);

위 예제에서 fetchData 함수는 1초 후에 데이터를 가져와 콜백 함수 handleData를 호출합니다.

콜백 지옥 (Callback Hell)

여러 비동기 작업을 중첩해서 처리할 때 콜백을 사용하면 코드가 복잡해지고 가독성이 떨어지는 문제를 초래합니다. 이를 콜백 지옥이라고 합니다.

function fetchData(callback) {
  setTimeout(() => {
    const data = { name: "John", age: 30 };
    callback(data);
  }, 1000);
}

function fetchAdditionalData(data, callback) {
  setTimeout(() => {
    data.additionalInfo = "Some more info";
    callback(data);
  }, 1000);
}

fetchData((data) => {
  fetchAdditionalData(data, (updatedData) => {
    console.log("Updated Data:", updatedData);
  });
});

프로미스 (Promise)

프로미스란?

프로미스는 비동기 작업의 최종 완료 또는 실패를 나타내는 객체입니다. 콜백 패턴보다 가독성이 좋고, 에러 처리가 간단합니다. 프로미스는 pending(대기), fulfilled(이행), rejected(거부) 상태를 가집니다.

프로미스 사용법

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = { name: "John", age: 30 };
      resolve(data);
    }, 1000);
  });
}

fetchData()
  .then((data) => {
    console.log("Data received:", data);
  })
  .catch((error) => {
    console.error("Error:", error);
  });

위 예제에서 fetchData 함수는 프로미스를 반환하고, then 메서드를 사용하여 데이터를 처리합니다. catch 메서드를 사용하여 에러를 처리할 수 있습니다.

프로미스 체이닝

여러 비동기 작업을 순차적으로 처리할 때 프로미스 체이닝을 사용할 수 있습니다.

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = { name: "John", age: 30 };
      resolve(data);
    }, 1000);
  });
}

function fetchAdditionalData(data) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      data.additionalInfo = "Some more info";
      resolve(data);
    }, 1000);
  });
}

fetchData()
  .then(fetchAdditionalData)
  .then((updatedData) => {
    console.log("Updated Data:", updatedData);
  })
  .catch((error) => {
    console.error("Error:", error);
  });

async/await

async/await란?

asyncawait는 ES2017(ES8)에서 도입된 비동기 프로그래밍을 위한 새로운 문법입니다. 프로미스를 기반으로 하며, 비동기 코드를 동기 코드처럼 작성할 수 있게 해줍니다.

async/await 사용법

async function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = { name: "John", age: 30 };
      resolve(data);
    }, 1000);
  });
}

async function fetchAndHandleData() {
  try {
    const data = await fetchData();
    console.log("Data received:", data);
  } catch (error) {
    console.error("Error:", error);
  }
}

fetchAndHandleData();

async/await의 장점

  • 가독성: 코드가 동기 코드처럼 보이기 때문에 가독성이 높습니다.
  • 에러 처리: try/catch 블록을 사용하여 에러를 쉽게 처리할 수 있습니다.

async/await 체이닝

여러 비동기 작업을 순차적으로 처리할 때도 async/await를 사용할 수 있습니다.

async function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = { name: "John", age: 30 };
      resolve(data);
    }, 1000);
  });
}

async function fetchAdditionalData(data) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      data.additionalInfo = "Some more info";
      resolve(data);
    }, 1000);
  });
}

async function fetchAndHandleData() {
  try {
    const data = await fetchData();
    const updatedData = await fetchAdditionalData(data);
    console.log("Updated Data:", updatedData);
  } catch (error) {
    console.error("Error:", error);
  }
}

fetchAndHandleData();

결론

JavaScript에서 비동기 프로그래밍을 처리하는 방법에는 콜백, 프로미스, async/await가 있습니다. 각각의 방법은 장단점이 있으며, 상황에 맞게 선택하여 사용해야 합니다. 콜백은 간단하지만 가독성이 떨어지고, 프로미스는 가독성이 좋고 에러 처리가 간단합니다. async/await는 프로미스를 기반으로 하여, 비동기 코드를 동기 코드처럼 작성할 수 있어 가독성이 매우 높습니다. 이 글을 통해 각 방법의 사용법과 차이점을 이해하고, 비동기 프로그래밍을 효과적으로 처리할 수 있기를 바랍니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다