개발 환경·macOS · · 약 18분 소요

macOS에서 Homebrew(brew)가 병·GHCR에서 타임아웃 날 때: formula·Bottle CDN·ghcr.io를 Clash(mihomo)로 분기·DNS를 맞추는 실측 (2026)

검색창에 brew update 타임아웃이나 brew install 느림을 넣는 분들은 보통 한 줄짜리 우회가 아니라 재현 가능한 출구 정리를 원합니다. Homebrewbrew.sh·formulae.brew.shformula 메타와 JSON API를 보고, 실제 bottle 바이너리는 ghcr.io(GHCR), github.com 릴리스 자산, objects.githubusercontent.com 같은 CDN·스토리지 호스트로 이어지는 경우가 많습니다. 그래서 브라우저는 빠른데 터미널만 멈추거나, brew update는 끝나는데 brew install만 끊기는 비대칭 증상이 반복됩니다. 이미 켜 둔 Clash 또는 mihomo에 호스트 묶음 분기 규칙을 두고 DNS·클라이언트 시스템 프록시/TUNmacOS 터미널과 맞추면 같은 증상이 크게 줄어듭니다. pip·PyPI를 Clash로 묶은 적이 있다면 흐름은 같고, 대상 FQDN만 GitHub·Homebrew 축으로 바꾸면 됩니다.

1. brew가 한 도메인만 쓰지 않는 이유

Homebrew는 패키지 정의(formula)를 가져오고, 미리 빌드된 바이너리(bottle)를 내려받아 설치하는 파이프라인입니다. 정의 파일·버전 메타는 github.com의 Homebrew 조직 저장소나 API 응답을 타고, 실제 병 아티팩트는 ghcr.io 컨테이너 레지스트리나 GitHub가 제공하는 객체 스토리지 URL로 연결되는 구성이 대표적입니다. 중간에 pkg-containers.githubusercontent.com처럼 리다이렉트 체인이 길어지는 경우도 있어, 개발자 입장에서는 「brew 명령 하나」처럼 보여도 네트워크 레이어에서는 서로 다른 FQDN 묶음을 순서대로 두드리는 셈입니다.

Clash 분기에서 실수하기 쉬운 패턴은 GEOIP 기본 규칙만 두고 github.com 한 줄만 예외로 올려 두는 경우입니다. 그러면 API는 빠른 노드로 갔다가 objects.githubusercontent.com 줄만 느린 노드로 새거나, 반대로 TLS 연결이 특정 회선에서만 지연되는 식의 부분 실패가 남습니다. mihomo 연결 목록을 호스트명 기준으로 정렬해 보면 어느 단계에서 정책이 갈라지는지 금방 드러납니다.

2. 증상 나누기: update vs 병 GET

먼저 brew update -v로 갱신 단계에서 멈추는 URL이 무엇인지 확인하세요. brew install -v 패키지명은 다운로드 진행률이 특정 퍼센트에서 오래 멈추거나 curl: (28) Operation timed out 비슷한 메시지로 끝나는지 봅니다. brew update는 비교적 빠른데 brew install만 실패한다면, 메타는 되었고 bottle·릴리스 자산 축의 출구가 잘못됐을 가능성이 큽니다. 반대로 처음부터 TLS 핸드셰이크가 길다면 노드 품질·SNI 정책도 의심하고 구독·TLS·DNS 로그 절차를 같이 적용합니다.

한 줄 정리

install 단계만 끊긴다면 ghcr.io·objects.githubusercontent.com·릴리스 호스트를 github.com API 줄과 같은 정책 그룹으로 올려 두는 것부터 점검하세요.

3. macOS 터미널과 Clash 출구: 시스템 프록시·TUN

