Clash API로 노드 자동 전환하는 고급 설정과 장애 조치 가이드

빌드, AI 서비스, 원격 서버를 사용하는 중 프록시가 끊길 때마다 수동으로 노드를 바꾸는 방식은 안정적이지 않습니다. 이 글에서는 Clash API로 상태를 확인하고 지연 기준에 따라 전략 그룹을 변경하는 자동 장애 조치 구조와 운영 절차를 구현합니다.

API 자동 전환의 구조와 적용 범위

빌드 작업, AI 서비스, 원격 서버 접속처럼 연결이 오래 유지되거나 중단에 민감한 작업에서는 문제가 발생할 때마다 클라이언트 화면을 열어 노드를 직접 바꾸는 방식이 안정적이지 않습니다. 노드가 잠시 응답하지 않는 순간에도 요청이 계속 들어오고, 사용자가 자리를 비운 동안 장애가 발생할 수 있기 때문입니다. Clash의 외부 제어 API를 사용하면 현재 선택된 노드, 프록시 그룹, 지연 시간과 연결 상태를 프로그램으로 확인한 뒤 조건에 따라 다른 노드를 선택할 수 있습니다.

이 구조는 “가장 빠른 노드를 무조건 선택”하는 기능과는 다릅니다. 자동 장애 조치는 정해진 후보 목록을 순서대로 검사하고, 실제 업무에 사용할 수 있는 노드만 정책 그룹에 적용하는 운영 절차입니다. 예를 들어 5초 안에 테스트 URL에 응답하지 않거나, 연속 세 번 지연 시간이 기준을 초과하면 현재 노드를 장애 상태로 간주하고 다음 후보로 이동합니다. 반대로 한 번의 느린 응답만으로 전환하면 일시적인 네트워크 혼잡에도 선택 노드가 계속 바뀌는 플래핑이 발생하므로, 성공 횟수와 실패 횟수를 함께 관리해야 합니다.

자동 전환을 구성하려면 네 가지 요소가 필요합니다. 첫째, 외부 제어 API를 열어 둔 Clash 또는 mihomo 클라이언트입니다. 둘째, 전환 대상이 되는 select 정책 그룹입니다. 셋째, 후보 노드의 이름과 테스트 기준입니다. 넷째, 일정 간격으로 API를 호출할 별도의 스크립트나 작업 스케줄러입니다. API는 상태를 제공하고 선택을 변경할 뿐, 클라이언트 내부에서 임의의 프로그램을 실행하지는 않으므로 자동화 스크립트는 별도로 운영해야 합니다.

외부 제어 포트는 공개하지 마세요

external-controller: 0.0.0.0:9090처럼 모든 인터페이스에 API를 열면 같은 네트워크의 다른 장치가 프록시 설정을 바꿀 수 있습니다. 가능하면 127.0.0.1:9090으로 제한하고, 원격 서버에서 관리해야 할 때만 방화벽과 인증 토큰을 함께 설정하세요. API 주소와 secret은 구독 링크와 마찬가지로 인증 정보로 취급해야 합니다.

external-controller와 secret 설정

mihomo 계열 설정 파일에서는 보통 다음과 같이 외부 제어 주소와 인증 토큰을 지정합니다. 이미 사용 중인 설정 파일에 같은 키가 있다면 중복으로 추가하지 말고 기존 값을 수정해야 합니다.

external-controller: 127.0.0.1:9090
secret: "change-this-to-a-long-random-token"

일부 클라이언트는 설정 파일을 직접 편집하지 않고 환경설정 화면에서 컨트롤러 주소를 입력하도록 제공합니다. 이 경우 화면에 표시되는 주소가 실제 커널의 주소와 같은지 확인해야 합니다. Clash Verge, Clash Verge Rev, Mihomo Party 등은 UI가 서로 다르지만, 핵심은 커널 정보 페이지에서 mihomo가 실행 중인지와 컨트롤러 포트가 열려 있는지를 확인하는 것입니다. 원조 Clash 기반 클라이언트는 API 경로와 지원 기능이 다를 수 있으므로, 아래 예시는 mihomo 호환 API를 기준으로 사용하세요.

API가 정상적으로 열렸는지는 브라우저나 터미널에서 확인할 수 있습니다. secret을 설정한 경우 요청 헤더에 Authorization: Bearer 토큰을 넣어야 합니다.

curl -s \
  -H "Authorization: Bearer change-this-to-a-long-random-token" \
  http://127.0.0.1:9090/version

curl -s \
  -H "Authorization: Bearer change-this-to-a-long-random-token" \
  http://127.0.0.1:9090/proxies

