규칙을 한 파일에 몰아넣지 말아야 하는 이유

Clash 설정이 작을 때는 rules: 아래에 도메인과 정책을 직접 적어도 큰 문제가 없습니다. 하지만 서비스가 늘어나고 지역별 규칙, 광고 차단 목록, AI 서비스 목록, 사내 도메인이 함께 들어오기 시작하면 하나의 YAML 파일은 빠르게 관리 한계에 도달합니다. 구독 프로필이 갱신될 때마다 로컬 수정분이 사라지거나, 특정 규칙을 잠깐 비활성화하려다 들여쓰기 하나를 잘못 넣어 전체 설정이 로드되지 않는 일도 흔합니다.

rule-providers는 규칙 목록을 별도 파일로 분리하고, Clash가 그 파일을 원격 또는 로컬 공급자로 읽게 하는 기능입니다. 메인 설정에는 공급자의 이름과 형식, 업데이트 주기만 남기고 실제 DOMAIN-SUFFIX, DOMAIN-KEYWORD, IP-CIDR 목록은 별도 YAML에 보관합니다. 이렇게 나누면 GitHub에서 규칙 파일만 검토하고 변경 이력을 비교할 수 있으며, 여러 프로필에서 동일한 규칙 세트를 재사용하기도 쉽습니다.

다만 rule-provider가 모든 코어와 클라이언트에서 똑같이 동작하는 것은 아닙니다. 오래된 Clash 계열 코어는 일부 필드나 형식을 지원하지 않을 수 있고, Clash Verge Rev·Mihomo·Clash for Android처럼 실제 코어가 다른 클라이언트는 파서의 허용 범위도 달라질 수 있습니다. 따라서 설정을 작성하기 전에 현재 실행 중인 코어 버전과 지원 문법을 확인하고, 새 규칙을 한 번에 대량 적용하기보다 작은 공급자부터 검증하는 편이 안전합니다.

ℹ 운영 기준: rule-provider는 규칙을 숨기는 기능이 아니라 규칙의 생명주기를 분리하는 기능입니다. 누가 언제 어떤 도메인을 추가했는지 추적할 수 있도록 GitHub 저장소와 커밋 메시지를 함께 관리하세요.

공급자 YAML의 기본 구조와 형식 선택

가장 단순한 공급자 파일은 payload 배열에 규칙을 넣는 방식입니다. 파일 확장자는 보통 .yaml 또는 .yml을 사용하며, 각 항목은 현재 코어가 이해할 수 있는 규칙 문자열이어야 합니다. 예를 들어 광고 도메인을 분리하려면 다음처럼 구성할 수 있습니다.

payload:
  - DOMAIN-SUFFIX,ads.example.com
  - DOMAIN-SUFFIX,tracking.example.net
  - DOMAIN-KEYWORD,telemetry

메인 설정에서는 이 파일을 rule-providers에 등록합니다. type은 원격 URL을 읽는 경우 http, 디스크에 함께 배포한 파일을 읽는 경우 file을 사용합니다. URL 공급자는 일정 시간이 지나면 다시 내려받도록 interval을 지정하고, 로컬 저장 위치는 path로 명확히 정합니다. 원격 파일의 URL, 캐시 경로, 업데이트 주기를 한 줄씩 분리해 두면 장애가 생겼을 때 어느 계층에서 실패했는지 빠르게 알 수 있습니다.

rule-providers:
  MY-ADS:
    type: http
    behavior: domain
    format: yaml
    url: https://raw.githubusercontent.com/example/clash-rules/main/ads.yaml
    path: ./rules/my-ads.yaml
    interval: 86400

rules:
  - RULE-SET,MY-ADS,REJECT
  - MATCH,PROXY

여기서 behavior는 공급자가 어떤 종류의 규칙을 담는지 설명합니다. 도메인만 담는 목록에는 domain, IP 범위나 혼합 규칙을 다루는 목록에는 코어가 지원하는 적절한 값을 사용해야 합니다. 일부 Mihomo 환경에서는 format: yaml과 함께 YAML의 payload 구조를 요구하고, 다른 형식에서는 규칙 줄을 직접 읽도록 설정합니다. 공급자 파일과 등록부의 형식이 서로 다르면 다운로드는 성공해도 규칙이 0개로 로드될 수 있으므로, “HTTP 200”만으로 성공을 판단해서는 안 됩니다.

원격 공급자와 로컬 공급자의 차이

