npm ERR! code E502로 502 Bad Gateway 반복될 때 (Windows + npm Registry)

Overloaded npm registry gateway causing 502 errors during install on Windows

이 증상은 설치 자체가 막혀 빌드/배포가 즉시 중단되는 손해로 직결되므로, 원인 추적보다 “우회 설치 경로 확보 + 재시도 폭주 차단”이 먼저입니다(2026 환경 기준).

중요 안전장치: 이 작업은 반드시 관리자 권한(Run as Administrator)으로 실행된 터미널에서 진행하십시오(사내 보안/정책 환경에서 npm 설정 반영이 막히는 경우가 있습니다).

기술 상황 정의(Environment): Windows / Node.js + npm / npm Registry(HTTP 게이트웨이·CDN) / 기업망 프록시·DNS·SSL 검사 가능성

2026 포인트: 레지스트리 앞단의 CDN·게이트웨이 계층이 분리된 구조에서 일부 POP/경로만 흔들려도, 클라이언트가 정상이어도 502가 반복될 수 있습니다.

npm ERR! code E502 / 502 Bad Gateway / request to https://registry.npmjs.org/… failed

결론 요약: 레지스트리(또는 그 앞단 게이트웨이)가 불안정해 정상 요청이 502(E502)로 튕기는 상태일 때 동일 증상이 재현됩니다.

해결 흐름: 판단 → 분리 → (즉시 코드) → 복구

✅ 바로 적용 (Quick Fix)

결정 문장: “오류가 반복되면 아래 코드부터 실행한다.”

WHY: 지금은 원인(장애 원인/네트워크 경로)보다 호출 밀도 제어(재시도 간격) + 지터(랜덤 지연) + 필요 시 레지스트리 우회로 설치를 살리는 게 우선입니다.

METRIC: npm ERR! code E502 / 502 Bad Gateway 메시지가 멈추거나, 실패 빈도가 눈에 띄게 감소합니다.

NEXT: 해결되면 본문 절차는 건너뛰고 종료합니다.

# 관리자 권한 PowerShell에서 실행 (Run as Administrator)
# 1) 순간적인 게이트웨이 튐을 흡수하도록 npm 재시도 파라미터 확장
npm config set fetch-retries 5
npm config set fetch-retry-mintimeout 20000
npm config set fetch-retry-maxtimeout 120000

# 2) (선택) 사내 미러/프록시 레지스트리가 있으면 그쪽으로 우회 (사용 가능한 URL만)
# npm config set registry https://YOUR_MIRROR_REGISTRY/

# 3) 지터(Jitter)로 동시 폭주를 피한 뒤 설치 1회 시도
Start-Sleep -Seconds (Get-Random -Minimum 2 -Maximum 5)
npm install --no-audit --no-fund

🧩 확인 코드 (Verification)

WHY: 서버(레지스트리/게이트웨이) 문제인지, 로컬(프록시/인증/네트워크) 문제인지 실제 요청 1회로 분리합니다.

METRIC: STATUS(상태코드)와 ERROR가 출력되고, 5xx인지(서버/게이트웨이) 4xx인지(인증/차단) 연결 오류인지(DNS/프록시/방화벽) 구분됩니다.

NEXT: 5xx면 Quick-Fix 유지, 4xx/연결오류면 아래 정밀 절차(프록시·DNS·캐시·정책)로 이동합니다.

# Windows용 원라인 진단: 실제 GET 1회 + 상태코드/응답크기 출력 (헤더만 조회하지 않음)
node -e "const https=require('https');const url=process.argv[1]||'https://registry.npmjs.org/react';const t=Date.now();https.get(url,r=>{let b=0;r.on('data',c=>b+=c.length);r.on('end',()=>{console.log('URL:',url);console.log('STATUS:',r.statusCode);console.log('BYTES:',b);console.log('MS:',Date.now()-t);process.exit(r.statusCode===200?0:1);});}).on('error',e=>{console.log('URL:',url);console.log('ERROR:',e.name,e.message);console.log('MS:',Date.now()-t);process.exit(1);});"

🧯 복구 코드 (Recovery)

WHY: 재시도만 늘리면 로그 폭증/빌드 타임아웃이 생기므로, 정해진 횟수만 재시도 + 지터 백오프 + 실패 시 즉시 중단으로 손실을 최소화합니다.

METRIC: 재시도 로그 폭증이 멈추고, 성공 시 설치가 진행되며, 실패 시 “즉시 중단 후 우회 정책(미러/캐시)”로 전환됩니다.

NEXT: 끝까지 실패하면 이 시점부터 로컬 조치를 중단하고(PC 파일 삭제 같은 파괴적 조치 금지), 조직 단위의 미러/CI 캐시/프록시 정책으로 관리합니다.

# PowerShell 재시도 루프 (Windows 기본 환경 친화)
# - 성공하면 즉시 종료
# - 실패하면 지터 백오프 후 재시도
# - 최종 실패 시 1로 종료(파이프라인에서 우회 정책 트리거 용도)
$ErrorActionPreference = "Stop"
$max = 4