/version이 JSON 형식의 버전을 반환하면 컨트롤러에 접근할 수 있는 상태입니다. /proxies는 현재 커널이 인식한 프록시와 정책 그룹을 반환합니다. 401 응답은 토큰이 없거나 틀렸다는 뜻이고, 연결 거부는 포트가 열리지 않았거나 클라이언트가 실행되지 않았다는 뜻입니다. 404가 나오면 API 경로가 해당 커널에서 지원되는지, 실제로 mihomo API에 요청하고 있는지 먼저 확인하세요.

정책 그룹 이름을 먼저 고정하세요

자동화 스크립트는 화면에 보이는 위치가 아니라 정책 그룹의 이름을 기준으로 동작합니다. 설정 파일에서 proxy-groups의 이름을 짧고 고정된 값으로 정하고, 예를 들어 AI-AUTOBUILD-FAILOVER처럼 다른 그룹과 겹치지 않게 작성하세요. 그룹 이름을 나중에 바꾸면 API 호출 대상도 함께 수정해야 합니다.

노드 조회와 지연 테스트 절차

자동 전환의 첫 단계는 후보 노드와 정책 그룹을 구분하는 일입니다. /proxies 응답의 proxies 객체에는 개별 노드, select, url-test, fallback 같은 그룹이 함께 들어 있습니다. 개별 노드는 일반적으로 all, history, now 정보를 갖고, 선택 그룹은 all 목록과 현재 선택값인 now를 갖습니다.

지연 시간은 노드 자체의 왕복 시간과 실제 서비스 접속 가능성을 구분해서 봐야 합니다. 노드의 테스트 URL에 빠르게 응답해도 AI 서비스나 원격 저장소가 차단되어 있으면 업무에는 사용할 수 없습니다. 따라서 일반적인 HTTPS 주소 하나만 검사하는 것보다 업무 목적에 맞는 테스트 URL을 두 단계로 나누는 편이 좋습니다. 첫 번째는 연결 경로를 확인하는 기본 URL이고, 두 번째는 실제 사용할 서비스의 가벼운 HTTPS 엔드포인트입니다. 로그인이나 대용량 다운로드를 테스트에 포함하면 불필요한 트래픽이 발생하므로 피하세요.

mihomo의 지연 측정 API는 프록시 이름을 URL 경로에 넣고, 쿼리 문자열로 테스트 주소와 제한 시간을 전달하는 방식으로 사용할 수 있습니다. 노드 이름에 공백이나 특수 문자가 있다면 반드시 URL 인코딩해야 합니다.

curl -s -G \
  -H "Authorization: Bearer change-this-to-a-long-random-token" \
  --data-urlencode "url=https://www.example.com/generate_204" \
  --data-urlencode "timeout=5000" \
  "http://127.0.0.1:9090/proxies/노드 이름/delay"

응답의 delay 값은 밀리초 단위입니다. 다만 단 한 번의 측정값을 최종 판단에 사용하지 않는 것이 좋습니다. DNS 캐시, 서버의 순간적인 부하, 무선 네트워크의 재전송 때문에 1회 측정은 크게 흔들릴 수 있습니다. 같은 노드를 짧은 간격으로 두세 번 검사하고, 성공한 값의 중앙값을 사용하거나 실패 횟수를 별도로 누적하면 판단이 훨씬 안정적입니다.

상태판정 예시자동화 동작
정상3회 중 2회 이상 응답, 중앙값 800ms 이하현재 노드 유지
느림응답은 있지만 중앙값이 800~2000ms즉시 전환하지 않고 다음 주기에 재검사
불안정3회 중 2회 이상 타임아웃 또는 5xx후보 목록의 다음 노드로 전환
복구새 노드가 연속 3회 정상 응답안정 상태로 기록, 자동 복귀는 별도 정책 적용

정책 그룹을 변경하는 API 호출

지연 테스트가 끝나면 선택 그룹에 현재 사용할 노드를 지정합니다. mihomo의 선택 그룹 변경은 해당 그룹 이름을 경로에 넣은 PUT /proxies/:name 요청으로 처리하며, JSON 본문에 name을 전달합니다. URL 경로와 JSON 본문에서 사용하는 이름은 모두 설정 파일에 표시된 정확한 이름이어야 합니다.

curl -s -X PUT \
  -H "Authorization: Bearer change-this-to-a-long-random-token" \
  -H "Content-Type: application/json" \
  -d '{"name":"Tokyo-01"}' \
  "http://127.0.0.1:9090/proxies/AI-AUTO"

