Clash 멀티 디바이스 설정 동기화: 구독 링크·호스팅 설정·수동 내보내기 3가지 방법
PC·스마트폰·태블릿에서 Clash 설정을 똑같이 유지하는 방법을 비교합니다. 구독 링크 자동 동기화, 자체 호스팅, 수동 내보내기·가져오기의 적용 환경과 유지 비용, 충돌 해결법을 정리했습니다.
먼저 동기화할 대상부터 구분하기
여러 기기에서 '설정이 서로 맞지 않는' 문제는 대부분 클라이언트 문제가 아니라, 성격이 다른 여러 데이터를 한데 묶어 관리한 데서 비롯됩니다. 저장 위치와 갱신 방식, 자동 동기화 가능 여부가 각각 다르므로 먼저 구분한 뒤 방법을 논하는 게 좋습니다.
| 데이터 | 저장 위치 | 자동 동기화 가능 여부 |
|---|---|---|
| 구독 링크 | 각 클라이언트의 설정 보관함 | 아니요, 기기마다 한 번씩 입력 |
설정 본체 config.yaml | 클라이언트 설정 디렉터리 또는 호스팅 URL | 예, 구독을 가져올 때 전체 교체 |
| 노드 및 규칙 세트 providers | ./providers, ./ruleset 캐시 | 예, interval에 따라 정기적으로 가져옴 |
| 현재 선택된 노드, 실행 모드 | 클라이언트 실행 상태 | 아니요, 기기마다 독립적 |
실제로 통일해야 하는 것은 설정 본체와 providers 캐시입니다. 전자는 포트, DNS, TUN, 규칙을 결정하고 후자는 노드 목록을 결정합니다. 어떤 노드가 선택되어 있는지, mode가 rule인지 global인지는 기기별로 따로 설정하는 것이 자연스러우므로 억지로 맞출 필요가 없습니다.
흔한 오해: 구독이 같다고 설정도 같은 것은 아니다
구독은 노드 출처만 결정합니다. mixed-port, dns, tun, rules 같은 필드는 각 클라이언트가 로컬에서 관리하므로, 구독을 바꿔도 포트가 동기화되지 않고 로컬 규칙도 동기화되지 않습니다. 따라서 '세 기기에 같은 링크를 입력했다'와 '세 기기가 동일하게 동작한다'는 서로 다른 문제이며, 후자는 아래 방법으로 보장해야 합니다.
방법 1: 구독 링크 자동 동기화
세 기기에 같은 구독 주소를 입력하면 클라이언트가 정해진 간격으로 자동으로 가져옵니다. 데스크톱, Android, iOS 모두 지원하는 가장 폭넓은 방식이며 유지 비용도 가장 낮습니다.
'구독' → '새로 만들기'에서 구독 주소를 붙여넣고 저장합니다. 아직 프록시를 켜지 마세요.
구독 카드를 마우스 오른쪽 버튼으로 클릭 → '편집'에서 자동 업데이트 간격을 기본 1440분에서 360~720분으로 바꿉니다.
구독 카드를 마우스 오른쪽 버튼으로 클릭 → '업데이트'로 설정 이름 하나만 남지 않고 전체 노드 목록이 제대로 나오는지 확인합니다.
'설정' → '시스템 프록시'를 필요에 따라 켜고, TUN 모드는 '설정' → 'TUN 모드'에서 따로 켭니다. 모바일은 클라이언트의 VPN 서비스가 처리하므로 추가 설정이 필요 없습니다.
Android는 '프로필' 목록에서 프로필을 길게 눌러 업데이트 메뉴를 확인하고, iOS는 프로필 상세 페이지에서 아래로 당겨 새로 고칩니다.
rules, mixed-port, dns 섹션이 있으면 업데이트 후 해당 필드가 구독 값으로 덮어써집니다. 자체 규칙을 구독 설정에 직접 넣는 것이 '업데이트할 때마다 사라지는' 가장 흔한 원인입니다.
포트가 덮어써진 뒤 나타나는 증상
구독이 mixed-port를 7890에서 7891로 바꾸면 시스템 프록시와 브라우저 확장에 하드코딩된 7890은 여전히 예전 포트를 가리킵니다. 이때 클라이언트는 연결됨으로 표시되지만 웹페이지가 전혀 열리지 않습니다. external-controller 패널(기본 수신 127.0.0.1:9090)을 열어 실제 적용된 포트를 확인하세요.
# 현재 적용 중인 포트, 모드, DNS 설정 확인
curl -s http://127.0.0.1:9090/configs
명령줄이 불편하면 데스크톱 클라이언트 '설정' 페이지에 표시되는 포트를 브라우저 확장의 값과 비교하면 됩니다.
적용 범위
- 적합: 기기 1~3대, 규칙을 구독에 그대로 따르며 추가 파일을 관리하고 싶지 않은 경우.
- 부적합: 자체 규칙이 있거나, 기기별로 포트를 다르게 쓰거나, 구독 구조를 자주 바꾸는 경우.
방법 2: 자체 호스팅 설정으로 YAML 하나로 모든 기기 관리
설정 본체를 직접 다운로드할 수 있는 주소(프라이빗 오브젝트 스토리지, 자체 nginx, 프라이빗 저장소의 raw 링크 등)에 올리고, 각 기기에서 이 주소를 구독처럼 가져옵니다. 이후 규칙을 바꿀 때는 이 파일 하나만 수정하면 각 기기가 다음번 가져올 때 자동으로 반영됩니다.
노드 출처와 규칙 분리하기
노드를 proxies에 직접 쓰지 말고 proxy-providers로 커널이 직접 가져오게 하세요. 포트, DNS, 규칙처럼 사용자 고유의 부분은 모두 base config에 작성합니다.
mixed-port: 7890
allow-lan: false
mode: rule
log-level: warning
external-controller: 127.0.0.1:9090
unified-delay: true
tcp-concurrent: true
proxy-providers:
airport-a:
type: http
url: "https://sub.example.com/api/v1/client/subscribe?token=9f2c1a7b4e"
interval: 3600
path: ./providers/airport-a.yaml
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
timeout: 3000
rule-providers:
reject:
type: http
behavior: domain
format: mrs
url: "https://example.com/rules/reject.mrs"
path: ./ruleset/reject.mrs
interval: 86400
dns:
enable: true
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
nameserver:
- https://223.5.5.5/dns-query
fallback:
- https://1.1.1.1/dns-query
두 interval의 단위는 모두 초입니다. 3600은 한 시간마다 노드를 가져오고, 86400은 하루에 한 번 규칙 세트를 가져옵니다. 노드 변동이 잦으면 전자를 1800으로 줄이고, 규칙 세트는 더 자주 가져올 필요가 없습니다.
format: mrs는 mihomo 1.18.0 이상이 필요하고, 구버전에서는 format: yaml과 behavior: domain 조합을 사용합니다. 또한 호스팅 주소는 직접 다운로드가 가능해야 합니다. 프록시를 거쳐야 접근할 수 있는 곳에 두면 첫 실행 시 설정을 가져오지 못해 노드 목록이 비어 있게 됩니다.
배포 전에 로컬에서 문법 검사하기
# 설정 검사만 수행하고 프록시는 시작하지 않음
mihomo -t -d /etc/mihomo -f config.yaml
검사를 통과한 뒤 호스팅 주소에 올립니다. 각 기기에서 호스팅 URL을 가져오면 노드는 providers가 정기적으로 가져오고, 규칙을 바꿀 때는 각 기기에서 설정만 다시 가져오면 되므로 기기마다 수정할 필요가 없습니다.
필드와 커널 버전 대응 관계
| 필드 | 사용 가능 버전 | 역할 |
|---|---|---|
format: mrs | mihomo 1.18.0부터 | 규칙 세트 바이너리 형식, 용량이 더 작고 로딩이 빠름 |
tcp-concurrent | mihomo 1.16부터 | 동시 연결 수립으로 핸드셰이크 대기 감소 |
unified-delay | mihomo 1.16부터 | 프로토콜별 지연 측정 기준 통일 |
geodata-mode | mihomo 1.16부터 | 내장 GEO 데이터 사용 방식 선택 |
방법 3: 수동 내보내기·가져오기
오프라인 기기나 라우터, 임시 디버깅 때만 쓸 만합니다. 설정 본체를 내보내고 providers/, ruleset/ 캐시 디렉터리까지 함께 복사해야 하며, 캐시 디렉터리가 빠지면 헛수고가 됩니다.
데스크톱 클라이언트는 '설정'에서 '설정 디렉터리 열기'를 클릭하고, mihomo 명령줄 버전은 보통 /etc/mihomo/config.yaml 또는 ~/.config/mihomo/config.yaml에 있습니다.
config.yaml만 복사하면 첫 실행 시 providers 캐시가 없어 노드 목록이 비어 있게 표시됩니다.
예: config-20260830.yaml. 클라이언트에 같은 이름의 설정이 여러 개 쌓여 서로 덮어쓰는 것을 막을 수 있습니다.
iOS는 먼저 '파일' 앱이나 클라우드 드라이브로 YAML을 기기에 저장한 뒤 클라이언트에서 '설정 가져오기'를 선택합니다.
'프록시' 페이지의 노드 수와 '규칙' 페이지의 항목 수가 원본 기기와 일치해야 가져오기에 성공한 것입니다.
다음과 같은 경우에는 사실상 수동 방식만 쓸 수 있습니다:
- 대상 기기에서 호스팅 주소에 접근할 수 없는 경우(내부망, 오프라인 환경 등).
- 규칙 하나나 DNS 설정 한 묶음만 임시로 검증하고 싶고 호스팅 파일은 건드리고 싶지 않은 경우.
- 라우터 같은 임베디드 환경이라 USB나 SCP로만 파일을 넣을 수 있는 경우.
충돌 처리: 변경 사항을 계층으로 나누기
세 가지 방법을 섞어 쓰면 충돌은 대부분 같은 원인에서 발생합니다. 바로 같은 필드를 두 곳에서 수정하는 것입니다. 해결책은 변경을 계층으로 나누는 것입니다. 구독이나 호스팅 파일에는 공통 부분만 넣고, 기기별 차이는 병합 계층에 둡니다.
병합 계층에는 차이만 작성
# Merge 설정: config.yaml 전체를 복사하지 않고 수정할 부분만 작성
prepend-rules:
- DOMAIN-SUFFIX,intranet.example.com,DIRECT
prepend-proxy-groups:
- name: 수동 선택
type: select
proxies: [자동 선택, DIRECT]
규칙은 prepend-rules로 맨 앞에 삽입해 구독에 포함된 규칙보다 우선순위를 높이고, 프록시 그룹은 prepend-proxy-groups로 목록 맨 위에 두어 인터페이스에서 바로 선택할 수 있게 합니다. 구독을 업데이트해도 병합 계층의 내용은 덮어써지지 않으며, 이것이 '구독 설정을 직접 수정하는 것'보다 안정적인 이유입니다.
일관성 점검 목록
| 점검 항목 | 위치 | 기대 결과 |
|---|---|---|
| 적용 포트 | '설정' → '포트' 또는 GET /configs | 모든 기기에서 7890으로 동일 |
| 노드 수 | '프록시' 페이지 | 같은 provider에서 가져온 노드 수가 일치 |
| 규칙 수 | '규칙' 페이지 | 호스팅 파일의 rules 항목 수와 일치 |
| provider 업데이트 시간 | GET /providers/proxies | interval 이내 |
| 실행 모드 | 트레이 메뉴 또는 홈 화면 | 평소에는 rule 유지, 문제 해결 시에만 global로 전환 |
# provider의 최근 가져오기 시간과 노드 수 확인
curl -s http://127.0.0.1:9090/providers/proxies
한 가지 경험 규칙: 같은 필드는 한 곳에서만 정의합니다. 포트, DNS, TUN은 base config에, 노드 출처는 proxy-providers에, 기기별 차이는 병합 계층에 작성하고, 선택된 노드와 실행 모드는 각 기기가 스스로 관리하게 둡니다. 이렇게 하면 세 기기 사이의 차이는 '현재 어떤 노드를 선택했는가'만 남습니다.
LAN 환경에서 주의할 두 가지
external-controller는 기본적으로127.0.0.1만 수신하므로 다른 기기에서 패널에 접근하려면0.0.0.0:9090으로 명시적으로 바꾸고secret을 설정해야 합니다.- 여러 기기에서 동시에
allow-lan을 켜도 서로 충돌하지 않습니다. 다만 다른 기기가 올바른 기기 IP를 가리켜야 하며 포트는 7890을 유지하면 됩니다.
세 가지 방법 선택 기준
| 방법 | 적용 환경 | 유지 비용 | 충돌 처리 |
|---|---|---|---|
| 구독 링크 자동 동기화 | 기기 1~3대, 규칙이 구독을 따름 | 낮음 | 각자 덮어쓰기, 로컬 변경 사항 소실 |
| 자체 호스팅 설정 | 3대 이상, 자체 규칙 보유 | 보통 | 병합 계층 분리, 충돌 예측 가능 |
| 수동 내보내기·가져오기 | 오프라인 기기, 라우터, 임시 디버깅 | 높음 | 전체 덮어쓰기, 수동 확인 필요 |
가장 흔한 조합은 메인 기기는 호스팅 URL과 병합 계층을 쓰고, 스마트폰과 예비 기기는 구독 링크를 직접 입력하며, 라우터처럼 네트워크로 업데이트하기 어려운 기기는 파일을 수동으로 넣는 방식입니다. 세 가지가 공존해도 같은 필드를 한 곳에서만 정의하면 서로 충돌하지 않습니다.
자주 묻는 질문
스마트폰과 PC에 같은 구독을 입력했는데 노드 수가 다릅니다
&flag=clash 같은 파라미터가 빠지면 결과가 달라집니다.구독을 업데이트하면 로컬 규칙이 사라집니다. 어떻게 유지하나요?
prepend-rules에 넣고, 병합 체인을 지원하지 않는 클라이언트는 자체 호스팅 URL로 바꿔 base config의 rules 섹션에 규칙을 작성합니다.같은 설정이 macOS에서는 정상인데 Android에서는 실행하자마자 오류가 납니다
tun, redir-port, tproxy-port는 데스크톱과 Linux 쪽 표기이며 Android는 클라이언트 자체 VPN 서비스가 처리합니다. 또한 external-controller를 0.0.0.0:9090으로 쓰면서 secret을 설정하지 않으면 일부 클라이언트는 아예 실행을 거부합니다. 이런 필드를 base config에서 빼서 각 플랫폼의 병합 계층에 넣으면 됩니다.여러 기기에서 동시에 TUN 모드를 켜면 충돌하나요?
allow-lan을 켰다면 다른 기기가 올바른 기기 IP를 가리키도록 주의하세요. 패널 포트는 기본적으로 로컬만 수신하므로 기기 간 접근하려면 명시적으로 열고 secret을 설정해야 합니다.