async/await 완벽 이해하기 – JavaScript 비동기 처리의 핵심

2025. 5. 28. 22:48Front-End/Vue.js

반응형

1. 왜 비동기 처리가 필요한가?

자바스크립트는 단일 스레드(single-thread) 기반 언어다.
즉, 어떤 작업이 오래 걸리면(예: 네트워크 요청), 그동안 다른 작업은 멈춰버리게 된다.

이를 해결하기 위해 자바스크립트는 비동기 처리 방식을 도입했는데,
그 대표적인 방식이 바로 Promise고, 그 위에 편하게 쓸 수 있도록 만들어진 문법이 async/await이다.


2. Promise 복습: 기본 비동기 구조

function getData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("성공")
    }, 1000)
  })
}

getData()
  .then(result => console.log(result))    // "성공"
  .catch(error => console.error(error))
  • Promise는 미래에 완료될 작업을 나타냄
  • .then()으로 성공 결과를 받고
  • .catch()로 실패를 처리

3. async/await: 동기 코드처럼 보이는 비동기

이걸 async/await로 바꾸면 이렇게 된다:

async function loadData() {
  try {
    const result = await getData()
    console.log(result)
  } catch (err) {
    console.error('에러 발생:', err)
  }
}

✅ 핵심 문법 정리

문법 의미
async function 비동기 함수 선언. 내부에서 await 사용 가능
await Promise가 끝날 때까지 기다림. 완료되면 결과 반환
try/catch 오류 발생 시 안전하게 핸들링

4. await의 동작 방식은 실제로 어떻게 되나?

await는 사실 내부적으로 .then()을 호출하는 것과 같다.

const result = await getData()
// ↔ 동일한 의미
getData().then(result => { ... })

단, await는 async 함수 안에서만 사용 가능하다는 점에 주의해야 한다.

// ❌ 오류 발생
const result = await getData()

5. 실전 예제 – API 호출

async function fetchUserData(userId) {
  try {
    const response = await fetch(`/api/users/${userId}`)
    const data = await response.json()
    return data
  } catch (error) {
    console.error("사용자 정보를 불러오는 데 실패:", error)
    return null
  }
}

여기서 중요한 건 두 번의 await이다.

  1. fetch()는 Promise를 반환
  2. .json()도 비동기이기 때문에 다시 await

6. 병렬 처리: await를 동시에 쓰면 직렬

// ❌ 느리다 – 순차 실행
const a = await fetchA()
const b = await fetchB()

✅ 병렬 처리하려면 Promise를 먼저 만들고, 나중에 await

const promiseA = fetchA()
const promiseB = fetchB()

const a = await promiseA
const b = await promiseB

또는 Promise.all()을 사용

const [a, b] = await Promise.all([fetchA(), fetchB()])

7. 에러 핸들링은 반드시 try/catch

await는 내부적으로 Promise.reject()가 발생하면 예외로 던져지기 때문에
꼭 try/catch로 감싸야 안전하다.

try {
  const data = await fetchData()
} catch (error) {
  // 네트워크 오류, 500 에러 등
}

에러 없이 쓰면 무중단으로 서비스가 죽을 수 있다.


8. Vue와 async/await

Vue의 onMounted()에서 비동기 호출할 때 자주 쓰는 패턴:

onMounted(async () => {
  try {
    const res = await fetch('/api/data')
    data.value = await res.json()
  } catch (e) {
    console.error("데이터 로드 실패:", e)
  }
})

또는 Composition 함수에서:

const loadSomething = async () => {
  const result = await apiCall()
  something.value = result
}

9. async/await의 한계

  • await는 직렬 실행이 기본이기 때문에 무턱대고 사용하면 성능 저하 가능
  • 오래 걸리는 작업은 Promise.all()로 병렬 처리 고려
  • 반복문 안에서 await를 쓰면 → 순차 실행됨 (주의!)

마무리 정리

키우드 설명
async 비동기 함수 선언
await Promise의 완료를 기다림
try/catch 예외 처리 필수
Promise.all 병렬 처리에 적합
Vue에서의 사용 API 호출, 파일 업로드, 초기 데이터 로딩 등
반응형