AbortController로 fetch 요청 취소하기
화면 이동이나 검색어 변경 이후에도 이전 네트워크 요청이 계속 실행되면 불필요한 자원을 사용하고, 늦게 도착한 응답이 최신 화면을 덮어쓰는 문제가 생길 수 있습니다. 브라우저에서 제공하는 AbortController를 사용하면 진행 중인 fetch 요청을 명시적으로 취소할 수 있습니다.
기본 사용법
AbortController를 생성하고 컨트롤러의 signal을 fetch 옵션으로 전달합니다. 이후 abort()를 호출하면 해당 신호를 사용하는 요청이 취소됩니다.
const controller = new AbortController();
fetch('/api/posts', {
signal: controller.signal,
});
controller.abort();취소된 요청은 일반적인 네트워크 실패와 구분해서 처리하는 것이 좋습니다.
try {
const response = await fetch('/api/posts', {
signal: controller.signal,
});
const posts = await response.json();
console.log(posts);
} catch (error) {
if (error instanceof DOMException && error.name === 'AbortError') {
return;
}
throw error;
}React에서 요청 정리하기
컴포넌트가 언마운트되거나 의존성이 변경될 때 이전 요청을 취소하면 오래된 응답이 상태를 변경하는 문제를 막을 수 있습니다.
useEffect(() => {
const controller = new AbortController();
async function loadPosts() {
try {
const response = await fetch('/api/posts', {
signal: controller.signal,
});
const posts = await response.json();
setPosts(posts);
} catch (error) {
if (error instanceof DOMException && error.name === 'AbortError') {
return;
}
setError(error);
}
}
loadPosts();
return () => controller.abort();
}, []);시간 제한 적용하기
지원되는 환경에서는 AbortSignal.timeout()으로 지정한 시간이 지난 요청을 취소할 수 있습니다.
const response = await fetch('/api/posts', {
signal: AbortSignal.timeout(5000),
});여러 취소 조건을 함께 사용해야 한다면 AbortSignal.any()로 사용자 취소 신호와 시간 제한 신호를 결합할 수 있습니다.
const controller = new AbortController();
const signal = AbortSignal.any([
controller.signal,
AbortSignal.timeout(5000),
]);
const response = await fetch('/api/posts', {signal});정리
signal을fetch에 전달하면 요청을 취소할 수 있습니다.React에서는 effect의 정리 함수에서 이전 요청을 취소하는 방식이 유용합니다.
AbortError는 실제 장애와 구분해서 처리해야 합니다.시간 제한이 필요하면
AbortSignal.timeout()을 사용할 수 있습니다.

댓글 0