요청을 시작할 수 있다면 취소할 수도 있어야 해. AbortController로 오래된 응답이 새 화면을 덮지 않게 만들어 보자.
요청마다 controller를 만들어
AbortController의 signal을 fetch에 넘기면 abort()로 진행 중인 요청을 멈출 수 있어. 컴포넌트가 사라지거나 query가 바뀔 때 cleanup에서 취소해.
오래된 응답이 뒤늦게 도착하는 문제를 막아
사용자가 A를 요청한 뒤 곧바로 B로 바꾸면 A 응답이 더 늦게 도착할 수 있어. 이전 요청을 취소하지 않으면 새 화면을 오래된 A가 덮어쓸 수 있지. Effect가 다시 실행되기 전에 이전 controller를 abort하면 마지막 요청만 상태에 반영돼.
AbortError는 예상된 종료야
취소된 fetch는 오류로 끝나지만 사용자에게 보여 줄 장애는 아니야. Catch에서 AbortError인지 확인해 조용히 끝내고, 네트워크 실패와 서버 오류만 실제 오류 상태로 다뤄.
사용자가 직접 멈출 수도 있어
스트리밍 채팅이나 큰 다운로드처럼 오래 걸리는 작업에는 Stop 버튼을 연결해. Controller를 ref에 보관하면 이벤트 핸들러에서 현재 요청을 취소할 수 있어.
취소 동사는 controller.abort()야
Controller를 만들고 controller.signal을 fetch 옵션에 넘긴 뒤, 새 요청이 이전 요청을 대신하거나 컴포넌트가 사라질 때 controller.abort()를 호출해. Fetch는 AbortError로 끝나고 오래된 응답은 state에 들어오지 않아.
사용자 취소와 timeout을 함께 묶을 수 있어
AbortSignal.timeout(5000)은 5초 뒤 요청을 취소해. 사용자의 controller와 timeout을 모두 적용하려면 AbortSignal.any([controller.signal, AbortSignal.timeout(5000)])를 사용해. 명시적 취소는 AbortError, timeout은 TimeoutError로 구분할 수 있어.