본문 바로가기
C.W.K.
Stream
Lesson 02 of 05 · published

`async`와 `await`: 비동기 흐름의 타입 읽기

~8 min · async-promises, async-await, syntax

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"await는 비동기를 동기로 바꾸지 않아. 다음 줄을 이어 쓸 수 있게 흐름을 풀어 줄 뿐이야."

async 함수의 반환 타입

async function load(): User라고 쓰는 것이 아니라 Promise<User>를 반환한다고 선언해야 해. 함수 본문에서 return user라고 해도 호출자는 즉시 User가 아니라 Promise를 받기 때문이야. 반환값이 없다면 Promise<void>가 돼.

추론이 잘 되는 작은 함수는 반환 타입을 생략할 수 있지만, 공개 API나 재귀 비동기 함수에서는 명시하면 계약이 선명해져. 구현을 실수로 바꿨을 때 호출부까지 넓게 번지기 전에 함수 경계에서 막을 수도 있어.

await가 하는 타입 변환

const user = await load()에서 userUser로 추론돼. Promise가 아닌 값에 await를 써도 그 값은 그대로 나오므로 문법상 가능하지만, 불필요한 await는 흐름을 오해하게 만들 수 있어. 병렬로 시작할 작업을 연달아 기다리면 성능도 달라지지.

서로 독립적인 요청은 먼저 Promise들을 만든 뒤 Promise.all로 함께 기다리고, 앞 결과가 뒤 입력에 필요한 경우에만 순차적으로 await해. 타입 안전과 실행 순서는 별개의 설계 축이야.

반환은 감싸고 Promise는 평평하게 해

async 함수에서 일반 값 42를 반환해도 공개 결과는 Promise<number>로 감싸져. 이미 Promise<User>인 값을 반환하면 결과를 다시 중첩하지 않고 그대로 Promise<User>로 평평하게 해.

Promise가 아닌 값을 await하면

await 42처럼 일반 값을 기다리면 런타임이 Promise.resolve처럼 처리해 같은 42를 돌려줘. 명시적으로 쓸 일은 드물지만 await가 입력을 어떻게 다루는지 보여 주는 규칙이야.

asyncawait는 Promise 흐름을 읽기 좋게 만드는 문법이야. 병렬성, 취소, 오류 책임은 자동으로 해결되지 않으니 코드에 따로 드러내.

Code

async wrap, await unwrap·typescript
// async 가 return 을 Promise<T> 로 wrap.
async function getNumber(): Promise<number> {
  return 42;                          // wrap → Promise<number>
}

// Promise return — flatten.
async function getUser(): Promise<User> {
  return fetchUser(1);                // Promise<User> 반환, Promise<Promise<User>> 아님
}

// await — async 함수에서만 unwrap.
async function main() {
  const n = await getNumber();        // n: number
  const u = await getUser();          // u: User

  // Non-Promise 에 await — 그냥 값 반환.
  const x = await 42;                  // x: number
}

// Top-level await — ESM 에 작동, default 로 CommonJS 안 됨.
const data = await fetch('/api/data');  // modern ESM module 에 유효

External links

Exercise

사용자와 게시물을 차례로 기다린 뒤 Profile을 반환하는 loadProfile을 작성해. 각 await 뒤의 지역 변수가 Promise가 아닌 실제 값 타입인지 확인해.
Hint
await fetchUser(id)Promise<User>에서 User를 꺼내. 일반 객체를 반환해도 async 함수의 공개 결과는 다시 Promise<Profile>이 돼.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.