본문 바로가기
IT·개발

Promise.all이 실패했는데 다른 작업은 계속돼요: catch와 취소는 달라요

by Runer 2026. 10. 27.
반응형

여러 작업을 Promise.all로 기다리다가 catch에 들어왔는데, 잠시 뒤 다른 작업의 완료 로그가 찍히나요? 이상한 재실행이라고 단정하기 전에 원래 작업이 계속 진행 중이었는지 확인해 보세요. Promise.all의 결과가 거부돼도 다른 작업이 자동으로 취소되지는 않아요.

따라서 catch는 묶음의 실패를 알리는 곳이에요. 모든 작업이 실패했다거나, 이미 끝난 일이 되돌아갔다는 증거는 아니에요. 외부 전송·저장이 있는 묶음이라면 전체 재시도 전에 각 작업의 상태가 특히 중요해요.

실패를 먼저 확인하고, 남은 작업은 나중에 끝내 볼게요

아래 코드는 외부 서버 없이 실행할 수 있어요. slow를 끝내는 함수를 따로 보관하고, catch가 실행된 다음 직접 완료시켜요. 실제 시간 지연이나 인터넷 속도에 기대지 않고 두 사건의 순서를 확인하는 예제예요. Node.js에서는 .mjs 파일로 실행할 수 있어요.

const events = [];
let finishSlow;

const slow = new Promise((resolve) => {
    finishSlow = () => {
        events.push("slow finished");
        resolve("slow ok");
    };
});
const failed = Promise.reject(new Error("fast failed"));
const tasks = [slow, failed];

try {
    await Promise.all(tasks);
} catch (error) {
    events.push(`caught: ${error.message}`);
}
console.log(JSON.stringify(events));

finishSlow();
const outcomes = await Promise.allSettled(tasks);
console.log(JSON.stringify(events));
console.log(JSON.stringify(outcomes.map((item) => item.status)));
["caught: fast failed"]
["caught: fast failed","slow finished"]
["fulfilled","rejected"]

첫 줄에서는 묶음의 오류를 이미 잡았지만 slow는 아직 완료되지 않았어요. 그 뒤 finishSlow를 호출하니 같은 slow가 정상 완료돼요. 실패 처리로 이동했다는 이유만으로 slow를 끝낼 수 없게 된 것은 아니에요.

마지막 allSettled에는 같은 tasks를 넘겼어요. 작업 생성 함수를 다시 호출하지 않았으므로 새로운 두 작업을 시작한 예제가 아니에요. 이미 만든 Promise들의 최종 상태를 모두 기다려 읽었어요.

결과 배열의 순서는 완료 순서가 아니에요

failed가 먼저 거부됐어도 결과 상태는 fulfilled, rejected 순서예요. tasks의 첫 항목이 slow이기 때문이에요. 결과를 원래 작업 ID와 연결할 때는 배열에 넣은 순서를 유지해야 해요. allSettled의 각 결과는 fulfilled이면 value, rejected이면 reason을 확인하는 구조예요.

필요한 결과 사용할 수 있는 대기 방식 별도로 설계할 것
모두 성공해야 다음 결과 계산 Promise.all 실패 뒤에도 진행되는 작업의 처리
각 작업의 성공·실패 결과 전부 확인 Promise.allSettled 실패 항목과 원래 ID 연결
남은 작업 중단 또는 이미 한 일 취소 각 작업이 지원하는 취소·보정 절차 확인 대기 함수만 바꿔 해결됐다고 가정하지 않기

catch에서 배열 전체를 다시 실행하기 전에

예를 들어 가상의 A·B·C 전송 중 B만 오류로 알려졌다고 해볼게요. A는 이미 끝났고 C는 아직 진행 중일 수 있어요. 이 상태에서 세 전송 함수를 다시 호출하면 A의 중복 전송이나 두 C의 겹침이 생길 여지가 있어요. 이 예시는 실제 서비스의 장애 사례나 측정 결과가 아니라, 작업별 상태를 확인해야 하는 이유를 설명하는 상황이에요.

기록을 남길 때는 묶음 실패 한 줄과 함께 작업 ID별 결과를 연결해 두세요. 응답이 없다는 것과 서버에 반영되지 않았다는 것은 실제 서비스에서 따로 확인할 문제예요. 재시도가 필요한 작업과 중복 실행을 막는 방법은 해당 서비스의 계약을 기준으로 정해야 해요.

이 코드는 Node.js 24.19.0에서 실제 실행해 출력 순서를 확인했어요. 네트워크 요청·취소 신호·외부 저장은 사용하지 않았어요. 자신의 코드에서는 Promise.all 앞에서 작업을 어디서 생성했는지, 실패 후 무엇이 계속 실행되는지부터 확인해 보세요.

요청 한 건의 HTTP 실패를 먼저 확인하고 싶다면: fetch의 404와 catch

참고 자료 · 2026-10-27 확인

MDN — Promise.all의 첫 거부와 다른 작업의 지속

MDN — Promise.allSettled의 결과와 입력 순서

ECMAScript 명세 — Promise.all 알고리즘

반응형