먼저 응답 내용부터 확인하세요: 구독 주소가 설정 형식은 아닙니다
Clash 구독 가져오기에 실패해도 바로 클라이언트를 바꾸지는 마세요. 같은 HTTPS 주소라도 바로 사용할 수 있는 YAML 설정을 반환할 수도 있고, Base64 문자열이나 로그인 페이지를 반환할 수도 있습니다. URL의 확장자만으로는 형식을 판단하기 어렵습니다. .yaml 확장자가 없는 엔드포인트에서도 YAML을 반환할 수 있으며, 해당 확장자가 붙은 주소도 인증이 만료되면 오류 메시지를 반환할 수 있습니다.
구독을 세 가지 층위로 나누면 판단하기 쉽습니다. 구독 주소는 데이터를 가져오는 경로이고, Base64는 텍스트 인코딩이며, 실제 데이터 구조를 정의하는 형식은 YAML이나 URI입니다. YAML도 전체 설정인지 노드만 담긴 데이터인지 구분해야 합니다. 노드 목록을 전체 설정으로 가져오는 것이 흔한 오류 원인입니다.
| 확인한 내용 | 일반적인 의미 | 다음 단계 |
|---|---|---|
proxies:、proxy-groups:、rules: |
전체 Clash 설정일 수 있음 | 노드, 그룹 참조, 커널 호환성을 확인합니다 |
proxies:와 노드 항목만 있음 |
노드 목록 또는 provider 데이터 | 노드 provider로 연결하거나 전체 설정에 병합합니다 |
여러 줄의 ss://, trojan:// 링크 |
URI 노드 목록 | 노드 가져오기를 지원하는 화면을 사용하거나 형식을 변환합니다 |
| 영문자와 숫자, 일부 기호가 연속해서 나옴 | Base64 인코딩 데이터일 수 있음 | 로컬에서 디코딩한 뒤 결과 형식을 확인합니다 |
<html>, 로그인 안내, JSON 오류 |
웹 페이지 또는 API 오류 응답 | 구독 만료 여부, 인증, 접근 제한을 확인합니다 |
YAML 설정: 노드, 정책 그룹, 규칙의 역할
YAML은 데이터 직렬화 형식이며 Clash 전용 형식은 아닙니다. YAML 파서가 읽을 수 있다는 것은 문법이 유효하다는 뜻일 뿐입니다. 클라이언트는 필드와 노드 프로토콜, 참조 관계도 검사합니다. mihomo 기반 클라이언트의 실제 지원 범위는 실행 중인 커널에 따라 달라집니다. 화면 이름에 Clash가 있는지만으로 판단하지 마세요.
최소 예제의 구조
아래 예제는 로컬 프록시 진입점, Shadowsocks 노드 하나, 선택 그룹 하나, 규칙 간의 관계를 보여줍니다. node.example.invalid은 예시용으로 예약된 도메인이고 비밀번호도 설명용 값이므로 실제 연결에는 사용할 수 없습니다. 포트 7890은 여기서 직접 지정한 로컬 혼합 프록시 포트이며, 모든 클라이언트가 이 포트를 사용하는 것은 아닙니다.
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
proxies:
- name: "Demo SS"
type: ss
server: node.example.invalid
port: 443
cipher: aes-128-gcm
password: "demo-pass"
proxy-groups:
- name: "수동 선택"
type: select
proxies:
- "Demo SS"
- DIRECT
rules:
- IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- MATCH,수동 선택
proxies: 서버 주소와 프로토콜, 포트, 인증 정보를 저장합니다.proxy-groups: 노드나 다른 정책을 묶어 사용자가 선택하거나 자동 정책을 적용할 수 있게 합니다.rules: 위에서 아래로 트래픽을 매칭합니다. 예제 마지막의MATCH는 나머지 연결에 적용됩니다.mixed-port: HTTP와 SOCKS 프록시 진입점을 제공합니다. 클라이언트의 재정의 설정이 값을 바꿀 수 있으므로 실제 실행 설정을 확인하세요.
이 예제는 구조를 설명하기 위한 것으로 DNS, TUN, LAN 접근 정책은 포함하지 않습니다. 범용 네트워크 최적화 방법이 아니며 DNS 요청의 실제 경로를 판단하는 데 사용할 수도 없습니다. 실제 설정을 가져오기 전에 서비스 제공자가 요구하는 전송 계층과 인증 필드를 그대로 유지하세요.
YAML에서 자주 실수하는 세 가지
- 들여쓰기: 공백을 사용하고 Tab은 쓰지 마세요. 위 예제의 목록 항목은 공백 2칸, 노드 속성은 공백 4칸 들여씁니다.
- 문자열: 특수 문자가 포함된 비밀번호와 노드 이름은 따옴표로 감싸는 것이 좋습니다. 따옴표로 감싸지 않은
#은 특정 위치에서 주석을 시작해 내용이 잘릴 수 있습니다. - 참조: 노드 이름과 정책 그룹 이름은 정확히 일치해야 합니다.
Demo SS를Demo-SS로 바꾸면 그룹 안의 참조도 함께 수정해야 합니다.
Base64 노드 목록: 먼저 디코딩한 다음 가져오세요
흔히 말하는 ‘Base64 구독’은 여러 URI 링크를 줄바꿈으로 이어 붙인 뒤 전체 텍스트를 Base64로 인코딩한 경우가 많습니다. 디코딩 결과는 여전히 노드 목록이며, 규칙이나 정책 그룹, DNS 설정이 새로 생기지는 않습니다. 서비스에 따라 다른 데이터를 인코딩하기도 하므로 최종 판단은 항상 디코딩 결과를 기준으로 해야 합니다.
표준 Base64에는 보통 +, /가 사용되고 끝에 =가 붙을 수 있습니다. URL 안전 변형은 -와 _를 사용합니다. 일부 API는 끝의 패딩을 생략합니다. 등호가 없다고 Base64가 아니라고 단정하지 말고, HTTPS 구독 주소 전체를 디코딩하지도 마세요.
디코딩 결과를 로컬에서 확인하기
컴퓨터에 Python 3이 설치되어 있다면 구독 응답에서 인코딩된 본문을 subscription.txt로 저장한 뒤, 파일이 있는 폴더에서 아래 명령을 실행하세요. 스크립트는 로컬 파일만 읽고 결과를 decoded.txt에 저장하므로 내용을 업로드하지 않습니다. 출력 파일에도 민감한 인증 정보가 포함될 수 있으니 사용 후 안전하게 정리하세요.
python3 - <<'PY'
from pathlib import Path
import base64
import binascii
raw = Path("subscription.txt").read_text(encoding="utf-8-sig")
encoded = "".join(raw.split())
encoded += "=" * (-len(encoded) % 4)
try:
decoded = base64.b64decode(
encoded, altchars=b"-_", validate=True
).decode("utf-8")
except (binascii.Error, UnicodeDecodeError, ValueError) as error:
raise SystemExit("디코딩 실패: 입력이 Base64 텍스트인지 확인하세요") from error
Path("decoded.txt").write_text(decoded, encoding="utf-8")
print("decoded.txt에 저장했습니다. 로컬에서 확인하세요")
PY
이 명령은 Unix 계열 셸의 here-document 문법을 사용하며 macOS와 Linux 등에서 실행할 수 있습니다. Windows에서는 Python 코드를 파일로 저장한 다음 실행하세요. 디코딩에 실패하면 웹 페이지 내용이 잘못 저장되지는 않았는지, 복사한 내용이 빠지지는 않았는지, 파일 바깥의 따옴표까지 복사하지는 않았는지 확인하세요.
URI 링크: 링크 하나가 노드 하나를 나타냅니다
URI는 보통 ss://, vmess://, vless://, trojan://처럼 프로토콜 이름으로 시작합니다. 각 링크가 같은 내부 인코딩을 사용하는 것은 아닙니다. 흔히 쓰이는 VMess 공유 링크는 JSON을 인코딩해 링크에 넣고, 다른 프로토콜은 사용자 정보와 호스트, 포트, 쿼리 매개변수 조합으로 연결 정보를 나타낼 수 있습니다.
Shadowsocks 예제: 인증 정보만 인코딩
ss://[email protected]:443#Demo%20SS
이 예제에서 YWVzLTEyOC1nY206ZGVtby1wYXNz를 디코딩하면 aes-128-gcm:demo-pass가 됩니다. node.example.invalid:443은 서버와 포트이고, #Demo%20SS는 퍼센트 인코딩된 표시 이름입니다. 앞서 나온 예제 노드에 해당하지만 정책 그룹과 분할 라우팅 규칙은 포함하지 않습니다.
- 퍼센트 인코딩과 Base64는 다릅니다:
%20은 공백을 뜻합니다. URI 구성 요소로 디코딩해야 하며 Base64로 처리하면 안 됩니다. - 이름은 연결 매개변수가 아닙니다: 링크 끝의 메모는 보통 표시 이름에만 영향을 줍니다. 쿼리 매개변수의 전송 설정은 연결 가능 여부를 직접 좌우할 수 있습니다.
- IPv6 주소에는 대괄호를 사용하세요: URI의 호스트 부분은 일반적으로
[IPv6주소]:포트형식이어야 하며, 콜론마다 단순히 나눌 수 없습니다. - SS 공유 링크 형식은 여러 가지입니다: 인증 정보 인코딩, 구형 전체 인코딩, 플러그인 매개변수의 호환성은 서로 다르므로 변환기가 구체적인 형식을 판별해야 합니다.
콜론을 찾아 나누는 식으로 처리하지 마세요. 비밀번호에 특수 문자가 포함될 수 있고 IPv6 주소에는 콜론이 있으며 WebSocket 경로에도 쿼리 매개변수가 들어갈 수 있습니다. 정확한 변환을 위해서는 각 링크를 공통된 문자열 치환 규칙으로 다루는 대신 프로토콜에 따라 파싱해야 합니다.
형식 변환: 유지되는 항목과 손실되는 항목
형식 변환의 핵심은 확장자를 바꾸는 것이 아니라 필드를 매핑하는 것입니다. 원본 형식에 데이터가 포함되어 있고 대상 형식과 대상 커널이 모두 해당 데이터를 지원해야 온전히 보존할 수 있습니다. 먼저 대상이 ‘노드 목록’, ‘provider 데이터’, ‘전체 설정’ 중 무엇인지 정한 다음 변환 방법을 선택하세요.
| 변환 방향 | 실제 작업 | 주요 제한 사항 |
|---|---|---|
| Base64 → URI 목록 | 바깥쪽 텍스트를 디코딩 | 규칙과 정책 그룹은 추가되지 않음 |
| URI 목록 → Base64 | 줄 단위로 정리한 뒤 전체를 인코딩 | 포장 형식만 바뀌며 호환성은 개선되지 않음 |
| URI 목록 → Clash YAML | 노드를 파싱한 뒤 그룹과 규칙을 추가 | 분할 라우팅 동작은 템플릿에 따라 달라지며 프로토콜 필드가 모두 변환되지 않을 수 있음 |
| 전체 YAML → URI 목록 | 링크로 변환할 수 있는 노드를 내보내기 | 규칙, DNS, TUN, 정책 그룹이 대개 손실됨 |
| 전체 YAML → provider 파일 | 노드를 추출해 provider 형식으로 출력 | 주 설정에서 해당 노드를 참조하는 방법을 별도로 정의해야 함 |
변환 후 다음 필드를 하나씩 확인하세요
- 기본 연결 정보: 서버, 포트, 비밀번호 또는 UUID, 프로토콜 종류. 포트는 원래 값을 유지해야 하며 모든 노드를
443으로 바꾸면 안 됩니다. - 암호화와 TLS: Shadowsocks 암호화 방식, TLS 사용 여부, SNI, ALPN, 인증서 검증 설정을 확인하세요. 테스트를 통과하려고 인증서 검증을 무작정 끄지 마세요.
- 전송 계층: WebSocket 경로와 Host, gRPC의 service name 등을 확인하세요. 주소와 비밀번호가 같아도 전송 계층이 다르면 연결되지 않을 수 있습니다.
- 프로토콜 확장: Reality 공개 키와 short ID, VLESS flow 같은 필드는 변환기와 커널이 모두 지원해야 합니다.
- 이름과 참조: 이름이 중복된 노드를 처리하는 방법을 정하고, 이름을 바꾼 뒤에는 정책 그룹 참조도 갱신하세요. 노드 목록만 바꾸면 존재하지 않는 이름이 남을 수 있습니다.
원본 Clash와 mihomo의 지원 범위는 서로 다릅니다. 대상 커널이 지원하지 않는 프로토콜은 ‘Clash 형식으로 변환’한다고 지원되는 것이 아닙니다. 새 프로토콜을 사용할 때는 구독 변환 템플릿을 계속 바꾸기보다 현재 커널 버전과 해당 필드 문서를 확인하세요.
가져오기 방법: 전체 설정과 노드 provider를 구분하세요
전체 YAML: 설정으로 가져와 활성화
클라이언트에서는 보통 ‘설정’ 또는 ‘Profiles’ 페이지에서 전체 설정을 관리합니다. 메뉴 이름은 클라이언트마다 다르므로 ‘URL에서 설정 가져오기’나 ‘로컬 설정 가져오기’를 선택했는지 확인하세요. ‘노드 추가’를 선택하면 안 됩니다. 가져온 뒤에는 설정을 활성화하고 실행 로그도 확인해야 합니다. 파일이 목록에 표시된다고 현재 설정으로 적용된 것은 아닙니다.
노드만 있는 경우: provider를 사용하거나 신중하게 병합
mihomo 프록시 provider를 사용하면 노드 출처와 주 설정을 분리해 관리할 수 있습니다. 클라이언트 간 호환성을 높이려면 proxies:가 명확히 포함된 YAML provider 파일을 우선 사용하세요. 다른 입력 형식의 지원 여부는 사용 중인 커널 버전에 따라 확인해야 합니다. 아래 예제는 로컬 노드 파일을 참조하고 use를 통해 노드를 정책 그룹에 연결합니다.
proxy-providers:
local-nodes:
type: file
path: ./providers/nodes.yaml
proxy-groups:
- name: "구독 노드"
type: select
use:
- local-nodes
rules:
- MATCH,구독 노드
./providers/nodes.yaml에는 앞서 본 것처럼 proxies: 아래에 노드 목록이 있어야 합니다. 상대 경로의 기준 위치는 커널의 작업 디렉터리와 클라이언트의 관리 방식에 따라 달라지므로 다운로드한 파일이 있는 폴더라고 단정할 수 없습니다. 이 조각을 주 설정에 병합할 때는 기존 설정에 같은 최상위 키나 정책 그룹 이름을 중복 선언하지 마세요.
원격 HTTP provider에는 업데이트 주소와 캐시 경로, 업데이트 간격도 설정해야 합니다. interval: 86400으로 지정하면 단위는 초이므로 24시간마다 업데이트됩니다. 원격 노드 목록 업데이트와 주 설정 업데이트는 별개의 과정입니다. 전자는 노드를 갱신하고, 후자는 규칙과 DNS를 포함한 설정 전체를 덮어쓸 수 있습니다.
가져오기 오류 해결: 응답, 문법, 커널, 실행 순서로 확인
- 응답 내용 확인. 파일을 로컬에 내려받아 처음 몇 줄을 확인하세요. HTTP
200은 요청이 정상적으로 응답했다는 뜻일 뿐 본문이 설정이라는 보장은 없습니다.401,403이면 먼저 인증과 접근 제한을 확인하세요. 일부 서비스는 User-Agent에 따라 다른 형식을 반환하므로 브라우저와 클라이언트에서 받는 내용이 다를 수 있습니다. - 외부 인코딩 확인. Base64라면 한 번 디코딩해 결과를 확인하세요. 무작정 여러 번 디코딩하거나 구독 주소, 웹 페이지 본문, 인코딩된 노드 목록을 한데 섞어 처리하지 마세요.
- YAML 문법 확인. “mapping”, “indentation” 오류는 보통 들여쓰기와 콜론, 따옴표 문제에서 발생합니다. 오류가 난 줄 번호를 확인하고 앞뒤 몇 줄도 살펴보세요. 실제 인증 정보가 포함된 설정을 온라인 YAML 검사기에 붙여 넣는 것은 피하세요.
- 필드 지원 여부 확인. “unsupported proxy type” 오류는 프로토콜과 커널의 지원 범위가 맞지 않을 때 주로 발생합니다. 클라이언트가 실제로 어떤 커널을 실행 중인지 확인한 다음 버전과 지원 목록을 살펴보세요.
- 이름 참조 확인. “proxy not found”와 같은 오류가 나면 노드 이름, 정책 그룹 이름, provider 이름이 일치하는지 확인하세요. 전체 설정에 노드만 있고 사용할 수 있는 정책이 없으면 원하는 분할 라우팅이 적용되지 않을 수도 있습니다.
- 실행 상태 확인. 설정이 성공적으로 로드된 다음 로컬 프록시 포트와 시스템 프록시 또는 TUN이 필요한 대로 활성화됐는지 확인하세요. 가져오기 성공, 프록시 진입점 활성화, 노드 연결은 각각 별도로 확인해야 합니다.
변환 후 ‘노드 속도 측정은 되지만 웹 페이지가 열리지 않는’ 문제가 생겨도 바로 인코딩 탓으로 돌리지는 마세요. 속도 측정은 지정된 테스트 요청만 확인합니다. 실제 접속은 DNS와 라우팅 규칙, UDP 지원, 앱의 프록시 설정에도 영향을 받습니다. 먼저 실패한 연결에 어떤 정책이 적용됐고 어떤 노드가 선택됐는지 확인한 뒤 문제 지점을 좁혀 가세요.
형식 선택 정리: 대상 클라이언트에서 바로 쓸 수 있는 데이터를 우선하세요
- 가져와서 바로 사용하려는 경우: 서비스 제공자가 현재 커널용이라고 명확히 안내한 전체 Clash 또는 mihomo 설정을 우선 선택한 뒤 분할 라우팅과 DNS 설정을 확인하세요.
- 직접 관리하는 규칙이 있는 경우: provider 노드 데이터를 우선 사용해 주 설정을 분리하세요. 그러면 구독 업데이트가 로컬 설정을 덮어쓸 가능성을 줄일 수 있습니다.
- 클라이언트 간 노드를 옮기는 경우: URI 목록은 노드를 하나씩 전달하기 편하지만 프로토콜 확장 필드를 각각 확인해야 합니다. 기존 정책 전체가 함께 전달될 것으로 기대하지 마세요.
- Base64 텍스트를 받은 경우: 먼저 로컬에서 디코딩해 내용을 확인하세요. 인코딩은 포장 방식일 뿐이며 실제 가져오기 방법은 내부 데이터 구조에 따라 결정됩니다.
변환이 꼭 필요하다면 로컬에서 실행되는 도구나 직접 관리하는 서비스를 우선 사용하세요. 원격 변환 서비스는 구독 인증 정보나 노드 정보를 접할 수 있고, 결과에 추가 규칙이나 설정이 들어갈 수도 있습니다. 원본과 변환 결과, 정상 작동하는 백업을 보관하고 ‘구조 확인 → 필드 대조 → 활성화 및 테스트’ 순서로 진행하면 문제가 생겼을 때 되돌릴 기준이 분명해집니다.