왜 config.yaml을 읽을 줄 알아야 할까
Clash·Mihomo(구 Clash Meta) 계열 앱은 결국 하나의 텍스트 프로필을 코어가 읽고, 그 안의 proxies·proxy-groups·rules 정의에 따라 트래픽을 붙입니다. 구독 링크만 넣으면 대부분 자동으로 채워지지만, 포트 충돌·정책 이름 불일치·LAN 공유·특정 사이트만 DIRECT 같은 요구가 생기면 결국 YAML을 직접 봐야 합니다. 이 글은 “한 줄 한 줄이 무슨 뜻인가”부터 시작해, 특히 초보자가 막히는 프록시 그룹(정책 그룹) 설계 패턴까지 이어집니다.
배포판·코어 버전마다 지원 타입과 키 이름이 조금씩 다를 수 있으므로, 예시는 가장 흔한 표기를 기준으로 합니다. GUI에서 보이는 설정 화면과 다른 경우, 메뉴에 적힌 “설정 디렉터리”의 실제 파일을 여는 것이 가장 빠릅니다.
용어: 문서·커뮤니티에서 전략 그룹・정책 그룹・프록시 그룹은 대개 같은 proxy-groups 항목을 가리킵니다. 규칙(rules) 오른쪽에 적는 문자열은 이 그룹의 name과 정확히 같아야 합니다.
YAML 문법: 들여쓰기, 리스트, 주석
YAML은 들여쓰기로 계층을 표현합니다. Clash 프로필은 보통 스페이스 두 칸 들여쓰기를 쓰고, 탭 문자를 섞지 않는 것이 안전합니다. 같은 계층은 같은 칸 수로 시작해야 하며, 한 단계만 어긋나도 “mapping values are not allowed here” 같은 파서 오류가 납니다.
리스트는 하이픈(-)으로 시작하는 블록이거나, [a, b] 형태의 인라인 배열입니다. proxies 항목은 흔히 - name: ... 형태의 딕셔너리 배열입니다. 주석은 #부터 줄 끝까지이며, UTF-8 인코딩을 유지하면 한글 주석도 가능하지만 구독 병합 시 인코딩이 깨지지 않게 편집기에서 저장 형식을 확인하세요.
# Top-level keys are usually unindented
port: 7890
proxies:
- name: node-a
type: ss
server: 192.0.2.1
port: 8388
cipher: aes-128-gcm
password: "use-strong-secret"
문자열에 :나 특수문자가 섞이면 따옴표로 감싸는 습관을 들이면, 나중에 규칙 줄을 붙여 넣을 때도 실수가 줄어듭니다.
상단 일반 설정: 포트, 모드, 로그
파일 앞부분에는 클라이언트가 리스닝할 HTTP/SOCKS 포트와 동작 모드가 옵니다. 과거 예제는 port와 socks-port를 나눴지만, 요즘 빌드는 mixed-port 하나로 HTTP·SOCKS를 같이 열기도 합니다. 실제 키 조합은 템플릿이 생성한 그대로 유지하고, 충돌만 없으면 됩니다.
allow-lan을 켜면 같은 Wi-Fi의 다른 기기가 당신 PC의 Clash 포트로 프록시를 걸 수 있습니다. 편리하지만 신뢰하지 않는 네트워크에서는 끄는 편이 안전합니다. bind-address로 특정 인터페이스에만 묶을 수 있는 구현도 있습니다.
mode는 대개 Rule, Global, Direct 중 하나입니다. Rule이면 아래 rules 표를 타고, Global이면 거의 전부 지정한 프록시로, Direct는 우회 없이 나갑니다. GUI의 토글과 이 값이 어긋나 있으면 “규칙을 바꿨는데 반응이 없다”는 혼란이 생깁니다.
log-level은 info·warning·debug 등인데, 규칙이 어디에 걸리는지 추적할 때만 잠깐 올렸다가 다시 내리면 로그 용량·노출 정보 측면에서 좋습니다.
mixed-port: 7890
allow-lan: false
mode: Rule
log-level: info
external-controller: 127.0.0.1:9090
proxies: 노드 한 줄한 줄이 ‘원천’
proxies 아래 각 항목은 실제로 붙을 업스트림 서버 정의입니다. name은 이후 proxy-groups와 rules가 참조하는 식별자이므로 짧고 유니크하게 짓는 것이 좋습니다. type에 따라 필요한 필드가 달라집니다. 예를 들어 Shadowsocks(ss)는 cipher·password, VMess는 uuid·alterId(구버전)·ALPN·TLS 설정 등을 요구합니다.
히스토리적으로 udp 지원 여부, skip-cert-verify 같은 TLS 완화 옵션, packet-encoding 같은 확장 필드가 붙기도 합니다. skip-cert-verify: true는 테스트에만 쓰고 장기 보관하지 마세요. 구독 발행 측이 제공하는 템플릿이 최신 코어와 맞지 않으면 기동 시 해당 노드만 무시되거나 전체가 실패할 수 있으니, 로그의 “unsupported type” 메시지를 함께 확인합니다.
proxies:
- name: office-ss
type: ss
server: 198.51.100.10
port: 443
cipher: aes-256-gcm
password: "replace-me"
udp: true
- name: vendor-vmess
type: vmess
server: example.com
port: 443
uuid: 00000000-0000-4000-8000-000000000000
alterId: 0
cipher: auto
tls: true
servername: example.com
proxy-groups 입문: 단일 노드를 감싸는 이유
규칙은 그룹 이름에 연결하는 경우가 많습니다. 이유는 간단합니다. 사용자가 GUI에서 국가별 라인을 고르거나, 지연 테스트로 자동 최적 노드를 고르게 하려면, 여러 proxies 후보를 한 덩어리로 묶은 논리적 슬롯이 필요하기 때문입니다. proxy-groups는 바로 그 슬롯입니다.
각 그룹도 name·type·proxies 리스트를 가집니다. proxies 항목에는 앞서 정의한 노드 name 문자열이 들어가고, 또 다른 그룹 이름을 넣어 중첩 선택을 만들기도 합니다. 순환 참조만 없으면 됩니다.
type별 동작: select, url-test, fallback, load-balance
select는 말 그대로 수동 선택 그룹입니다. 첫 기동 시 now로 시작하는 필드나 이전 세션 값이 남아 있을 수 있는데, 코어·GUI 조합에 따라 다르므로 파일만 보고 판단하기보다 UI와 함께 확인하세요.
url-test는 url로 지정한 대상(보통 작은 바이트의 https 엔드포인트)에 주기적으로 요청을 보내 시간이 가장 짧은 후보를 고릅니다. interval(초)·tolerance(밀리초 단위 허용 오차)가 붙습니다. 너무 공격적인 interval은 배터리와 로그를 낭비하고, 너무 느리면 장애 감지가 늦습니다.
fallback는 일종의 순차 헬스 체인에 가깝습니다. 첫 번째 후보가 죽었을 때 다음으로 넘어가는 패턴을 기대할 때 고르면 됩니다만, 세부 알고리즘은 코어 문서를 따르는 것이 안전합니다.
load-balance는 여러 노드로 부하를 나눕니다. 전략(strategy)에 따라 해시 기반 고정 세션형이 될 수도 있고 단순 라운드로빈에 가까울 수도 있습니다. 스트리밍·은행 앱처럼 세션 고정이 필요한 서비스에서는 오히려 불리할 수 있으니, 목적에 맞는지 먼저 생각해야 합니다.
relay는 노드를 연쇄해 한 줄로 이어 붙이는 타입입니다. 체인 중 한 홉이라도 잘못되면 전체가 실패합니다. 익숙해지기 전에는 단순 select·url-test부터 쓰는 편이 낫습니다.
proxy-groups:
- name: PROXY
type: select
proxies:
- AUTO
- office-ss
- DIRECT
- name: AUTO
type: url-test
proxies:
- vendor-vmess
- office-ss
url: https://www.gstatic.com/generate_204
interval: 300
tolerance: 50
규칙과 연결하기: 오른쪽 토큰이 곧 그룹 이름
rules의 각 줄은 대략 TYPE,인자...,정책 형식입니다. 마지막 정책 자리에 PROXY처럼 proxy-groups의 name을 적습니다. 그룹 이름을 바꿨다면 규칙 전체에서 일괄 치환하지 않으면 기동이 깨집니다. DIRECT와 REJECT는 예약어로 그대로 쓰입니다.
맨 아래 MATCH,PROXY 한 줄은 사실상 필수에 가깝습니다. 위 규칙 어디에도 안 걸리는 흐름을 받아 줍니다. 분할 규칙을 더 깊게 다루는 글은 별도 가이드를 참고하되, YAML 관점에서는 정책 문자열 = 그룹 name이라는 등식만 기억해도 절반은 해결입니다.
프로바이더: proxy-providers와 rule-providers 한눈에
대규모 구독은 매번 파일에 긴 proxies 배열을 붙여 넣기보다, 원격 YAML을 주기적으로 내려받는 provider로 쪼개 두는 경우가 많습니다. proxy-providers 항목에 type: http·url·path·interval을 두고, proxy-groups의 proxies에 provider: 이름 형태로 끼워 넣을 수 있습니다(정확한 키 이름은 사용 중인 코어 문서 확인).
rule-providers는 앞서 언급한 대로 대량 도메인·IP 목록을 모듈화합니다. behavior가 domain·ipcidr·classical 중 무엇인지에 따라 매칭 엔진이 달라지므로, 가져온 세트 문서의 권장값을 따르세요.
dns와 tun: 흔한 상위 블록
Rule 모드에서 도메인 규칙과 GEOIP가 함께 쓰이면, DNS가 fake-ip를 쓰는지, fallback DNS를 두었는지에 따라 체감 동작이 크게 달라집니다. dns: 아래 enable·enhanced-mode·nameserver 목록은 한 번쯤 전체를 읽어 두면, “이 사이트만 이상하게 탄다”는 증상을 추적할 때 단서가 됩니다.
TUN 인터페이스를 켜는 빌드는 tun: 블록에 스택·MTU·DNS 하이재킹 같은 옵션이 있습니다. 권한(관리자/네트워크 확장) 요구와 플랫폼별 차이가 크므로, YAML만 보지 말고 OS 설정도 함께 봐야 합니다.
실무 워크플로: 수정·검증·백업
프로필을 고칠 때는 (1) 사본을 만들고 (2) 작은 덩어리만 바꾼 뒤 (3) 저장·재로드·로그 확인 순으로 가는 것이 안전합니다. Git으로 버전 관리하면 “어제 되던 구독이 오늘 깨졌다”는 상황에서 diff로 원인을 빨리 찾을 수 있습니다.
자동 병합 도구가 있더라도, 중복 키·같은 name의 proxies가 생기지 않게 확인하세요. 특히 사용자 규칙을 파일 끝이 아니라 중간에 붙이면, 아래쪽 기본 MATCH가 의도치 않게 앞당겨지는 일은 없는지 들여쓰기를 다시 봐야 합니다.
짧게 보는 FAQ
Q. Global 모드인데 규칙을 수정해도 소용없나요?
A. 네, mode: Global이면 사실상 규칙보다 전역 프록시 선택이 우선하는 흐름입니다. Rule 모드로 바꾼 뒤 테스트하세요.
Q. 그룹에 DIRECT를 넣을 수 있나요?
A. 네, select 그룹의 후보로 DIRECT 문자열을 넣는 패턴이 흔합니다. 이때도 대문자·철자가 정확해야 합니다.
Q. 코어가 “proxy not found”라고 하면?
A. proxy-groups나 규칙이 가리키는 이름이 proxies 목록·provider에 실제로 존재하는지 확인하세요. 구독 갱신 후 이름이 바뀌었을 가능성이 큽니다.
범용 VPN 앱·브라우저 전용 우회와 비교해 Clash YAML의 강점
앱 스토어형 VPN은 버튼 하나로 켜기엔 편하지만, 분할 터널 세밀도나 팀·가정 내 장비 공유 패턴에는 한계가 있습니다. 해외 회선으로 모든 트래픽을 몰면 국내 결제·캡차·지연 문제가 생기기 쉽고, 반대로 브라우저 확장만 쓰면 IDE·패키지 매니저·게임 런처는 그대로 노출되는 경우가 많습니다. Clash 계열은 한 번의 YAML로 포트·TUN·규칙·정책 그룹을 같은 언어로 기술할 수 있어, “이 프로젝트는 DIRECT, 업데이트 서버만 프록시”처럼 직무 맞춤형 경로를 표현하기 좋습니다.
또 구독 업체가 바뀌어도 프록시 그룹 골격과 rules는 그대로 가져가는 편이 기본입니다. 구조를 YAML로 이해해 두면, 새 노드 이름만 끼워 넣어도 예전 패턴을 재현할 수 있습니다. 플랫폼에 맞는 클라이언트를 받아 같은 프로필을 옮겨 쓰는 흐름도 비교적 단순합니다.