"await는 비동기를 동기로 바꾸지 않아. 다음 줄을 이어 쓸 수 있게 흐름을 풀어 줄 뿐이야."
async 함수의 반환 타입
async function load(): User라고 쓰는 것이 아니라 Promise<User>를 반환한다고 선언해야 해. 함수 본문에서 return user라고 해도 호출자는 즉시 User가 아니라 Promise를 받기 때문이야. 반환값이 없다면 Promise<void>가 돼.
추론이 잘 되는 작은 함수는 반환 타입을 생략할 수 있지만, 공개 API나 재귀 비동기 함수에서는 명시하면 계약이 선명해져. 구현을 실수로 바꿨을 때 호출부까지 넓게 번지기 전에 함수 경계에서 막을 수도 있어.
await가 하는 타입 변환
const user = await load()에서 user는 User로 추론돼. Promise가 아닌 값에 await를 써도 그 값은 그대로 나오므로 문법상 가능하지만, 불필요한 await는 흐름을 오해하게 만들 수 있어. 병렬로 시작할 작업을 연달아 기다리면 성능도 달라지지.
서로 독립적인 요청은 먼저 Promise들을 만든 뒤 Promise.all로 함께 기다리고, 앞 결과가 뒤 입력에 필요한 경우에만 순차적으로 await해. 타입 안전과 실행 순서는 별개의 설계 축이야.
반환은 감싸고 Promise는 평평하게 해
async 함수에서 일반 값 42를 반환해도 공개 결과는 Promise<number>로 감싸져. 이미 Promise<User>인 값을 반환하면 결과를 다시 중첩하지 않고 그대로 Promise<User>로 평평하게 해.
Promise가 아닌 값을 await하면
await 42처럼 일반 값을 기다리면 런타임이 Promise.resolve처럼 처리해 같은 42를 돌려줘. 명시적으로 쓸 일은 드물지만 await가 입력을 어떻게 다루는지 보여 주는 규칙이야.
async와 await는 Promise 흐름을 읽기 좋게 만드는 문법이야. 병렬성, 취소, 오류 책임은 자동으로 해결되지 않으니 코드에 따로 드러내.