바로 이해하는 async / await

srchae·2025년 1월 27일
post-thumbnail

한 때, 비동기 구문을 쉽게 이해하지 못 했던 사람으로서 이를 다룬 포스팅을 해야지 늘 생각했고 이 글을 포스팅 해보려 한다.

예시 코드로 이해하기

1. 기본 코드

function fetchData() {
  const response = fetch("https://api.example.com/data");
  console.log(response);
}

fetchData();

실행 결과

  • fetch는 비동기 함수로 Promise 객체를 반환
  • console.log(response)는 실제 API 데이터가 아닌, Promise 객체를 출력
  • 이유는 fetch가 완료되기 전에 console.log가 실행되었기 때문

2. 비동기 선언 (async/await) 으로 작성된 코드

async function fetchData() {
  const response = await fetch("https://api.example.com/data");
  const data = await response.json(); // JSON으로 변환
  console.log(data);
}

fetchData();

실행 결과

  • await를 사용하면 fetch가 완료될 때까지 코드 실행이 일시 중단
  • response 변수는 API 호출 결과를 기다렸다가 실제 응답 데이터를 반환
  • console.log(data)는 변환된 JSON 데이터를 출력

비동기 처리를 위한 .then() vs async/await

1. .then() 사용

function fetchData() {
  fetch("https://api.example.com/data")
    .then((response) => response.json())
    .then((data) => {
      console.log(data); 
    })
    .catch((error) => console.error("Error:", error));
}

fetchData();

.then() 체인을 사용하면 동일한 작업을 비동기적으로 처리할 수 있지만,
코드가 길어지거나 중첩되면 가독성이 떨어질 수 있다.

2. async/await 사용

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

fetchData();

비동기 선언(async/await)을 사용하면 코드가 더 읽기 쉽고,
마치 동기적으로 보이기 때문에 복잡한 로직을 처리하기 유용하다.

조금 더 쉬운 이해를 위해 음식 주문을 예시로 들어보겠다.

쉬운 이해를 돕는 예시

1. 동기 방식의 주문

function orderFoodSync() {
  const food = makeFood(); // 음식을 만드는 함수을 통한 응답을 기다림
  console.log(`음식 받음: ${food}`);
  console.log("테이블로 이동");
}

음식을 받아야지만 테이블로 이동할 수 있다.

2. 비동기 방식의 주문

function orderFoodAsync() {
  makeFoodAsync().then((food) => {
    console.log(음식 받음: ${food});
  });
  console.log("테이블로 이동"); // 기다리지 않고 실행
}

음식을 받기 전에 테이블로 이동할 수 있다.

비동기를 사용하는 이유

  • 요청에 따른 응답외의 다른 작업이 필요할 때 기다리지 않아도 되는 효율적 처리가 가능하다.
  • 즉, 여러 작업이 병렬적으로 처리할 수 있다.

그렇다면 왜 .then() 말고 async/await을 쓸까요?

  • then()은 콜백 체인이 길어지면서 다소 복잡해질 수 있다.
  • async/await은 코드가 마치 동기적으로 진행되는 것처럼 보이기 때문에 직관적이다.

실제 사용 예시

const onSubmit = async (data: LoginFormData) => {
  console.log(data); // (1)
  try {
    const response = await api.login(data); // (2)
    console.log("response::", response); // (3)

    if (response.status === 201) { // (4)
      setUserInfo(response.data.user); // (5)
      router.push("/"); // (6)
    }
  } catch (error) {
    console.log(error); // (7)
  }
};

코드 설명을 통한 정리

  • api.login(data)가 서버로 요청을 보내지만, await를 사용하기에 응답을 대기하지만, 함수 외부에서는 대기가 발생하지 않음
  • 비동기 작업이 진행되는 동안, 호출한 쪽에서는 다른 동작 수행 가능 (예: onSubmit 함수 외에서 일어나는 동작)
  • try-catch 구조로 오류를 안정적으로 처리
  • async/await를 사용하여 비동기 작업을 동기적 흐름처럼 작성 가능

결론 및 요약

비동기 코드가 중요한 이유

  • 작업 간 대기 시간을 줄여 효율적인 처리가 가능하다.
  • 요청/응답 작업과 병렬적으로 다른 작업을 수행할 수 있다.
  • async/await은 직관적인 코드로 복잡한 로직을 간결하게 처리할 수 있다.
profile
🐥집요함과 꾸준함🪽

0개의 댓글