for ($i = 1; $i -le $max; $i++) {
  Write-Host ("Attempt {0}/{1}" -f $i, $max)
  try {
    npm install --no-audit --no-fund
    Write-Host "OK"
    exit 0
  } catch {
    $sleep = Get-Random -Minimum 2 -Maximum 7
    Write-Host ("FAILED -> backoff(s)={0}" -f $sleep)
    Start-Sleep -Seconds $sleep
  }
}

Write-Host "FAILED: stop local actions; switch to mirror/CI cache policy"
exit 1

✅ 발생 증상

npm install 또는 npm ci 실행 중 npm ERR! code E502와 함께 502 Bad Gateway가 특정 패키지에서 반복됩니다.

같은 커밋/같은 package-lock.json인데도 어떤 시도는 통과하고 어떤 시도는 실패합니다.

다운로드 단계(레지스트리 메타데이터 조회/타르볼 fetch)에서 멈추고, 이후 의존성 해석이 진행되지 않거나 중간에 중단됩니다.

기업망에서는 프록시(407), 접근 차단(403), 인증/토큰 문제(401)처럼 4xx가 섞여 보일 수도 있어 “상태코드로 먼저 분리”가 필요합니다.

❌ 원인 분석

502(E502)는 “클라이언트 요청이 게이트웨이까지는 도착했지만, 게이트웨이가 업스트림(레지스트리/스토리지)에서 정상 응답을 못 받아 실패”할 때 흔히 나타납니다.

즉, A(5xx 반복)라면 로컬 파일을 삭제해도 본질이 해결되지 않고, 네트워크 경로/게이트웨이 상태에 따라 성공과 실패가 갈립니다.

동시에 많은 install이 발생하면 같은 호스트로의 요청이 폭주하고, 게이트웨이 레벨에서 실패가 튈 확률이 올라갑니다.

그래서 재시도는 “빨리 많이”가 아니라 “느리게, 랜덤하게, 제한적으로” 해야 하며, 실패 누적 시에는 즉시 중단 후 우회 경로로 전환해야 합니다.

[npm client] --GET--> [CDN/Edge] --proxy--> [Gateway] --upstream--> [registry backend / storage]
     |                      |                 |                      |
     |<-----502/E502---------|  (edge/path)    |<---timeout/overload--|

🧠 기술적 배경 이해 (감리사 1차 판정 구역)

npm 설치는 “메타데이터 조회(패키지 버전/의존성) → tarball 다운로드 → 무결성 검증 → 압축 해제”의 흐름으로 진행됩니다.

이 중 E502가 자주 터지는 구간은 메타데이터 조회 또는 tarball fetch이며, 실제로는 CDN/게이트웨이를 통해 라우팅되는 HTTP 요청 묶음입니다.

게이트웨이가 순간 과부하/경로 장애를 겪는 상태에서 클라이언트가 즉시 재시도를 반복하면, 실패한 요청이 더 많은 재요청을 만들어 병목이 더 커집니다.

Backoff/Jitter는 재시도 간격을 늘리고 랜덤 지연을 섞어 “동시에 다시 몰리는 파동”을 깨뜨려, 같은 총 요청량이라도 성공 확률을 높이는 전략입니다.

Circuit Breaker 관점에서는 일정 횟수 실패 후 즉시 중단하고(회로 차단), 다른 경로(미러/캐시)로 전환해 전체 파이프라인을 살려야 합니다.

Windows 기업 환경에서는 프록시(WinHTTP/브라우저 프록시), SSL 검사, DNS 정책이 끼어들 수 있어 5xx처럼 보여도 실제 원인이 4xx/연결오류인 경우가 존재합니다.

📊 빠른 구분표 (Decision Table)

이 경우에는 A로 판단한다: Verification에서 STATUS가 502/503/504 등 5xx로 반복되면 A(서버/게이트웨이 불안정)입니다.

이 경우에는 B로 판단한다: Verification에서 STATUS가 401/403/407 등 4xx이거나 ERROR가 DNS/연결불가/프록시 관련이면 B(프록시/인증/네트워크 경로)입니다.

A면 Quick-Fix, 아니면 정밀 절차로 이동한다.

이 시점부터 로컬 조치를 중단한다: A인데도 PC 파일 삭제/레지스트리 수정 같은 로컬 파괴 조치는 효과가 없으니 중단합니다.

코드 블록이 없는 글은 해결 글이 아니다.

✅ 해결 방법 (WHY / METRIC / NEXT)

1) A(5xx/E502)이면 “호출 밀도 제어(재시도 정책)”부터 고정합니다.

WHY: 순간 장애는 재시도 전략만으로도 통과 가능하며, 연속 재시도는 오히려 실패를 확대합니다.

METRIC: 같은 패키지에서 E502 반복 빈도가 줄고, 설치가 어느 시점부터 진행되기 시작합니다.