GitHub에 공개하거나 접근 가능한 저장소에 규칙을 올리고 raw 주소로 읽는 방식은 여러 기기에서 같은 목록을 쓰기 좋습니다. 반면 사내 호스트, 개인 서비스, 구독 정보처럼 공개하면 안 되는 값은 공개 GitHub에 넣어서는 안 됩니다. 이런 경우에는 로컬 파일, 비공개 저장소를 거치는 승인된 배포 과정, 또는 클라이언트가 지원하는 안전한 내부 URL을 사용해야 합니다.

로컬 공급자는 네트워크가 끊겨도 마지막으로 저장된 규칙을 읽을 수 있다는 장점이 있습니다. 대신 모든 기기에 파일을 복사해야 하고, 업데이트 자동화가 별도로 필요합니다. 원격 공급자는 배포가 간편하지만 GitHub 장애, raw 응답 제한, TLS 인증서 문제, 브랜치 변경에 영향을 받습니다. 실전에서는 중요한 기본 규칙은 로컬 또는 안정적인 미러에 두고, 변경 빈도가 높은 커뮤니티 목록만 원격으로 두는 혼합 구성이 관리하기 좋습니다.

GitHub에서 규칙 세트를 버전 관리하는 방법

GitHub 저장소의 핵심은 단순히 YAML 파일을 업로드하는 것이 아니라 변경 과정을 검토 가능하게 만드는 데 있습니다. 저장소 안에 rules/ 디렉터리를 만들고, 용도별로 ads.yaml, ai.yaml, private.yaml처럼 파일을 나누면 규칙의 책임 범위가 분명해집니다. README에는 지원 코어, 파일 형식, 마지막 검증 날짜, 적용할 정책 이름을 기록해 두세요. 파일 이름을 자주 바꾸면 raw URL과 클라이언트 캐시가 함께 꼬이므로 안정적인 경로를 유지하는 것이 좋습니다.

커밋은 “규칙 수정”처럼 모호하게 쓰기보다 “광고 공급자에서 오탐 도메인 3개 제거”, “AI API 도메인 추가”, “Mihomo YAML 형식으로 변환”처럼 영향 범위를 설명해야 합니다. 작은 변경을 작은 커밋으로 나누면 문제가 생겼을 때 마지막 변경만 되돌릴 수 있습니다. 특히 도메인 목록을 자동 생성하는 스크립트를 사용한다면 생성 원본과 결과 파일을 구분하고, 수동으로 수정한 줄이 다음 실행에서 덮어써지는지 문서에 명시해야 합니다.

공개 규칙 목록이라도 토큰, 구독 URL, 내부 호스트명, 사설 IP, 사용자 식별 정보가 섞이지 않았는지 확인해야 합니다. GitHub 커밋에서 파일을 삭제해도 과거 이력에는 값이 남을 수 있으므로 비밀 정보가 실수로 올라갔다면 단순 삭제보다 자격 증명 폐기와 이력 정리 절차가 우선입니다. 또한 제3자가 관리하는 규칙을 그대로 가져오는 경우에는 라이선스, 업데이트 빈도, 과도하게 넓은 도메인 패턴을 검토해야 합니다.

ℹ GitHub 팁: 기본 브랜치에는 검증된 규칙만 병합하고, 실험용 도메인은 별도 브랜치나 풀 리퀘스트에서 테스트하세요. 규칙 파일 하나의 오타가 여러 사용자의 트래픽 정책을 동시에 바꿀 수 있습니다.

RULE-SET 우선순위와 예외 규칙 설계

공급자를 등록했다고 자동으로 적용되는 것은 아닙니다. rules: 아래에서 RULE-SET을 호출해야 하며, Clash는 일반적으로 위에서 아래 방향으로 규칙을 평가합니다. 따라서 더 구체적인 예외를 넓은 규칙보다 위에 배치해야 합니다. 예를 들어 특정 개발 패키지 저장소는 프록시로 보내되 일반적인 GitHub 도메인은 직접 연결하려는 경우, 예외 규칙을 먼저 적고 그 다음에 전체 공급자를 배치해야 합니다.

rules:
  - DOMAIN,packages.example.com,PROXY
  - RULE-SET,DEV-SERVICES,PROXY
  - RULE-SET,GLOBAL-DIRECT,DIRECT
  - GEOIP,LAN,DIRECT
  - MATCH,PROXY

