npm install이 길게 멈춤? registry·tarball CDN을 Clash로 나누는 실측 (2026)
npm install 타임아웃이 registry.npmjs.org와 tarball CDN 두 축에서 갈린다면
프론트엔드·백오피스를 짜는 과정에서 pnpm·yarn·npm 중 무엇을 쓰든, 공통으로 HTTPS가 registry.npmjs.org 트리에 먼저 붙습니다. 카탈로그 JSON까지는 순식간인데 패키지 압축 파일을 받는 단계만 멈추거나 재시작하며 마지막에 ETIMEDOUT이 찍히는 패턴은, 네트워크 전체 실패보다 특정 종단점이 막히거나 패킷이 한 출구회선만 오래 헤매는 증상에 가깝습니다. 패키지마다 다른 백엔드로 리다이렉트된다는 점이 핵심이라, 사용자가 즐겨 쓰는 대형 패키지를 설치했을 때 터미널에 찍히는 각 URL의 호스트네임을 순서대로 적어 두고 Clash 대시보드에서 어떤 분할 규칙에 매칭됐는지 비교해야 정확한 해가 나옵니다.
TUN 모드가 꺼진 상태에서 특정 에디터·터미널만 시스템 프록시를 무시하면, 패킷 차원에서 도메인 규칙이 통하지 않습니다. 레지스트리는 붙지만 tarball만 직통으로 새는 구성으로 보일 수 있습니다. 따라서 패키지 관리 도구 차원에서는 개발자 프록시를 명시했는지, 혹은 모든 프로세스에 동일 게이트가 적용되는지도 함께 점검해야 합니다. 본 글은 기업 또는 개인에게 허용된 법적 범위에서만 동작해야 한다는 전제로, 기술적으로 어떻게 레이어를 분리하는지 알아봅니다.
안내: npm 퍼블리싱 회사와 CDN 제공자는 시간이 지나면 리다이렉트 경로와 저장소 호스트네임을 조정합니다. 따라서 블로그에 고정 된 “완결 목록”은 기준이 되기 어렵고, 사용자 본인의 접속 로그를 첫 페이지로 삼아서 DOMAIN·DOMAIN-SUFFIX 목록만 얇게 시작한 뒤 관측이 붙을 때마다 줄을 하나씩 늘리는 방식을 권합니다.
Docker 데스크톱 또는 오픈 API 글들과 놓치기 쉬운 차별점
Docker 분할 글은 레이어 브리지 안에서 발생하는 패킷 흐름을 다루고, 각종 코드 도우미용 API 분할 글들은 JSON 엔드포인트 레이턴시에 초점을 둡니다. 반면 패키지 설치는 무수히 많은 잡음형 TCP 연속 다운로드로 시간이 김니다. 순간 속도 테스트를 통과한 노드가 대용량 tarball 전송에서는 세션 시간 제한 때문에 떨어져 나가거나, 패킷 손실이 큰 회선 때문에 재전송 블록 반복 때문에만 겉으로 타임아웃처럼 보일 수 있습니다. 그래서 pnpm이나 yarn의 Corepack이 섞일 때처럼 병렬 채널 수가 많을수록 전송 특성 차이도 커져 같은 노드를 공유했을 때 패키지만 실패하기도 하니, 테스트할 때 노드 교체 순서까지 정해 두고 회귀 점검하는 편이 낫습니다.
직장망이라면 패키지 캐시 프록시를 이미 제공하는 경우도 있으니 회사 허브 정책 사이에 놓여 있는지도 확인해야 합니다. 허브를 쓰지 않더라도, 본 글에서는 이미 허브 밖까지 나온 상태에서 순수하게 registry.npmjs.org 패밀리에 붙었을 때의 대시보드를 기준합니다.
ETIMEDOUT·무한 프로그레스 패턴 진단표
아래 패턴이 겹칠 때 Clash 로그 레벨을 올린 뒤 연결 카드 안에서 해당 요청 레코드를 찾으면 원인 접근 속도가 빨라집니다.
- 패키지 메타 패치는 순식간인데
tgz만 멈춤: registry.npmjs.org 앞쪽은 동작하지만, 실제 패키지 본체를 주는 이름이 같은 호스트네임이라도 패스가 장어처럼 꼬이거나 또는 리다이렉트 때문에 다른 패밀리로 이동한 경우입니다. 요청 헤더에 찍히는Location에 주목해야 합니다. - 사무실 Wi-Fi에서는 되지만 집이나 카페에서만 깨짐:
GEOIP로 국내로 직통 보냈을 때 느린 출구 회선이라면 터미널만이라도 해당 그룹에 넣거나, 반대로 막힌 경우만 프록시로 올린다는 선택이 들어옵니다. 이 때 국내 쇼핑몰처럼 민간 사이트를 실수로 전역 프록시에 태워버리면 체감 지연이 생기므로 규칙 우선 순서가 중요합니다. - pnpm 레이어에서는 실패했는데 yarn으로는 통과함: 오프라인 레이어 캐시나 샤드를 다루기 때문에 디스크 I/O 차이처럼 보이기도 하나, 많은 경우엔 패키지를 가져오는 순서 때문에 한 호스트네임부터 붙어버리는 순서 차이 때문입니다.
- 큰 파일만 깨진다면: 중간 회선 또는 노드 업스트림이 회선당 동시 접속 또는 전송 시간 제한 등을 거는 패턴이라 TCP 길게 유지해야 하는 패키지만 실패하게 됩니다.
registry.npmjs.org 패밀리를 시작점으로 하는 DOMAIN-SUFFIX 묶음
registry.npmjs.org 줄 한 줄 자체로도 카탈로그와 일부 패키지 직링크를 포함하는 경우가 있으나 모든 항등식을 보장하지 않습니다. 흔하게는 DOMAIN-SUFFIX npmjs.org 줄을 따라 붙도록 조정합니다. Yarn 클래식 계열에서 흔히 쓰이는 registry.yarnpkg.com 은 이름이 달라도 레지 레이어만 다른 경우가 많으므로 관측된 호스트네임별로 각각 DOMAIN 줄을 넣거나 레지 줄을 각 클라이언트용 YAML 패치로 나누어 관리합니다.
사내 회사 레지 미러 또는 지역별 미러를 쓸 때는 해당 미러 이름이 무엇인지에 따라 DIRECT를 유지해야 합니다. 특히 차이너즈 미러 패턴이라면 GEOIP-CN 전용 블록과 같은 맥락에서 정리해야 합니다. 레지 이름이 명백하게 국내 서비스였다면 DIRECT를 유지시키지만, 패키지가 서명된 공식 패스를 통해 실제 받는 패킷 목적지 이름이 무엇인지 다시 검증해야 합니다. 간단 확인용으로 패키지 JSON에서 tarball 필드의 절대 URL을 복사해 두고 문자열 패턴을 따라가세요.
실무 팁: 패키지를 한 번이라도 받으면 해당 tarball URL이 레지 레이어 또는 로컬 캐시에 남습니다. 그 주소 줄에서 호스트네임 분절별로 줄을 줄여 가며 테스트하면 공격적으로 과도하게 넓은 패턴을 줄일 수 있습니다. 넓은 패턴 하나가 의도하지 않았던 CDN 세그먼트까지 전역 프록시로 끌고 가 버리면 청구서 회선 속도 차이 때문에 일상 업무 패킷 시간이 깨져 버리기도 하니 과도하게 넓지 않게 작성하는 균형 작업입니다.
YAMLproxy-groups:
- name: "NPM-Registry"
type: select
proxies:
- DIRECT
# ... nodes that unblock registry lookups ...
- name: "NPM-Tarball"
type: url-test
url: https://registry.npmjs.org/-/ping
interval: 240
tolerance: 40
proxies:
- DIRECT
# ... nodes that tolerate long downloads ...
- name: "Proxy"
type: select
proxies:
- DIRECT
# ... baseline subscription ...
rules:
# Put concrete observed hosts ahead of GEOIP bundles
- DOMAIN-SUFFIX,npmjs.org,NPM-Tarball
- DOMAIN,registry.yarnpkg.com,NPM-Registry
# Add telemetry-driven entries, e.g.:
# - DOMAIN-SUFFIX,your-registry-mirror.vendor.tld,DIRECT
위 블록은 개념용입니다. url-test 헬스 URL 자체가 npm으로 다시 리다이렉트될 수 있다면 구독사가 제공하는 패시브 테스트 엔드포인트와 혼합해 주기와 허용 편차를 조정해야 합니다. 전략 이름은 구독에 맞춰 바꿀 수 있습니다. 패키지를 프록시로 다 보내기보단 NPM 전용 채널로만 몰며 나머지 일상 패킷은 국내로 직행시키도록 설계해야 하루 사용성이 깨지지 않습니다.
규칙 순서·DNS·Fake-IP 교차 검증과 TUN
첫 줄에서 걸린 규칙이 곧 결과라는 사실 때문에, GEOIP KR DIRECT 한 줄처럼 두껍지만 범위가 넓은 항목이 NPM 줄보다 더 위쪽에 있더라면 터미널 패킷이 이미 해당 줄에서 떨어져 나간 뒤이고 이후 줄은 무의미합니다. 규칙 분할 가이드에 설명 된 것처럼 서비스 전용 줄을 GEOIP 패턴보다 위쪽에 놓거나, 제공자가 만든 규모가 큰 RULE-SET 사이 어디까지 삽입할지 정해야 안정적입니다.
DNS 레이어도 맞물립니다. enhanced-mode: fake-ip 를 쓰더라도 OS 수준 레졸브가 다른 상위 회선만 바라본다면, 애플리케이션에서 이미 받은 레코드 때문에 Clash 레이블이 깨져 버립니다. TUN 가이드처럼 시스템 전체 패킷을 커널 경로까지 흘리는 방안을 테스트해 가며 패키지 패치 전용 프로필을 따로 들고 있습니다. 테스트가 끝나면 과도한 패킷 캡슐링을 줄이도록 주기적인 정리까지 이어져야 업무 패킷에 부담되지 않습니다.
- 문제 패키지를 설치 명령에
--verbose또는 패키지 관리자 제공 진단 플래그를 붙여 실제 HTTPS 대상 줄을 순서대로 저장합니다. - 패널 또는 로컬 로그 파일에서 줄마다 규칙 명과 정책 그룹이 어떻게 표기되는지 캡처합니다.
- 문제 줄을 DIRECT vs 프록시로 바꾸거나 그룹을 바꿔 동일 테스트를 재현합니다.
- 문제 줄이 줄어 들면 과도하게 넓은 패턴을 천천히 잘라 냅니다.
- 동일 테스트를 새벽 회선 상태에서도 재현해야 노드 과부화일지 업스트림 과부화일지를 구별합니다.
위험: 패키지를 완전 무검증으로 받을 수 있는 무제한 업스트림 구독 문자열 또는 커스텀 RULE-SET 을 그대로 놓두면 패키지가 중간 회선 레이어만이라도 교체되어 위변조될 가능성 있습니다. 패키지 수준이 높았을수록 패키지 SHA 검증 기능을 끈 채 테스트하지 말 것을 권장합니다.
FAQ와 관찰 순서 재정리 및 마무리
많은 팀원이 레지 패치가 순식간이면 네트워크 상태가 정상이라고 착각하는데 실제 패키지는 실패합니다. 패키지 JSON과 tarball 사이 간극 때문에 생기므로 패키지마다 줄을 줄인 뒤 NPM 특화 전략 그룹만 조정해야 합니다. Yarn 설정에서 기본 이름이 무엇인지와 pnpm 레지 줄이 어디를 가르키고 있는지만 한 번이라도 명시되어 있으면 끝난 것이며, 회사 허브로 이미 리다이렉트된다면 허브의 인증 패턴과 패키지 캐시 만료 패턴까지 추적해야 합니다.
전역 VPN 한 벌만 켜 놓으면 패키지만이 아니라 스트림·금융·사내 허브 트래픽까지 모두 같은 회선 위로 올라가 체험이 나빠질 때가 많습니다. 반대로 패키지만 전송 안정 회선 위로 피하는 구성이라면 패키지만 안정 속도 회선까지 옮기더라도 국내 쇼핑몰이나 과금 없는 과제 사이트는 국내로 직행시켜 속도 패널티를 줄일 수 있습니다. 다만 패키지만 전달하는 과정이라도 보안 패치 사이즈가 커질 때는 한동안 패킷 패턴이 과장되므로 테스트 주기를 정해 놓습니다.
몇몇 대형 패키지는 메타 줄과 실패 줄이 많은 리다이렉트 사슬 때문에 한 번 테스트에서만으로는 줄이 줄지 않지만, 패턴이 반복될 때마다 작은 줄을 채워 나가며 유지하면 이후 패키지가 바뀌어도 대응이 빨라집니다.
Hugging Face 대용량 LFS 글처럼 카탈로그와 무거운 정적 패스가 이름만 같아도 패킷이 갈라지므로 로그 패턴 학습 습관이 중요합니다. 범위가 넓은 규칙만으로 패키지만 막거나 오탐이 나면 디버깅에 하루를 쓰기도 하지만, 테스트 전용 소규모 프로필로 줄 단위 교체 순서만 정하면 원인 접근 시간이 줄어듭니다.
일반형 VPN처럼 토글 한 번으로 전체 패킷을 같은 출구에 고정해야 하는 도구에서는 registry.npmjs.org처럼 가벼운 메타 줄과 무거운 tarball 줄을 서로 다른 정책으로 나누기 위해 필요한 줄 단위 제어까지 손이 잘 안 닿고, 팀 채널에 공유하려던 규칙 목록이라도 디바이스마다 상태가 살짝씩 다른 경우 디버깅이 길게 이어지기 마련입니다. 반면 ClashSource처럼 DOMAIN-SUFFIX와 규칙 순서까지 자연스럽게 손대는 흐름에 익숙해지면 패키지만 안정 회선 위로 피했다가 일상 패킷은 국내로 남긴 채 테스트 프로파일 하나를 작업 시간에만 켰다가 끄는 식의 조합도 부담되지 않습니다. 문서 허브로 프로파일 패턴을 참고할 수 있으며, 줄마다 짧게 재현 테스트를 돌린 뒤 패키지 전용 규칙만 위쪽으로 재배치해 보길 원하신다면 무료로 ClashSource를 내려받아 같은 절차를 그대로 담아 시작해 보시면 재시도 패턴까지 한 번에 줄일 수 있습니다.