macOS에서 Clash Verge Rev 같은 GUI는 시스템 프록시 패스를 켜거나 TUN으로 전체 트래픽을 끌어올립니다. 터미널의 curl·brew가 어떤 경로를 타는지는 설정 조합에 따라 달라지므로, 「브라우저만 빠름»과 동시에 나오면 시스템 확장 권한·프로파일 적용 여부를 다시 확인합니다. 처음 설치하는 분은 macOS에서 Verge Rev 시스템 프록시·TUN 가이드로 베이스를 맞춘 뒤 본문 절차를 이어가면 재시도 낭비가 줄어듭니다.

글로벌 모드에만 의존하기보다 규칙 모드에서 GitHub 축을 확실히 잡아 두면, 일상 업무 트래픽과 brew 대용량 다운로드를 같은 안정 노드로 묶기 쉽습니다. 장시간 받는 병이 있다면 url-test·fallback으로 손에 익은 레인을 고정하는 것도 실무 팁입니다.

4. Clash 규칙 예시: GitHub·GHCR·Homebrew CDN

프로필 rules: 앞쪽(높은 우선순위)에 아래와 같은 축을 모읍니다. PROXY는 본인 YAML의 실제 정책 그룹 이름으로 바꿉니다. 프로젝트마다 커스텀 formula 미러가 있으면 그 호스트를 별도 DIRECT 규칙으로 분리해 두세요.

# Example rules — replace PROXY with your policy group name
rules:
  - DOMAIN-SUFFIX,github.com,PROXY
  - DOMAIN-SUFFIX,githubusercontent.com,PROXY
  - DOMAIN-SUFFIX,github.io,PROXY
  - DOMAIN-SUFFIX,ghcr.io,PROXY
  - DOMAIN-SUFFIX,brew.sh,PROXY
  - DOMAIN-SUFFIX,homebrew.sh,PROXY

실제 실패 로그에 objects.githubusercontent.com·pkg-containers.githubusercontent.com·특정 *.fastly.net 류가 찍히면 같은 그룹으로 추가합니다. 규칙·정책 그룹 문서와 함께 보면 RULE-SET과 로컬 예외의 순서를 정리하기 쉽습니다. rule-providers를 쓰더라도 GitHub·GHCR 전용 줄은 상단에 두는 편이 덜 깨집니다.

보안: 회사 중간 프록시가 TLS를 검사하는 환경이라면 키체인 신뢰과 정책을 먼저 맞추세요. curl에 검증 무시 옵션을 습관화하면 감사·보안 사고 리스크가 커집니다.

5. DNS·fake-ip를 brew 프로세스와 맞추기

분기는 도메인 문자열과 Clash가 본 IP 결과가 한 흐름일 때 가장 잘 맞습니다. fake-ip를 쓰는데 터미널만 시스템 리졸버로 직접 묻고 있으면, GUI 앱과 brew가 다른 경로를 보는 것처럼 행동합니다. DNS·fake-ip·redir-host 글의 절차를 Homebrew 시나리오에 맞게 단축 적용하세요. 듀얼 스택에서 간헐적 실패가 남으면 IPv6·DNS 보정 체크리스트를 병행합니다.

Safari나 Chrome의 DoH가 켜져 있고 Clash DNS와 충돌하는 경우도 있으므로, 브라우저만이 아니라 시스템 전체에서 어떤 리졸버가 우선인지 한 번씩 점검하는 것이 좋습니다. TUN 모드라고 해서 터미널 예외가 없다고 단정하지 말고, 실제 연결 로그로 검증하세요.

6. HOMEBREW_* 변수와 미러: 보조 수단

팀 정책에 따라 공식 미러나 사내 프록시를 씁니다. HOMEBREW_BOTTLE_DOMAIN 등으로 병 베이스 URL을 바꾸면 호스트 패턴이 달라지므로, 미러 문서에 나온 FQDN을 Clash 규칙에 다시 반영해야 합니다. 미러가 여전히 GitHub 객체 URL로 리다이렉트한다면 본문의 GitHub 축 규칙이 그대로 필요합니다.

