Next.js
React 검색 결과가 오래된 응답으로 바뀌지 않게 막은 방법
debounce와 AbortController를 함께 적용한 튜토리얼입니다.
느린 네트워크에서만 보였다
검색창에 next를 입력한 뒤 nextjs를 빠르게 입력하면 먼저 보낸 요청이 늦게 끝나 최신 결과를 덮어썼다. debounce는 요청 수를 줄였지만 이미 나간 요청의 순서를 보장하지 않았다.
취소와 순서 보호를 함께 썼다
const controllerRef = useRef<AbortController | null>(null);
useEffect(() => {
const timer = setTimeout(async () => {
controllerRef.current?.abort();
const controller = new AbortController();
controllerRef.current = controller;
try {
const r = await fetch(`/api/search?q=${encodeURIComponent(query)}`, {
signal: controller.signal,
});
setResults((await r.json()).items);
} catch (e) {
if ((e as DOMException).name !== 'AbortError') setError('검색 실패');
}
}, 250);
return () => clearTimeout(timer);
}, [query]);
요청마다 번호를 부여해 가장 최신 번호만 상태를 변경하게도 했다. 취소는 브라우저 요청을 줄이고, 번호 비교는 이미 서버에서 끝난 응답을 막는다.
검증 메모
느린 응답을 강제로 만들고 a, ab, abc를 빠르게 입력했다. 이전 요청이 취소되는지, 검색어와 결과 기준이 같은지, 정상 취소에 오류 문구가 나오지 않는지 확인했다.
“덜 보낸다”와 “오래된 응답을 반영하지 않는다”는 서로 다른 요구였다.