문제 상황
대량 청구서를 발송 중에 취소하는 로직이 필요했습니다.
그래서 fetch 비동기 통신을 취소하는 abortController를 사용했습니다.
🚨 주의사항
abortController는 프론트의 요청만 취소하는 것임을 알아야 합니다.
요청 이후에 백엔드에서 일어나는 일은 제어할 수 없습니다.
예를 들어 청구서 발송을 클릭하고, 곧바로 취소를 눌러서 요청을 취소했다하더라도 백엔드에서는 발송이 시작된 상태이고 이것을 취소할 수는 없습니다.
저는 위와 같은 이유로 해당 로직을 작성했지만, 사용하지는 못했습니다 :(
해결 방법
메일을 발송하는 로직을 훅으로 만들어서 사용하는 컴포넌트에서 호출하도록 했습니다.
import AbortController from "abort-controller";
export function useSendInvoice(emails: React.Key[]) {
// sendInvoice 함수 실행 시 새로 생성하나 리렌더링은 막기 위해 useRef 사용
// 새로 생성하는 이유는 한 번 취소하면 계속 {aborted: true} (취소상태)로 호출되기 때문임
const abortControllerRef: MutableRefObject<AbortController | null> = useRef(null);
const url = `${process.env.NEXT_PUBLIC_API_ENDPOINT}/billing/invoice/send/mail`;
async function sendInvoice() {
abortControllerRef.current = new AbortController();
try {
const res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("loginToken")}`,
},
body: JSON.stringify({ emails }),
signal: abortControllerRef.current.signal as AbortSignal,
});
const { resultCode, result } = await res.json();
if (res.status !== 200 || resultCode !== "SUCCESS") {
return { success: false, errorType: "unknown error" };
}
return { success: true, data: result };
} catch (err) {
const errorObj = err as Error;
if (errorObj.name === "AbortError") {
return { success: false, errorType: "aborted" };
}
return { success: false, errorType: "unknown error" };
}
}
// fetch 요청만 중간에 취소되고 메일은 다 발송되서 사용 안 함
function cancelSend() {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
}
return { sendInvoice, cancelSend };
}
useRef를 사용한 이유
취소한 이후에 sendInvoice
를 호출하면 {aborted: true}
(취소상태)로 호출되는 문제가 발생했습니다.
useRef를 사용하여 sendInvoice를 호출할 때마다 abortControllerRef.current sendInvoice
를 새로 생성하나, 리렌더링은 되지 않도록 처리했습니다.
'Programming > Client' 카테고리의 다른 글
Amazon S3 Pre-signed URL의 만료 시간 검사하기 (0) | 2024.10.13 |
---|---|
body 스크롤 확실하게 막기 (0) | 2024.06.07 |
[Javascript] 파일 및 모듈 내보내기 (script / Common JS / ES Modules 그리고 Bundler) (1) | 2023.09.30 |
[MSW] 브라우저, Node.js 환경에서 API 모킹하기 (0) | 2023.05.22 |
Javascript / React에서 Fetch 올바르게 사용하기 (with Node.js 테스트 환경) (0) | 2023.05.21 |