증상을 이렇게 정의해 보세요
사파리나 크롬은 원하는 노드를 잘 타는데, 같은 맥에서 연 터미널만 brew·git clone·curl이 여전히 직통으로 나간다면 흔히 「Clash가 안 켜졌다」기보다 터미널 프로세스가 프록시 정보를 전혀 모르는 상태인 경우가 많습니다. macOS의 시스템 HTTP/SOCKS 프록시 설정은 많은 GUI 앱에 전달되지만, CLI 도구는 OS가 자동으로 모든 환경 변수를 채워 주지 않습니다. 그래서 클라이언트에서 「시스템 프록시 따르기」를 켰다 해도, 이미 떠 있는 셸 세션에는 아무 변화가 없을 수 있습니다.
또 다른 패턴은 값은 있는데 포트·스킴이 어긋난 경우입니다. Clash 계열이 7890에서 HTTP를 열고 있는데 환경 변수는 SOCKS 전용 포트를 가리키거나, 반대로 http:// 프리픽스 없이 호스트만 적어 둔 경우입니다. 마지막으로 no_proxy(또는 NO_PROXY)에 넓은 패턴을 넣어 두어 사내망·로컬호스트가 예외 처리되는 경우도 자주 있습니다. 아래 순서대로 좁혀 가면 원인을 메모해 두고 같은 증상을 빨리 닫을 수 있습니다.
1단계: 지금 이 터미널이 읽는 셸과 파일 순서
zsh를 쓰는 경우, 로그인 셸과 비로그인 인터랙티브 셸이 읽는 파일이 다릅니다. 터미널 앱이 새 창을 열 때 로그인 셸로 뜨는지 여부에 따라 ~/.zprofile과 ~/.zshrc 중 어디까지 실행되는지가 갈립니다. 그래서 「에디터로 .zshrc만 고쳤는데 반영이 안 된다」는 일이 생깁니다. 우선 아래를 실행해 현재 세션의 셸과 로그인 여부를 확인하세요.
echo $SHELL로 기본 셸을 보고, ps -p $$ -o comm=로 실제로 돌고 있는 바이너리 이름을 확인합니다. 로그인 셸인지는 echo $0 앞에 하이픈이 붙는지(예: -zsh)로도 감을 잡을 수 있습니다. 설정을 넣을 위치는 팀 합의가 없다면 실무적으로 GUI 터미널에서 항상 읽히는 쪽에 두는 편이 덜 헷갈립니다. 예를 들어 로그인 셸이면 ~/.zprofile 또는 ~/.zlogin, 인터랙티브 셸이면 ~/.zshrc를 우선 점검합니다.
한 가지 더, IDE 안의 통합 터미널은 부모 프로세스가 IDE라서 별도의 환경 스냅샷을 갖습니다. 맥 기본 터미널에서는 잘 되는데 VS Code 안에서만 안 된다면, IDE를 완전히 종료했다가 다시 열거나 해당 세션을 새로 띄운 뒤 변수를 다시 확인하세요. CI나 스크립트로 돌리는 비인터랙티브 셸은 또 다른 경로를 타므로, 「수동 터미널에서만 재현되는지」를 먼저 적어 두면 이후 분석이 빨라집니다.
2단계: 프록시 관련 환경 변수를 표로 읽기
대부분의 CLI HTTP 클라이언트는 다음 변수들을 봅니다. 이름은 생태계마다 조금씩 다르지만, macOS에서 자주 쓰는 조합은 아래와 같습니다. 대문자와 소문자를 둘 다 설정해 두면 호환성이 좋습니다. 예를 들어 http_proxy와 HTTP_PROXY, https_proxy와 HTTPS_PROXY를 같은 값으로 맞춥니다.
HTTP 프록시 포트가 7890이라면 전형적으로 export http_proxy=http://127.0.0.1:7890 형태입니다. SOCKS5를 쓸 때는 export all_proxy=socks5://127.0.0.1:7891처럼 스킴을 명시해야 합니다. ALL_PROXY는 이름 그대로 「전체」에 대한 폴백으로 쓰이는 경우가 많아, HTTP 전용 도구와 섞이면 기대와 다른 경로를 탈 수 있으니 한 번에 다 넣기보다 단계적으로 켜며 관찰하는 것이 좋습니다.
env | grep -i proxy로 현재 세션에 실제로 무엇이 잡혀 있는지 출력해 보세요. 여기서 비어 있으면 brew나 curl이 프록시를 쓸 근거가 없습니다. 값이 있는데도 직통이면 no_proxy에 목적지 호스트나 상위 도메인이 들어가 있는지, 프록시 URL이 잘못되었는지(루프백이 아닌 LAN IP를 가리키는 등)를 의심합니다. 프록시 문자열에 공백이나 따옴표가 섞여 파싱이 깨진 사례도 있으니 복사·붙여넣기 후에도 한 줄인지 확인합니다.
3단계: Clash가 실제로 듣는 포트와 스킴 맞추기
Clash·Mihomo 계열 클라이언트는 프로필에 따라 mixed-port 하나로 HTTP와 SOCKS를 같이 받거나, port와 socks-port를 나눌 수 있습니다. 환경 변수의 http://는 HTTP 프록시 핸드셰이크를 기대하므로, 실제로는 SOCKS만 열려 있는 포트를 가리키면 실패하거나 이상 동작을 합니다. 클라이언트 UI나 설정 YAML에서 현재 프로필 기준 리스닝 포트를 확인한 뒤, 그에 맞춰 http_proxy와 all_proxy를 분리해 주는 것이 안전합니다.
일부 사용자는 시스템 프록시만 켜 두고 터미널 변수는 비워 둔 채 「왜 안 되지?」라고 느낍니다. 이 경우 해결책은 둘 중 하나입니다. 클라이언트가 제공하는 터미널용 환경 변수 복사 기능을 쓰거나, 위에서 설명한 대로 셸 설정 파일에 직접 export를 추가합니다. 반대로 TUN 모드를 켜 두었다면 IP 레벨에서 트래픽이 이미 가로채이므로 CLI 입장에서는 프록시 변수 없이도 기대한 경로로 나가는 경우가 있습니다. 다만 DNS·라우팅 이슈는 별도이므로 TUN 모드 가이드와 함께 보는 것이 좋습니다.
4단계: 앱별로 프록시를 따로 두는 경우
Git은 환경 변수만으로는 부족하고 git config --global http.proxy 같은 저장소 단위 설정이 우선할 때가 있습니다. 오래전에 넣어 둔 프록시가 남아 있으면 새 환경 변수와 충돌해 보이기 어려운 증상이 납니다. git config --global --get http.proxy로 확인하고, 필요 없으면 비웁니다. HTTPS 원격을 쓴다면 http.https://github.com.proxy 같은 URL별 프록시 항목도 함께 봅니다.
Homebrew는 내부적으로 curl 등을 사용하므로 일반적으로 위 HTTP(S) 프록시 환경 변수를 따릅니다. 그럼에도 특정 탭에서만 실패한다면 해당 세션에 변수가 없는지, 회사 프록시가 추가 인증을 요구하는지를 살펴봅니다. SSH는 기본적으로 HTTP CONNECT 프록시를 쓰지 않으므로, ssh user@host가 직통인 것이 곧 프록시 미적용이라고 단정하면 안 됩니다. 필요하면 ProxyCommand나 전용 래퍼를 쓰는 별도 패턴입니다.
컨테이너 도구나 언어별 패키지 매니저(npm, pip 등)는 각자 프록시 옵션이 있어, 「전역 환경 변수는 맞는데 특정 명령만 실패한다」는 보고가 나옵니다. 이때는 해당 도구의 설정 파일과 캐시를 우선 의심하세요.
5단계: no_proxy와 사내망 예외
회사 노트북에서는 NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,.internal처럼 넓은 예외를 넣어 두는 경우가 많습니다. 패턴 문법은 사용하는 라이브러리마다 조금씩 달라서, 「이 호스트는 예외일 줄 알았는데 실제로는 아니다」가 발생합니다. 증상이 특정 호스트에서만 재현된다면 no_proxy를 잠시 비우고 테스트해 보거나, 최소 패턴으로 줄여 가며 범인을 찾습니다.
로컬 개발 서버(localhost)는 예외로 두고 싶은 경우가 많지만, 원격 API까지 우회되면 디버깅이 꼬입니다. 팀 단위로 no_proxy 정책을 문서화해 두면 신입 온보딩 시간이 줄고, 보안 감사 질문에도 답하기 쉽습니다.
흔한 실수와 빠른 판별 팁
첫째, 프록시를 켠 뒤 이미 열려 있던 터미널 탭만 보고 판단하는 경우입니다. export는 자식 프로세스로만 전달되므로, 설정 파일을 고쳤다면 새 탭을 열거나 source ~/.zshrc로 현재 세션에 주입해야 합니다. 둘째, 127.0.0.1과 ::1을 혼동하는 경우입니다. 일부 스택은 IPv6를 먼저 시도하다가 이상한 경로로 빠질 수 있으니, Clash가 IPv4 루프백만 듣는지 확인합니다.
셋째, 여러 Clash 계열 클라이언트를 번갈아 쓰다가 포트가 바뀐 채 환경 변수만 옛값인 경우입니다. 업데이트 후 기본 mixed 포트가 바뀌었다면 문서에 적어 둔 스크립트를 같이 고쳐야 합니다. 넷째, 프록시 체인 중 한 홉이 MITM 인증서를 요구하는데 curl에 -k를 남발하는 대신 신뢰 저장소에 루트를 설치해야 하는 케이스입니다. 이는 보안과 직결되므로 회사 정책을 따르세요.
정리
macOS에서 「Clash는 켜져 있는데 터미널만 직통」은 대부분 셸 초기화 경로와 프록시 환경 변수, Clash 리스닝 포트·스킴 불일치, 앱별 별도 설정, no_proxy 예외 다섯 축으로 설명됩니다. 위 순서대로 좁히면 재현 조건을 짧은 메모로 남길 수 있고, 다음에 비슷한 이슈가 와도 같은 체크리스트로 빠르게 닫을 수 있습니다. GUI 프록시와 TUN, CLI 변수는 서로를 완전히 대체하지 않으므로 사용 패턴에 맞게 조합하는 것이 좋습니다.
브라우저 위주라면 시스템 프록시만으로도 충분한 경우가 많고, 개발용 터미널이 많다면 환경 변수 스니펫을 팀 저장소에 공유해 두면 온보딩 비용이 줄어듭니다. 규칙 품질과 DNS 설계는 여전히 중요하므로, 필요하면 문서 허브의 고급 설정 파트를 함께 참고하세요. 장기적으로는 Mihomo 기반 클라이언트 하나로 코어 업데이트와 포트 정책을 일원화해 두는 편이 운영 부담을 줄이는 경우가 많습니다.