왜 external-controller 기반 자동 전환이 필요한가
Clash의 프록시 그룹에서 노드를 직접 클릭해 바꾸는 방식은 짧은 테스트에는 충분하지만, 장시간 스트리밍·원격 개발·화상 회의·CI 작업처럼 연결이 계속 유지되는 환경에서는 한계가 분명합니다. 선택한 노드의 지연 시간이 갑자기 높아지거나 패킷 손실이 늘어도 사용자가 화면을 보고 있지 않으면 그대로 장애가 이어집니다. 특히 노트북을 덮었다가 다시 열거나 Wi-Fi와 유선 네트워크를 오갈 때에는 기존 노드가 더 이상 좋은 경로가 아닌데도 선택 상태가 유지되는 일이 흔합니다.
external-controller는 실행 중인 Clash 또는 Mihomo 코어의 상태를 HTTP API로 조회하고 일부 설정을 바꿀 수 있게 하는 관리 인터페이스입니다. 이를 이용하면 현재 선택된 정책 그룹, 그룹에 포함된 프록시, 최근 지연 측정값, 연결 상태를 스크립트에서 읽을 수 있습니다. 단순히 “가장 빠른 노드 하나를 고르는” 작업을 넘어, 지연·연속 실패·응답 시간·업무 시간대 같은 조건을 조합해 장애 조치 정책을 만들 수 있다는 점이 핵심입니다.
다만 자동 전환은 무조건 빠른 노드로 갈아타는 기능이 아닙니다. 노드가 바뀌면 기존 TCP 연결이나 스트리밍 세션이 끊길 수 있고, 너무 짧은 주기로 검사를 반복하면 정상 노드와 불안정 노드 사이를 오가는 플래핑이 발생합니다. 따라서 먼저 관찰하고, 일정 횟수 이상 실패했을 때만 전환하며, 전환 뒤에는 일정 시간 동안 다시 판단하지 않는 히스테리시스를 설계해야 합니다. 이 글은 Clash Verge Rev, Mihomo 계열 코어처럼 API와 프록시 그룹을 제공하는 환경을 기준으로 설명합니다.
external-controller와 API 인증을 안전하게 준비하기
먼저 현재 사용 중인 프로필이 실제로 어떤 코어에 의해 실행되는지 확인합니다. Clash 계열 클라이언트는 화면 이름은 비슷해도 코어 버전과 지원하는 API가 다를 수 있습니다. 설정 파일에서 external-controller가 어느 주소와 포트를 사용하는지 확인하고, API 주소를 문서에 기록할 때는 실제 포트와 일치하는지 점검합니다. 일반적으로 로컬 테스트에는 127.0.0.1:9090 같은 바인딩을 사용하며, 모든 인터페이스를 의미하는 주소로 열어 두는 것은 피하는 편이 좋습니다.
API 비밀번호는 설정 파일의 secret 값으로 보호합니다. 일부 클라이언트는 GUI에서 컨트롤러 주소와 비밀번호를 별도로 입력하게 하므로, YAML의 값과 UI에 저장된 값이 다르면 브라우저 대시보드는 열려도 스크립트 요청은 401 Unauthorized를 반환할 수 있습니다. 비밀번호를 셸 명령의 인수로 직접 작성하면 셸 기록이나 프로세스 목록에 남을 수 있으므로, 운영 환경에서는 환경 변수나 권한이 제한된 별도 파일을 사용하는 것이 안전합니다.
연결 확인은 가장 작은 API 요청부터 시작합니다. 현재 프로필의 상태가 반환되는지, 응답이 JSON 형식인지, 인증 헤더가 필요한지 순서대로 봅니다. 예를 들어 다음 요청에서 응답이 오지 않는다면 자동 전환 로직을 만들기 전에 코어 실행 상태, 포트 충돌, 방화벽, 인증값을 먼저 해결해야 합니다.
curl -H "Authorization: Bearer YOUR_SECRET" \
http://127.0.0.1:9090/version
curl -H "Authorization: Bearer YOUR_SECRET" \
http://127.0.0.1:9090/proxies
외부 장치에서 호출해야 하는 특별한 이유가 없다면 스크립트도 같은 컴퓨터에서 실행하세요. 사내 서버나 홈 서버에서 원격으로 관리해야 한다면 방화벽의 허용 출발지, TLS를 제공하는 역방향 프록시, 강한 인증 비밀번호를 함께 설계해야 합니다. API 포트를 공유기 포트 포워딩으로 노출하는 방식은 짧은 실험이라도 권장하지 않습니다. controller API에는 노드 선택뿐 아니라 연결 종료나 설정 변경과 관련된 기능이 포함될 수 있기 때문입니다.
자동 판단에 사용할 API 엔드포인트와 지표
자동 전환의 품질은 어떤 데이터를 읽느냐에 따라 달라집니다. /proxies 응답에서는 프록시 그룹과 개별 노드의 현재 상태를 확인할 수 있고, 그룹 객체에서 현재 선택된 이름을 읽을 수 있습니다. 특정 노드의 지연을 측정할 때에는 Clash 코어가 제공하는 지연 테스트 API를 사용합니다. 클라이언트와 코어 버전에 따라 경로의 쿼리 이름이나 지원 방식이 다를 수 있으므로, 고정된 예제를 그대로 믿기보다 현재 코어의 API 문서와 실제 응답을 함께 확인해야 합니다.
측정 대상 URL도 중요합니다. 포털 페이지나 이미지가 큰 URL을 검사하면 CDN 캐시와 콘텐츠 크기가 결과를 흔들 수 있습니다. 반대로 너무 작은 응답만 검사하면 DNS는 빠르지만 실제 스트리밍이나 API 통신은 느린 노드를 좋은 것으로 판단할 수 있습니다. 업무 목적에 맞춰 짧고 안정적인 HTTPS 응답 URL을 하나 정하고, 동일한 URL·동일한 timeout·동일한 측정 간격을 모든 후보에 적용해야 비교가 공정합니다.
| 지표 | 사용 목적 | 주의할 점 |
|---|---|---|
| HTTP 지연 | 후보 노드의 기본 응답성을 비교 | 측정 URL과 지역에 따라 결과가 달라짐 |
| 연속 실패 횟수 | 일시적 손실과 실제 장애를 구분 | 한 번의 timeout만으로 전환하지 않기 |
| 최근 전환 시각 | 짧은 시간의 반복 전환을 차단 | 쿨다운 시간을 별도로 저장해야 함 |
| 현재 그룹 선택값 | 스크립트가 바꾼 상태를 확인하고 중복 요청 방지 | 노드 이름의 공백과 대소문자를 보존 |
지연값 하나만 보고 노드를 교체하면 오판이 많습니다. 예를 들어 A 노드가 80ms, B 노드가 110ms로 측정되어도 A에서 패킷 손실이 반복되면 실제 사용성은 B가 더 나을 수 있습니다. 반대로 B가 10ms 빠르다는 이유로 매번 전환하면 장거리 연결이 재설정되어 체감 품질이 나빠질 수 있습니다. 실전에서는 “최저 지연”보다 허용 지연 안에서 실패율이 낮고 오래 안정적인 노드를 우선하는 점수 모델이 적합합니다.
실패 횟수·쿨다운·우선순위를 포함한 전환 로직
자동 장애 조치 스크립트는 다음 순서로 구성하면 관리하기 쉽습니다. 첫째, API에서 대상 그룹의 현재 선택값과 후보 목록을 읽습니다. 둘째, 후보별 지연을 같은 조건으로 측정합니다. 셋째, timeout 또는 비정상 상태를 실패로 기록하되, 한 번의 실패만으로 즉시 교체하지 않습니다. 넷째, 현재 노드가 연속해서 정해진 횟수만큼 실패했거나 임계 지연을 일정 시간 초과했을 때 전환 후보를 고릅니다. 마지막으로 API에 새 노드 이름을 보내고, 실제 그룹의 선택값이 바뀌었는지 다시 조회합니다.
- 대상 그룹 고정: 자동화할 그룹을
AUTO_PROXY처럼 별도 이름으로 만들고, 일반 수동 선택 그룹과 섞지 않습니다. - 후보 필터링: 만료된 노드, 업무상 사용할 수 없는 지역, 내부 테스트 전용 노드는 목록에서 제외합니다.
- 상태 누적: 노드별 성공·실패 횟수와 마지막 측정 시각을 메모리나 작은 상태 파일에 기록합니다.
- 전환 조건 적용: 연속 실패 3회, 지연 2,000ms 초과, 또는 측정 API 오류처럼 명확한 조건을 사용합니다.
- 쿨다운 실행: 전환 후 60초 또는 120초 동안은 새 측정 결과가 나빠도 다시 바꾸지 않습니다.
- 전환 검증: API 응답의 성공 여부만 믿지 말고 그룹의 현재 선택값과 실제 연결 로그를 확인합니다.
후보 선택은 고정 우선순위와 점수 방식을 혼합할 수 있습니다. 예를 들어 같은 지역의 후보를 우선하고, 그 안에서 최근 성공률이 높은 노드를 선택합니다. 모든 후보가 실패하면 원래 노드로 무작정 돌아가기보다 수동 선택 그룹이나 DIRECT가 정책상 허용되는지 확인해야 합니다. 보안 정책상 직접 연결이 금지된 환경이라면 실패 상태를 알림으로 보내고, 잘못된 우회 경로를 자동으로 만들지 않는 것이 안전합니다.
스크립트가 여러 개 실행되는 것도 막아야 합니다. cron, 작업 스케줄러, 컨테이너 재시작 훅이 같은 파일을 동시에 호출하면 한 프로세스는 A로, 다른 프로세스는 B로 바꾸는 경쟁 상태가 생깁니다. PID 파일, 파일 잠금, 단일 서비스 실행 중 하나를 적용하고, API 호출에는 짧은 연결 timeout과 재시도 횟수 제한을 둡니다. 재시도도 무한 반복하지 말고 실패 원인과 시각을 로그에 남겨야 다음 장애 분석이 가능합니다.
로그·알림·롤백으로 운영 흐름 완성하기
자동 전환을 배포한 뒤에는 “노드가 바뀌었다”는 사실보다 “왜 바뀌었는가”를 남기는 것이 중요합니다. 최소한 측정 시각, 대상 그룹, 이전 노드, 새 노드, 측정 URL, 지연값, 실패 횟수, API 응답 코드, 전환 사유를 기록하세요. 노드 이름에 국가나 통신사 표시가 포함되어 있어도 로그가 지나치게 길어지면 검색이 어려우므로 내부 식별자와 표시 이름을 함께 관리하면 좋습니다.
모니터링은 API 상태와 실제 애플리케이션 상태를 나누어 보아야 합니다. API가 200 OK를 반환해도 선택한 노드의 TLS 연결이 계속 실패할 수 있고, 반대로 지연 테스트 URL이 일시적으로 느려도 사용 중인 장시간 스트림은 정상일 수 있습니다. 따라서 전환 직후 Clash 연결 로그에서 새 노드로 요청이 나가는지, 대상 도메인이 의도한 정책 그룹에 매칭되는지, 사용자 애플리케이션의 오류가 줄었는지를 함께 확인합니다.
알림은 모든 측정 결과가 아니라 의미 있는 이벤트만 보내야 합니다. 예를 들어 3회 연속 실패, 5분 안에 두 번 이상 전환, 전체 후보 실패, API 인증 실패, controller 포트 연결 불가를 알림 대상으로 두면 소음이 줄어듭니다. 알림 메시지에는 secret이나 구독 URL을 포함하지 말고, 노드 전체 이름이 민감한 정보라면 일부를 마스킹합니다. 운영자가 알림을 보고 수동으로 확인할 수 있도록 마지막 성공 시각과 현재 선택값도 함께 표시하면 좋습니다.
변경 전에는 현재 프로필과 그룹 설정을 별도 파일로 백업하고, 자동화가 기대와 다르게 동작하면 스크립트를 먼저 중지한 뒤 수동 선택으로 되돌립니다. 구독 갱신 때 그룹 이름이나 노드 이름이 바뀌면 API 요청은 성공한 것처럼 보여도 원하는 후보를 선택하지 못할 수 있으므로, 갱신 후에는 노드 목록과 그룹 멤버를 다시 검증해야 합니다. 새 코어로 업데이트할 때도 테스트 프로필에서 API 응답 구조와 지연 측정 경로가 그대로인지 확인한 뒤 운영 프로필에 반영하세요.
일부 단순 GUI는 노드 선택과 기본 url-test만 제공하고, 실패 횟수·쿨다운·알림·롤백을 한 화면에서 세밀하게 조정하기 어렵습니다. 반대로 직접 만든 셸 스크립트는 자유롭지만 인증 관리, 동시 실행 방지, 코어별 API 차이를 사용자가 모두 책임져야 합니다. Clash V.CORE는 외부 컨트롤러와 정책 그룹을 중심으로 상태 조회, 후보 전환, 로그 확인을 한 흐름으로 구성하기 쉬워 이런 운영 부담을 줄일 수 있으므로, 자동 장애 조치를 실제로 적용하려면 다운로드 페이지에서 환경에 맞는 Clash V.CORE 빌드를 확인해 시작하는 편이 좋습니다.