brew install --build-from-source나 팀 내부 미러 설정은 다운로드 위치를 바꿀 수 있지만 빌드 시간·의존성 컴파일 비용이 커지고, 근본적인 회선 문제를 가리지는 못하는 경우가 많습니다. 우선 Clash·DNS로 출구를 안정화한 다음에 최적화를 검토하는 편이 운영 부담이 적습니다. 컨테이너 개발과 겹친다면 Docker Hub 분기 글과 출구 정책을 맞춰 두면 재현성이 좋아집니다.

7. curl·verbose로 호스트 역추적

동일 터미널 세션에서 Clash를 켠 상태로 curl -vI https://github.com, curl -vI https://ghcr.io, curl -vI https://formulae.brew.sh를 나란히 실행해 TLS·HTTP 지연 차이를 비교합니다. brew install -v 재시도 시 mihomo 로그에서 해당 시각의 호스트·정책·노드 이름을 대조합니다. 특정 도메인만 바꿔 DIRECTPROXY를 번갈아 가며 대조 실험하면 원인이 회선인지 규칙인지 빠르게 갈립니다.

로그에 GitHub 호스트가 안 보일 때

DNS가 Clash 밖으로 새거나 TUN/시스템 프록시가 터미널에 적용되지 않은 경우입니다. 설정 재적용 후 같은 셸에서 다시 시도하세요.

대용량 병만 끊길 때

객체 스토리지 호스트와 레지스트리 호스트를 모두 같은 그룹에 넣었는지 확인하세요. CDN 엣지가 지역별로 달라지면 노드 교체만으로는 한계가 있습니다.

8. 자주 묻는 질문

아래는 본문을 읽은 뒤 남는 짧은 확인용입니다. 구조화된 FAQ 블록은 검색 결과 보조에도 도움이 될 수 있습니다.

brew update는 되는데 brew install에서만 타임아웃이 날 수 있나요?

흔합니다. 메타·API 축과 병·릴리스 자산 축이 서로 다른 호스트로 나뉘기 때문입니다. 한쪽만 올바른 출구로 가면 비대칭 증상이 납니다.

GHCR 규칙만 넣었는데 왜 아직 느릴까요?

인증·API·리다이렉트·객체 저장소가 추가로 열립니다. 로그에 찍힌 전체 호스트를 같은 정책 그룹으로 묶는 편이 안전합니다.

소스 빌드로 바꾸면 타임아웃이 사라지나요?

brew install --build-from-source는 받는 아티팩트 패턴을 바꿀 수 있지만 빌드 시간과 의존성 컴파일 비용이 커지고, 회선·DNS 문제를 근본적으로 없애지는 못하는 경우가 많습니다. Clash 분기와 이름 해석을 먼저 안정화하세요.

정리하면, Homebrewbrew update·brew install 타임아웃은 단일 스위치 문제가 아니라 formula 메타, bottle·ghcr.io(GHCR), GitHub 릴리스 자산·API가 동시에 같은 출구를 타야 풀리는 경우가 많습니다. Clash·mihomo는 호스트 묶음을 정책 그룹으로 고정하고 로그로 검증하기 쉬워 macOS 개발자 워크플로에 잘 맞습니다. 반면 앱 안 토글 위주의 상용 VPN은 호스트별·프로세스별 출구를 세밀히 맞추거나 장애 시 원인 로그를 남기기 어렵고, 긴 병 다운로드 중 노드를 바꾸는 실험도 제한적인 경우가 많습니다. YAML과 대시보드를 직접 다룰 수 있다는 점에서 Clash 계열이 이런 brew·CI 네트워크 디버깅에 유리합니다.

→ Clash를 무료로 내려받아 mixed-port와 프로필을 정리한 뒤, 위 순서대로 GitHub·Homebrew 축과 DNS를 맞춰 보세요.

주제 관련도가 높은 읽을거리 — 같은 카테고리의 Clash 실전 가이드.