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로만 막을 수 있어서다