두 공급자에 같은 도메인이 들어 있으면 먼저 매칭되는 공급자의 정책이 적용됩니다. 광고 목록과 업무용 허용 목록이 충돌하는 상황에서는 파일 이름만 보고 판단하지 말고, 실제 규칙 순서와 정책 그룹을 함께 확인해야 합니다. 특히 DOMAIN-SUFFIX,example.com은 모든 하위 도메인에 영향을 줄 수 있으므로, 로그인·API·정적 파일이 서로 다른 경로를 사용하는 서비스에는 지나치게 넓은 접미 규칙을 신중하게 적용하세요.

예외가 계속 늘어난다면 공급자 하나에 모든 의도를 넣고 있는 신호입니다. “직접 연결”, “프록시”, “차단”, “개발 서비스”처럼 결과 정책별로 목록을 나누면 규칙 순서를 읽기 쉬워집니다. 다만 너무 작은 파일을 수십 개 만들면 업데이트 상태와 캐시를 관리하기 어려워지므로, 실제 변경 주기와 담당 주체를 기준으로 적당한 경계를 정해야 합니다.

자동 업데이트와 로그 기반 장애 분석

interval은 공급자 파일을 확인하는 주기이지 모든 연결이 즉시 새 규칙으로 바뀐다는 뜻은 아닙니다. 클라이언트가 공급자를 다운로드하고 파싱한 뒤 활성 프로필에 반영하는 과정이 필요합니다. 업데이트 직후에는 공급자 관리 화면에서 마지막 갱신 시간, 파일 크기, 규칙 수, HTTP 상태를 확인하세요. 파일 크기가 갑자기 0바이트에 가깝거나 규칙 수가 평소보다 크게 줄었다면 GitHub 경로, 브랜치, raw 응답, YAML 문법을 먼저 점검해야 합니다.

장애를 재현할 때는 문제가 된 도메인을 한 개로 줄이고 Clash 연결 로그에서 해당 요청을 찾습니다. 로그에 요청이 보이지 않으면 DNS, 애플리케이션 프록시 상속, TUN 모드 여부를 살펴보고, 요청은 보이지만 예상 정책이 아니라면 규칙 순서와 공급자 로드 상태를 확인합니다. 정책은 맞는데 연결이 실패하면 그때 노드, TLS, 원격 서버 응답을 분리해서 검사합니다. 처음부터 노드를 계속 바꾸면 규칙 문제와 네트워크 품질 문제가 섞여 원인을 놓치기 쉽습니다.

업데이트 실패와 규칙 매칭 실패도 구분해야 합니다. GitHub에서 파일을 내려받지 못한 경우에는 기존 캐시가 계속 사용될 수 있고, 클라이언트에 따라 마지막 정상 버전을 유지하거나 공급자를 비활성화할 수 있습니다. 반대로 다운로드는 성공했지만 형식 필드가 코어와 맞지 않으면 새 버전이 적용되지 않을 수 있습니다. 변경 전후에 공급자 해시, 규칙 수, 특정 테스트 도메인의 매칭 결과를 기록하면 롤백 판단이 빨라집니다.

운영 환경에서는 새 규칙을 바로 기본 브랜치에 반영하지 말고, 테스트 프로필에서 먼저 공급자를 불러오는 절차를 권장합니다. 테스트 대상은 DNS 조회, HTTPS 접속, WebSocket이나 장시간 스트리밍, 직접 연결 예외, 차단 규칙 등으로 나누면 좋습니다. 검증이 끝난 뒤에만 기본 브랜치와 자동 업데이트 경로에 병합하고, 문제가 생기면 마지막 커밋을 되돌린 뒤 클라이언트에서 공급자를 수동 새로 고침합니다.

단일 파일을 직접 편집하는 방식은 처음에는 단순하지만 구독 갱신과 팀 협업, 변경 추적이 필요한 순간마다 한계가 드러납니다. 반대로 일부 GUI 클라이언트는 rule-provider의 형식 선택이나 캐시 경로를 충분히 보여 주지 않아 원인 분석이 어렵고, 오래된 포크는 최신 Mihomo 필드를 무시할 수 있습니다. Clash V.CORE는 YAML 기반 공급자와 규칙 우선순위를 직접 확인하면서도 프로필과 코어 상태를 한 흐름에서 점검하기 좋으므로, GitHub 규칙 세트를 반복 운영할 사용자라면 현재 환경에 맞는 빌드를 내려받아 작은 테스트 공급자부터 적용해 보는 것이 가장 안전합니다.