NEXT: 아래 설정을 적용한 뒤, 지터를 섞어 재설치합니다.

npm config set fetch-retries 5
npm config set fetch-retry-mintimeout 20000
npm config set fetch-retry-maxtimeout 120000
Start-Sleep -Seconds (Get-Random -Minimum 2 -Maximum 5)
npm install --no-audit --no-fund

2) B(프록시/정책) 가능성이 있으면 “Windows 프록시 + npm 프록시 설정”을 먼저 확인합니다.

WHY: 407/403/연결오류는 레지스트리 장애가 아니라 “경로가 막힌 것”이므로, 재시도로는 해결되지 않습니다.

METRIC: 프록시 확인 후 Verification의 STATUS가 4xx/ERROR에서 200 또는 5xx로 바뀌며 원인 구분이 확정됩니다.

NEXT: 아래에서 프록시 잔존 설정을 확인하고, 조직 정책에 맞게 정리합니다.

# npm 프록시 설정 확인(값이 남아 있으면 조직 정책에 맞게 수정/삭제)
npm config get proxy
npm config get https-proxy

# Windows WinHTTP 프록시 확인(서버 환경에서 특히 영향)
netsh winhttp show proxy

# (선택) 조직 정책에 따라 프록시를 초기화해야 하는 경우만 사용
# netsh winhttp reset proxy

3) 캐시/락파일 기반으로 “외부 fetch 의존”을 줄여 CI/재시도 비용을 낮춥니다.

WHY: 외부 레지스트리 순간 장애가 CI를 매번 멈추게 만들면 릴리즈가 흔들리고, 동일 커밋 재시도 비용이 누적됩니다.

METRIC: 동일 커밋 재빌드에서 외부 요청량이 줄고, 실패가 캐시로 흡수되거나 재시도 루프로 제한됩니다.

NEXT: CI는 npm ci를 기본값으로 두고, 실패 시 Recovery 루프로 제한적으로 회복을 시도합니다.

# lockfile 기반 재현 설치(개념): npm ci 우선
npm ci --no-audit --no-fund

⚠️ 그래도 안 될 경우 체크리스트

관리자 권한 터미널인지 확인합니다(도구: PowerShell 제목에 Administrator 표시 또는 권한 관련 오류 발생 여부).

현재 레지스트리 설정을 확인합니다(도구: npm config get registry).

npm 캐시 경로를 확인합니다(도구: npm config get cache; 일반적으로 %AppData%\npm-cache 계열).

WinHTTP 프록시가 설정돼 있는지 확인합니다(도구: netsh winhttp show proxy).

DNS 해석이 흔들리는지 확인합니다(도구: Resolve-DnsName registry.npmjs.org 또는 nslookup registry.npmjs.org).

특정 시간대에만 실패하는지 확인합니다(도구: Verification 원라인을 시간 간격 두고 1회씩 실행).

패키지 하나만 실패하는지 확인합니다(도구: Verification URL을 다른 패키지로 바꿔 1회 호출).

보안 솔루션의 SSL 검사/차단 로그가 있는지 확인합니다(도구: 사내 에이전트 콘솔/이벤트 로그/보안팀 문의).

❓ FAQ

Q. 제목/로그에 npm ERR! code E502가 찍히면 무조건 서버 문제인가요?

A. 자주 그렇지만 항상은 아닙니다(프록시/SSL 검사 환경에서는 경로가 끊겨도 비슷하게 보일 수 있어, Verification 상태코드로 확정하는 게 안전합니다).

Q. npm cache clean –force를 해야 하나요?

A. A(5xx/E502 반복)에서는 캐시 파괴보다 재시도/지터/우회가 먼저이며, 캐시 삭제는 마지막 수단으로만 사용합니다.

Q. 캐시를 마지막 수단으로 점검/정리하려면 무엇을 쓰나요?

A. 먼저 npm cache verify로 무결성 점검을 하고, 그래도 필요할 때만 npm cache clean –force를 사용합니다.

Q. yarn/pnpm으로 바꾸면 해결되나요?

A. 레지스트리/게이트웨이가 문제면 어떤 클라이언트든 영향받을 수 있어, 우회 레지스트리/백오프가 더 직접적입니다.

Q. status 페이지가 정상인데도 502가 나올 수 있나요?

A. 가능합니다(지역 CDN/특정 경로/일부 POP 장애 등)하므로, “내 경로에서 실제 요청 1회”로 판단합니다.

✅ 요약 및 마무리

이 경우에는 A로 판단한다: Verification에서 5xx(특히 502/E502)가 반복되면 서버/게이트웨이 문제입니다.

A면 Quick-Fix(재시도+지터) 유지, 아니면 정밀 절차(프록시/인증/네트워크)로 이동합니다.

이 시점부터 로컬 조치를 중단한다: A에서 파일 삭제/레지스트리 수정 같은 파괴적 조치는 효과가 없으니 중단합니다.

코드 블록이 없는 글은 해결 글이 아니다.

참고 자료

npm Status