이 글이 필요한 개발 환경의 증상
코드를 작성하는 동안 브라우저는 정상적으로 열리는데 GitHub clone·push만 멈추거나, npm·pnpm·pip 패키지가 간헐적으로 다운로드되지 않는다면 애플리케이션 자체보다 실행 경로를 먼저 확인해야 합니다. 개발 도구는 브라우저처럼 운영체제의 시스템 프록시를 항상 따르지 않습니다. 셸에서 실행한 Git, Node.js 프로세스, Python 패키지 관리자, Docker 데몬은 서로 다른 네트워크 설정을 읽을 수 있기 때문에 같은 컴퓨터에서도 결과가 달라집니다.
이 글에서는 Clash Verge Rev 또는 Mihomo 기반 클라이언트를 기준으로 개발용 프록시를 정리합니다. 핵심은 모든 트래픽을 무조건 프록시로 보내는 것이 아니라, Clash TUN 모드로 프록시 설정을 인식하지 못하는 프로세스를 보완하고, 동시에 터미널에는 HTTP_PROXY·HTTPS_PROXY·NO_PROXY를 명시하는 것입니다. 이렇게 하면 GitHub, 패키지 저장소, 컨테이너 레지스트리, AI 코딩 도구를 같은 기준으로 진단할 수 있습니다.
다만 조직 네트워크의 보안 정책이나 저장소 접근 규칙을 우회하는 용도로 사용해서는 안 됩니다. 회사의 인증 프록시, 사내 Git 서버, 내부 패키지 레지스트리는 일반적인 외부 서비스와 다른 예외 처리가 필요할 수 있으므로, 네트워크 담당자가 제공한 주소와 인증 방식을 우선 적용하세요.
개발 도구마다 프록시를 읽는 방식이 다른 이유
웹 브라우저에서 사이트가 열린다는 사실만으로 Git과 Docker의 연결까지 정상이라고 판단하기는 어렵습니다. 브라우저는 시스템 프록시나 확장 프로그램의 설정을 사용하지만, Git은 자체 설정과 환경 변수를 함께 확인합니다. Node.js 기반 도구는 실행된 셸의 환경 변수를 물려받고, Docker CLI는 다시 별도의 Docker 데몬에 명령을 전달합니다. 데몬이 호스트와 다른 환경에서 실행되면 CLI에 프록시를 넣어도 이미지 다운로드는 실패할 수 있습니다.
| 대상 | 주로 확인할 설정 | 대표적인 실패 증상 |
|---|---|---|
| Git | 환경 변수, git config, SSH 또는 HTTPS 방식 |
clone timeout, TLS 오류, push 중 연결 종료 |
| npm·pnpm | HTTP_PROXY, 레지스트리 주소, 인증서 |
패키지 메타데이터 조회 지연, ECONNRESET |
| Docker | Docker 데몬의 프록시, 레지스트리별 예외 | 이미지 pull timeout, manifest 조회 실패 |
| AI 코딩 도구 | 셸 환경, IDE 환경, HTTPS 스트리밍 연결 | 로그인 실패, 응답 스트림 중단, API timeout |
따라서 문제를 해결할 때는 먼저 실패한 명령을 하나로 고정하고, 그 명령이 어떤 프로세스와 호스트를 거치는지 나눠서 살펴보는 것이 좋습니다. 예를 들어 GitHub HTTPS 연결이 실패하면 DNS 확인, TCP 연결, TLS 협상, HTTP 응답을 순서대로 확인해야 합니다. 처음부터 여러 규칙을 한꺼번에 바꾸면 어느 설정이 효과가 있었는지 알기 어려워집니다.
github.com이 아니라 objects.githubusercontent.com이나 패키지 CDN에서 멈추는 경우처럼, 처음 보이는 도메인과 실제 실패 도메인이 다를 수 있습니다.
Clash TUN 모드로 기본 경로 만들기
TUN 모드는 가상 네트워크 인터페이스를 만들어 운영체제의 IP 트래픽을 Clash 코어가 처리하도록 돕습니다. 애플리케이션이 프록시 환경 변수를 읽지 않더라도 비교적 넓은 범위의 연결을 Clash 규칙에 태울 수 있다는 점이 장점입니다. Git HTTPS, Docker의 레지스트리 연결, IDE 확장 기능처럼 시스템 프록시 상속이 불완전한 프로그램을 점검할 때 특히 유용합니다.
Clash Verge Rev에서 먼저 활성 프로필을 확인하고, 코어가 정상적으로 실행되는지 살펴보세요. 그다음 설정 화면에서 TUN을 켜고 운영체제가 요청하는 관리자 권한을 허용합니다. 메뉴 이름은 클라이언트와 버전에 따라 TUN Mode, 서비스 모드, 시스템 확장처럼 다르게 표시될 수 있습니다. 권한을 허용했는데도 인터페이스가 만들어지지 않는다면 다른 VPN 프로그램, 보안 소프트웨어, 이전 Clash 서비스가 가상 어댑터를 점유하고 있는지 확인해야 합니다.
TUN을 켠 뒤에는 곧바로 글로벌 모드로 고정하기보다 규칙 모드에서 시작하는 편이 안전합니다. 일반 웹사이트와 국내 패키지 미러까지 모두 같은 노드로 보내면 속도가 떨어지고, 인증서 검사나 사내 서비스 접근에 문제가 생길 수 있습니다. 개발용 정책은 외부 개발 서비스만 프록시 그룹으로 보내고, 로컬 주소와 내부 네트워크는 직접 연결하는 구조가 관리하기 쉽습니다.
특히 127.0.0.1, localhost, 사내 도메인, Docker 브리지 주소, 개발 서버의 로컬 포트는 예외 목록에 포함하는 것이 좋습니다. NO_PROXY에 모든 사설 대역을 무심코 넣으면 내부 서비스는 편해지지만, 회사 환경에서 의도하지 않은 우회 경로가 생길 수 있으므로 실제 사용하는 범위만 적어야 합니다.
DNS와 MTU까지 함께 확인하기
TUN을 켰는데도 연결이 불안정하다면 프록시 노드보다 DNS 처리 방식을 먼저 점검하세요. 도메인 질의는 로컬 DNS로 보내고 실제 HTTPS만 프록시로 보내는 구성에서, 특정 레지스트리 주소가 잘못 해석되거나 지역별 CDN으로 연결될 수 있습니다. Clash의 DNS 모드와 운영체제의 DNS 캐시가 충돌하면 첫 요청만 오래 걸리고 재시도 후 성공하는 패턴이 나타나기도 합니다.
반대로 모든 DNS 요청을 원격으로 보냈을 때 내부 도메인이 해석되지 않을 수도 있습니다. 외부 서비스와 사내 서비스의 이름 해석 경로를 구분하고, 변경 후에는 캐시를 비운 다음 새 셸이나 새 IDE 세션에서 다시 테스트하세요. Docker를 사용한다면 컨테이너 내부의 /etc/resolv.conf가 호스트와 같은 결과를 내는지도 확인해야 합니다.
대용량 Git fetch, Docker 레이어 다운로드, AI 응답 스트리밍에서만 끊긴다면 MTU 또는 경로의 패킷 손실을 의심할 수 있습니다. 이 경우 무작정 MTU 값을 낮추기보다 짧은 요청과 긴 요청을 나누어 비교하고, Clash 로그의 재연결 횟수와 노드별 지연을 함께 기록하세요. 안정적인 값은 운영체제·네트워크·터널 방식에 따라 달라지므로 다른 사용자의 숫자를 그대로 복사하는 것은 권장하지 않습니다.
터미널과 IDE의 프록시 환경 변수 정렬
TUN은 넓은 범위의 트래픽을 보완하지만, 개발 도구에 명시적인 프록시를 넣으면 문제의 경계를 더 분명히 할 수 있습니다. Clash의 mixed-port가 HTTP 프록시 요청을 받을 수 있는지 확인한 뒤, 현재 셸에서 다음과 같이 환경 변수를 설정합니다.
export HTTP_PROXY=http://127.0.0.1:<mixed-port>
export HTTPS_PROXY=http://127.0.0.1:<mixed-port>
export ALL_PROXY=http://127.0.0.1:<mixed-port>
export NO_PROXY=localhost,127.0.0.1,::1
여기서 <mixed-port>는 실제 클라이언트에 표시된 포트로 바꿔야 합니다. SOCKS 포트만 열려 있다면 HTTP 프록시 URL을 그대로 넣을 수 없으므로 해당 런타임이 지원하는 SOCKS 형식과 인증 방식을 확인하세요. 같은 이름의 변수라도 대문자만 읽는 프로그램과 소문자만 우선하는 프로그램이 있어, 호환성을 위해 필요한 경우 두 형태를 함께 정의할 수 있습니다.
환경 변수를 셸 프로필에 영구 저장할 때는 모든 터미널에 적용하는 것이 정말 필요한지 먼저 생각해야 합니다. 사내 Git이나 내부 레지스트리까지 외부 노드로 보내지 않으려면 프로젝트별 실행 스크립트, direnv, IDE의 터미널 환경 설정처럼 범위를 제한하는 방식이 더 안전합니다. 프록시 주소에 토큰이나 비밀번호를 직접 넣으면 셸 히스토리와 프로세스 목록에 남을 수 있으므로, 인증이 필요한 프록시는 별도의 자격 증명 저장 방식을 사용하세요.
VS Code, JetBrains 계열 IDE, 터미널 멀티플렉서에서 새 환경 변수가 보이지 않는다면 IDE를 완전히 종료한 뒤 다시 실행합니다. 이미 실행 중인 GUI 프로세스는 나중에 셸에서 입력한 export를 자동으로 받지 않습니다. 다음 명령으로 현재 프로세스가 실제 값을 읽는지 확인하되, 공유 화면이나 로그에 프록시 인증 정보가 노출되지 않도록 주의하세요.
env | grep -i proxy
git config --global --get http.proxy
npm config get registry
Git·npm·Docker를 서비스별로 연결하기
GitHub HTTPS와 SSH 구분
GitHub를 HTTPS URL로 사용하는 경우 Git은 대체로 HTTPS_PROXY를 활용할 수 있습니다. 먼저 저장소 주소가 https://github.com/...인지 확인하고, 연결 로그에서 GitHub뿐 아니라 릴리스 파일과 LFS 객체가 내려오는 호스트도 살펴보세요. 전역 Git 프록시를 설정하면 명령마다 환경 변수를 넣지 않아도 되지만, 사내 저장소까지 같은 프록시를 타지 않도록 호스트별 설정이나 NO_PROXY를 함께 설계해야 합니다.
SSH 방식은 HTTP 프록시와 동작 원리가 다릅니다. [email protected]:... 주소를 사용하면서 단순히 HTTPS_PROXY를 추가해도 SSH 연결이 자동으로 프록시를 통과하지는 않습니다. 조직 정책상 SSH를 사용해야 한다면 허용된 bastion, SSH 프록시 명령, 또는 HTTPS 방식 전환 여부를 문서에 맞춰 결정하세요. 연결 방식을 모른 채 Git 설정을 여러 번 바꾸는 것보다 URL과 포트부터 확인하는 편이 빠릅니다.
npm과 pnpm 레지스트리 확인
패키지 관리자는 기본 레지스트리와 lockfile에 기록된 tarball 주소가 다를 수 있습니다. npm install이 메타데이터는 읽지만 실제 압축 파일에서 실패한다면, Clash 로그에서 요청된 CDN 호스트를 찾아야 합니다. 회사에서 사설 레지스트리를 사용한다면 해당 도메인은 직접 연결하거나 조직이 지정한 프록시로 분기하고, 공개 패키지만 외부 프록시 그룹으로 보내는 식으로 정책을 나누세요.
인증서 오류가 발생했을 때 검증을 끄는 방법부터 찾는 것은 위험합니다. 중간 인증서가 필요한 기업 프록시라면 회사가 배포한 CA를 올바른 신뢰 저장소에 등록하고, 만료된 인증서나 잘못된 시스템 시간을 먼저 수정해야 합니다. strict-ssl=false 같은 임시 설정은 원인 확인 후 되돌리는 것을 잊지 마세요.
Docker CLI와 데몬을 따로 점검하기
Docker에서 가장 많이 놓치는 부분은 CLI와 데몬이 같은 네트워크 프로세스가 아니라는 점입니다. 로컬 Docker Desktop을 사용하더라도 이미지 pull은 백그라운드 데몬 또는 VM 안에서 실행될 수 있습니다. 호스트 셸에 HTTPS_PROXY를 설정했는데도 docker pull이 실패한다면 Docker Desktop의 프록시 설정, Docker Engine 환경, 조직의 레지스트리 정책을 별도로 확인해야 합니다.
Dockerfile의 RUN npm install과 베이스 이미지 pull도 서로 다른 단계에서 발생합니다. 이미지 pull은 데몬의 레지스트리 연결을 사용하고, 빌드 중 실행되는 명령은 빌더 컨테이너의 환경을 사용할 수 있습니다. 따라서 한 단계가 성공했다고 전체 빌드의 프록시가 완성된 것은 아닙니다. 비밀 토큰을 Dockerfile의 ENV나 이미지 레이어에 넣지 말고, BuildKit의 비밀 전달이나 CI 플랫폼의 보호된 변수 기능을 활용하세요.
규칙 우선순위와 연결 검증 순서
규칙을 추가할 때는 넓은 도메인 키워드보다 구체적인 도메인 규칙을 위에 배치하는 것이 좋습니다. 예를 들어 특정 패키지 레지스트리를 프록시로 보내려는 규칙보다 앞에서 전체 국가 도메인을 직접 연결하도록 정의하면, 기대한 프록시 그룹에 도달하지 못할 수 있습니다. 같은 호스트가 DIRECT, REJECT, 프록시 그룹 중 어디에 매칭됐는지 연결 로그에서 확인하고, 규칙 파일을 바꾼 뒤에는 반드시 프로필을 다시 적용하세요.
검증은 작은 단계로 나누면 원인을 찾기 쉽습니다. 첫째, DNS가 예상한 주소를 반환하는지 확인합니다. 둘째, 일반 HTTPS 요청이 mixed-port 또는 TUN을 통해 나가는지 봅니다. 셋째, Git clone이나 패키지 설치처럼 실제 작업과 가까운 요청을 수행합니다. 마지막으로 Docker 이미지 pull과 AI 코딩 도구의 스트리밍 응답을 테스트합니다. 짧은 curl 요청만 성공했다고 장시간 연결까지 안정적이라고 결론 내리면 안 됩니다.
- Clash 프로필이 활성 상태이고 노드 그룹에 실제 선택 가능한 노드가 있는지 확인합니다.
- TUN 인터페이스와 mixed-port가 실행 중인지 확인하고 포트 번호를 기록합니다.
- Clash 로그에서 실패 호스트, 매칭 규칙, 선택된 프록시 그룹을 확인합니다.
- 현재 셸과 IDE가 같은 프록시 환경 변수를 받는지 확인합니다.
- Docker 데몬과 컨테이너 빌드 단계의 프록시를 분리해 각각 테스트합니다.
- 설정 변경 후 새 터미널과 새 컨테이너에서 동일한 명령을 반복합니다.
테스트 결과는 성공 여부만 기록하지 말고 시간, 네트워크 종류, 선택된 노드, 응답 지연, 재시도 횟수까지 남기는 것이 좋습니다. Wi-Fi에서는 성공하지만 모바일 핫스팟에서 실패하거나, 낮에는 되지만 저녁에만 GitHub가 느려지는 경우처럼 환경별 차이가 원인을 보여줄 수 있습니다. 여러 개발자가 같은 문제를 겪는 팀이라면 개인 키나 저장소 비밀을 제외하고 호스트·규칙·오류 코드만 공유하면 재현과 지원이 훨씬 쉬워집니다.
재부팅과 구독 갱신 후에도 유지하는 방법
개발 환경의 프록시는 한 번 켜고 끝나는 설정이 아닙니다. Clash 구독이 갱신되면 프록시 그룹 이름, 규칙 제공자, DNS 동작이 바뀔 수 있고, 운영체제 업데이트 후에는 TUN 권한이나 가상 인터페이스가 초기화될 수 있습니다. 문제가 다시 발생했을 때는 설정을 처음부터 지우기보다 마지막으로 정상 작동했던 프로필과 현재 프로필의 차이를 비교하세요.
프로젝트 문서에는 실제 비밀값 대신 필요한 포트, 예외 도메인, 테스트 명령, 예상되는 로그 상태를 기록할 수 있습니다. 예를 들어 “외부 GitHub HTTPS와 공개 npm 레지스트리는 개발 프록시 그룹, 사내 Git과 localhost는 DIRECT, Docker 데몬은 별도 프록시 적용”처럼 정책을 글로 남기면 새 팀원이 같은 시행착오를 반복하지 않습니다. 또한 CI 러너는 개발자의 노트북 Clash를 볼 수 없으므로, CI에서는 조직이 제공하는 고정 프록시나 허용된 네트워크 경로를 사용해야 합니다.
단순한 브라우저용 프록시 확장 프로그램은 빠르게 켜고 끌 수 있지만 Git, Docker 데몬, IDE 백그라운드 프로세스까지 일관되게 다루기 어렵고, 도구마다 별도 설정을 반복해야 하는 경우가 많습니다. 반면 Clash는 TUN으로 비표준 클라이언트의 경로를 보완하면서도 mixed-port와 명시적 환경 변수, 도메인별 규칙 로그를 함께 제공해 문제를 단계적으로 좁힐 수 있습니다. 개발 환경에서 저장소·패키지·컨테이너·AI 도구의 연결을 한 기준으로 관리하고 싶다면, 자신의 운영체제와 조직 정책에 맞는 Clash 클라이언트를 선택해 설정을 시작해 보세요.