성공 여부는 HTTP 상태 코드와 다시 조회한 now 값을 함께 확인하세요. 요청이 성공해도 노드 이름을 잘못 입력했거나 해당 노드가 현재 프로필에 존재하지 않으면 원하는 결과가 나오지 않을 수 있습니다. 전환 직후에는 GET /proxies/AI-AUTO로 현재 선택값을 확인하고, 실제 테스트 요청을 한 번 실행해 정책 그룹이 트래픽에 적용되는지도 검증해야 합니다.

정책 그룹은 다음처럼 작성할 수 있습니다. 후보 노드 목록을 직접 그룹에 넣고, 스크립트가 그중 하나를 선택하는 형태입니다.

proxy-groups:
  - name: AI-AUTO
    type: select
    proxies:
      - Tokyo-01
      - Seoul-02
      - Singapore-03
      - DIRECT

DIRECT를 후보에 넣을지는 서비스 성격에 따라 결정하세요. 원격 서버나 사내 빌드 저장소처럼 반드시 프록시를 사용해야 하는 작업이라면 DIRECT를 제외하는 편이 안전합니다. 반대로 국내 API처럼 직결이 더 안정적인 서비스라면 마지막 비상 경로로 둘 수 있습니다. 자동화 스크립트가 모든 후보를 실패로 판정했을 때 무조건 DIRECT로 바꾸면 보안 정책을 우회할 수 있으므로, 이 동작은 명시적인 설정값으로 분리하는 것이 좋습니다.

그룹 전체를 url-test로 바꾸지 마세요

자동 전환 스크립트가 이미 선택 로직을 담당하는데 그룹 타입까지 url-test로 사용하면 두 주체가 서로 다른 노드를 선택할 수 있습니다. 수동 검증이 필요한 경우에는 select 그룹을 유지하고, 스크립트가 한 번에 하나의 전환만 수행하도록 설계하세요. 자동화 주체는 하나여야 로그와 장애 원인을 추적하기 쉽습니다.

자동화 스크립트와 운영 안전장치

아래 Python 예시는 기본적인 장애 조치 흐름을 보여줍니다. 실제 운영에서는 후보 노드 이름, 그룹 이름, 테스트 URL, 지연 한도를 자신의 환경에 맞게 바꾸세요. 예시는 API 응답을 확인하고, 후보를 순서대로 검사하며, 정상 노드를 찾으면 선택 그룹을 변경합니다.

import time
import requests

API = "http://127.0.0.1:9090"
TOKEN = "change-this-to-a-long-random-token"
GROUP = "AI-AUTO"
NODES = ["Tokyo-01", "Seoul-02", "Singapore-03"]
TEST_URL = "https://www.example.com/generate_204"

HEADERS = {
    "Authorization": f"Bearer {TOKEN}",
    "Content-Type": "application/json",
}

def check_node(node):
    endpoint = f"{API}/proxies/{requests.utils.quote(node, safe='')}/delay"
    params = {"url": TEST_URL, "timeout": "5000"}
    try:
        response = requests.get(endpoint, headers=HEADERS,
                                params=params, timeout=8)
        response.raise_for_status()
        delay = response.json().get("delay")
        return isinstance(delay, int) and delay <= 1200
    except (requests.RequestException, ValueError, TypeError):
        return False

def select_node(node):
    endpoint = f"{API}/proxies/{requests.utils.quote(GROUP, safe='')}"
    response = requests.put(endpoint, headers=HEADERS,
                            json={"name": node}, timeout=8)
    response.raise_for_status()

for node in NODES:
    if check_node(node):
        select_node(node)
        print(f"selected: {node}")
        break
else:
    print("no healthy node found")

이 코드는 실행할 때마다 첫 번째 정상 노드를 선택하므로, 현재 노드가 멀쩡해도 목록의 첫 항목으로 돌아갈 수 있습니다. 운영용으로 바꾸려면 먼저 현재 선택값을 조회하고, 현재 노드가 정상인 동안에는 전환하지 않도록 해야 합니다. 또한 후보별 최근 결과를 파일이나 작은 데이터베이스에 저장해 연속 실패 횟수를 계산하세요. 한 번의 실패가 아니라 두세 번 연속 실패했을 때만 전환하고, 전환 후에는 최소 유지 시간인 쿨다운을 두면 플래핑을 줄일 수 있습니다.

  1. 시작할 때 /proxies로 그룹과 후보 노드가 실제로 존재하는지 확인합니다. 이름이 빠졌으면 전환을 중단하고 오류를 기록합니다.
  2. 현재 노드를 먼저 검사합니다. 현재 노드가 정상이라면 후보 전체를 검사하지 않아 API 요청과 불필요한 노드 이동을 줄입니다.
  3. 현재 노드가 연속 실패 기준에 도달하면 후보를 순서대로 검사하고, 정상 응답을 반환한 첫 노드를 선택합니다.
  4. 전환 전후의 시간, 이전 노드, 새 노드, 지연 값, 실패 원인을 로그에 남깁니다. 로그에는 secret이나 구독 URL을 절대 기록하지 않습니다.
  5. 모든 후보가 실패하면 마지막 정상 노드를 유지할지, 작업을 중지할지 결정합니다. 업무용 자동화에서는 실패한 상태를 숨기기보다 알림을 보내고 작업을 중단하는 편이 안전합니다.

