Day 11async/await와 fetch

async/await는 Promise 위에 얹은 문법 설탕이다 — Rust의 async fn/.await와 사실상 1:1 대응이라 이미 익숙할 것이다. 내부적으로는 여전히 Promise다.

1. async/await 기본

async function getTemp() {
  const temp = await readSensor();   // Promise가 풀릴 때까지 "이 함수 안에서만" 대기
  return temp * 9/5 + 32;
}

// async 함수는 항상 Promise를 리턴한다
getTemp().then((f) => console.log(f));
// 또는 다른 async 함수 안에서
const f = await getTemp();

2. try/catch로 에러 처리

async function safeGetTemp() {
  try {
    const temp = await readSensor();
    return temp;
  } catch (err) {
    console.error("읽기 실패:", err.message);
    return null;
  }
}

3. fetch 기본

async function getSeoulWeather() {
  const res = await fetch("https://api.open-meteo.com/v1/forecast?latitude=37.5&longitude=127¤t=temperature_2m");
  if (!res.ok) {
    throw new Error(`HTTP ${res.status}`);
  }
  const data = await res.json();      // 이것도 Promise라서 await 필요
  return data.current.temperature_2m;
}
fetch는 서버가 404/500을 응답해도 reject하지 않는다 — 네트워크 자체가 실패했을 때만 reject한다. 그래서 res.ok를 직접 확인해야 한다.

4. 순차 vs 병렬

// 순차 — b가 a를 안 기다려도 되는데 기다림 (느림)
const a = await fetchA();
const b = await fetchB();

// 병렬 — 둘 다 먼저 시작시키고 나중에 같이 기다림 (빠름)
const [a2, b2] = await Promise.all([fetchA(), fetchB()]);

🎯 실습 과제 — _submissions/day11.js

과제 1. 서울 온도 가져오기
getSeoulTemp(): 위 Open-Meteo URL로 fetch해서 현재 기온(숫자)을 리턴하는 async 함수. res.ok가 false면 에러를 던진다.

과제 2. try/catch 래핑
safeGetSeoulTemp(): getSeoulTemp()를 호출하되 네트워크 에러가 나면 잡아서 null을 리턴한다 (프로그램이 죽지 않게).

과제 3. Pi 온도와 비교
compareToOutside(piTempC): safeGetSeoulTemp()로 외부 기온을 가져와서, Pi 온도(piTempC 인자로 받음)와의 차이를 "Pi가 실외보다 N°C 더 뜨거움" 형식 문자열로 리턴한다. 외부 기온을 못 가져오면 "실외 기온 조회 실패"를 리턴한다.

과제 4 (도전). 병렬 재시도
Day 3의 retry를 async 버전으로 다시 작성한 retryAsync(asyncFn, times = 3)을 만든다 — asyncFn이 계속 reject되면 마지막 에러를 던지고, 재시도 사이에 await new Promise(r => setTimeout(r, 200))로 살짝 대기한다.

✅ 다 작성했으면:
cd ~/Documents/javascript-2주완성
bun _grade.ts day11