in-flight란

  • 보냈지만 아직 응답이 안 온, 진행 중인 요청/작업. 비행기가 이륙은 했는데 착륙 안 한 상태에 빗댄 말
  • "3 requests in-flight" = 동시에 처리 대기 중인 요청 3개

왜 중요한가 — 대표 패턴 3개

1. 중복 요청 제거 (in-flight dedup)

같은 요청이 진행 중이면 새로 안 쏘고 기존 것을 재사용한다.

const inflight = new Map();

function fetchUser(id) {
  if (inflight.has(id)) return inflight.get(id); // 이미 진행 중 → 그거 반환
  const p = fetch(`/api/user/${id}`).finally(() => inflight.delete(id));
  inflight.set(id, p);
  return p;
}

버튼 연타·동시 렌더로 같은 API가 여러 번 나가는 것을 막는다. React Query·SWR이 내부적으로 이걸 한다.

2. 진행 중 요청 취소 (abort)

새 요청이 오면 이전 in-flight 요청을 버린다. 검색 자동완성에서 필수.

let controller;
function search(q) {
  controller?.abort(); // 이전 in-flight 취소
  controller = new AbortController();
  return fetch(`/search?q=${q}`, { signal: controller.signal });
}

늦게 도착한 옛 응답이 최신 결과를 덮어쓰는 race condition을 막는다.

3. 진행 중 개수 추적

로딩 스피너, rate limit, graceful shutdown("in-flight 요청 다 끝날 때까지 대기 후 종료")에 쓴다.

캐시와의 관계 — 두 개의 다른 층

in-flight도 저장소라 캐시처럼 보이지만, 완료된 값이 아니라 미완료 Promise를 담는다.

데이터 캐시in-flight (프로미스 캐시)
저장완료된 응답값아직 안 끝난 진행 중 Promise
시간축과거 (이미 받음)현재 (기다리는 중)
목적재요청 자체를 안 함동시 요청을 하나로 합침

왜 캐시만으론 부족한가

t=0ms   요청 A 나감 → 캐시 미스 → fetch 시작
t=5ms   요청 B 들어옴 → 캐시 여전히 비어있음(A 미도착) → 또 fetch  ❌
t=100ms A 응답 도착 → 그제서야 캐시 채워짐

첫 응답이 오기 전 창(0~100ms)엔 캐시가 비어 있어 그 사이 요청이 중복으로 나간다. 이 구멍을 메꾸는 것이 in-flight다.

둘을 합친 표준 흐름

요청 들어옴
  ├─ ① 데이터 캐시에 값 있나?    → 있으면 그 값 반환 (끝)
  ├─ ② in-flight에 진행 중 있나? → 있으면 그 Promise 반환 (재사용)
  └─ ③ 둘 다 없으면
        → 새 fetch + in-flight 등록
        → 완료되면 in-flight에서 제거하고 데이터 캐시로 이동
const cache = new Map(); // 완료된 값
const inflight = new Map(); // 진행 중 Promise

function getUser(id) {
  if (cache.has(id)) return Promise.resolve(cache.get(id)); // ① 캐시 히트
  if (inflight.has(id)) return inflight.get(id); // ② in-flight 재사용

  const p = fetch(`/api/user/${id}`) // ③ 새 요청
    .then((r) => r.json())
    .then((data) => {
      cache.set(id, data); // 완료 → 캐시로
      inflight.delete(id); // in-flight에서 제거
      return data;
    });
  inflight.set(id, p);
  return p;
}

라이브러리

  • React Query / SWR — 같은 key 요청을 자동 dedup(내부 in-flight 추적) + 데이터 캐시
  • Apollo(GraphQL) — query dedup + normalized cache
  • 참고: npm inflight 패키지는 메모리 누수로 deprecated. 지금은 Promise+Map으로 직접 하거나 lru-cache 등을 쓴다

정리

  • in-flight = 아직 응답 대기 중인 진행 중 요청. 추적하면 중복 제거·취소·개수 관리가 된다
  • 데이터 캐시(완료값)와 짝을 이뤄야 하는 이유: 첫 응답 전 창의 중복 요청은 데이터 캐시로는 못 막고 in-flight로만 막을 수 있어서다