Windows에서는 작업 스케줄러로 1~5분 간격의 작업을 만들고, macOS와 Linux에서는 cron 또는 systemd timer를 사용할 수 있습니다. 너무 짧은 간격으로 실행하면 노드 제공자의 제한에 걸리거나 API와 테스트 트래픽이 불필요하게 증가합니다. 장시간 빌드처럼 작업 시작 전에만 확인하면 되는 경우에는 스케줄러보다 빌드 파이프라인의 사전 단계에서 검사하는 방식이 적합합니다.

전환 실패 시 점검 순서와 롤백

API 자동화가 동작하지 않을 때는 노드 자체보다 관리 경로를 먼저 확인해야 합니다. 클라이언트 화면에서 현재 그룹이 바뀌지 않는다면 API 주소, 포트, secret, 그룹 이름을 차례로 확인합니다. 그룹 전환은 성공했지만 애플리케이션 연결이 계속 실패한다면 해당 애플리케이션이 시스템 프록시를 따르는지, TUN 모드가 필요한지, DNS 해석이 올바른지 별도로 점검해야 합니다. API가 바뀌었다고 해서 모든 애플리케이션의 트래픽이 자동으로 Clash를 통과하는 것은 아닙니다.

  • 401 Unauthorized—Authorization 헤더의 Bearer 값이 현재 secret과 일치하는지 확인합니다. 토큰 앞뒤에 공백이나 따옴표가 포함되지 않았는지도 봅니다.
  • 404 Not Found—커널이 mihomo인지, 프록시 이름을 URL 인코딩했는지, 실제 API 경로가 해당 버전에서 지원되는지 확인합니다.
  • 400 또는 500 오류—JSON 본문의 키가 name인지, 선택하려는 노드가 그룹의 proxies 목록에 있는지 확인합니다.
  • 지연 측정은 성공하지만 서비스가 열리지 않음—테스트 URL이 실제 서비스의 차단·인증·지역 제한을 반영하지 못할 수 있습니다. 업무 대상에 가까운 별도 테스트 URL을 사용하세요.
  • 전환 직후 다시 원래 노드로 돌아감—스크립트가 여러 번 동시에 실행되거나, 그룹 타입의 자동 선택 기능과 스크립트가 동시에 동작하는지 확인합니다.

롤백은 자동화 시스템에 반드시 포함해야 합니다. 새 노드로 바꾼 뒤 일정 시간 안에 실제 업무 검사가 실패하면 이전 노드로 되돌리고, 같은 후보를 바로 재선택하지 않도록 잠시 제외합니다. 전환 횟수가 짧은 시간에 특정 한도를 넘으면 자동화를 중지하고 수동 확인을 요구하는 회로 차단기도 유용합니다. 이 장치는 API 장애, 전체 네트워크 장애, 잘못된 테스트 URL로 인한 연쇄 전환을 막아 줍니다.

운영 전에는 장애를 직접 재현하세요

정상 상태에서만 테스트하면 자동화의 절반만 검증한 것입니다. 테스트용 후보를 잠시 차단하거나 잘못된 포트를 지정해 타임아웃을 재현하고, 실패 횟수 누적, 다음 노드 선택, 로그 기록, 복구 후 동작까지 확인하세요. 검증이 끝나면 실제 후보와 테스트 URL을 원래 값으로 되돌리고, secret이 로그나 환경 변수 출력에 노출되지 않았는지 점검합니다.

Clash 클라이언트 다운로드

규칙 분리를 적용하려면 먼저 클라이언트가 트래픽을 인계받아야 합니다. 다운로드 센터에서 사용 중인 플랫폼에 맞는 클라이언트를 선택한 뒤, 다시 가이드로 돌아와 시스템 프록시 또는 TUN 인계를 완료하세요.

Clash 다운로드