배포 함수에서만 fetch가 끊기면 로컬 회선이 빠른 게 아니라 함수 대기 한도와 아웃바운드 경로가 다르다. ETIMEDOUT과 undici fetch failed의 cause.code를 남기고, maxDuration·AbortSignal·리전을 맞춘다. 개발자, Node.js, 버셀, Next.js, 백엔드, API 기준. 2026년 8월 Node.js·MDN·버셀 문서.
상대 서버가 거절한 게 아니라, 내 쪽이 기다리다 포기한 겁니다. 502는 게이트웨이가 업스트림을 이상하다고 본 응답이고, ETIMEDOUT은 소켓이 시간 안에 연결·읽기를 못 한 시스템 에러입니다.
undici는 Node.js 기본 fetch 구현입니다. TypeError: fetch failed의 cause에 ETIMEDOUT, ECONNRESET, CERT 오류가 붙습니다. 겉 메시지만 보면 네트워크 전체가 죽은 것처럼 보입니다. error.cause.code를 로그하세요.
로컬이 되는 이유는 노트북이 같은 주소를 집 회선으로 바로 치기 때문입니다. 함수는 플랫폼 바깥 경로와 리전, 짧은 기본 시간을 씁니다. 체감이 빨라 보여도 배포 쪽 시계가 더 짧으면 그날따라만 실패하는 것처럼 보입니다.
먼저 기억할 것 | fetch failed만 저장하지 말고 cause.code를 남기세요. ETIMEDOUT이면 시간·리전, CERT이면 인증서, ECONNREFUSED이면 대상 포트입니다.
함수 최대 시간과 fetch 타임아웃 중 먼저 오는 쪽이 로그에 남는다
시계가 세 개다, 함수·fetch·상대 서버
세 시계 중 가장 짧은 값이 이깁니다.
시계
무엇을 자르나
어디에 있나
함수 maxDuration
핸들러 전체
버셀 등 플랫폼 설정
AbortSignal.timeout
그 fetch 한 번
코드
상대 서버
원본이 느림
외부 API SLA
프록시/NAT
유휴 연결
플랫폼 아웃바운드
함수가 10초인데 fetch를 30초로 두면, 10초에 플랫폼이 자릅니다. 로그는 타임아웃이 아니라 함수 킬로 남을 수 있습니다. 반대로 fetch를 3초로 두면 cause가 AbortError입니다. ETIMEDOUT은 보통 OS 소켓 한도입니다.
응답 후 작업은 after로 빼면 사용자 요청 시계와 분리됩니다. 사용자에게 줄 값은 짧은 fetch만 남기세요.