구독 형식 가이드: base64·기본 JSON·공유 링크 상호 변환 방법

구독 주소를 열면 알 수 없는 문자열이 나오고, vmess 링크를 가져오면 노드 이름이 물음표로 바뀌며, JSON을 직접 쓰다 필드 하나만 빠져도 연결되지 않습니다. 세 형식의 경계가 어디인지, 변환 중 어느 단계에서 필드가 가장 잘 빠지는지 이 글에서 필드 단위로 하나씩 대조합니다.

이 글 한눈에 보기

base64 구독, 기본 JSON 설정, vmess·vless 공유 링크 세 형식을 나눠 대조하고 '구독 → 링크 목록 → 단일 노드 필드 → 기본 JSON' 전체 변환 경로와 변환 중 가장 잘 유실되는 필드를 정리합니다. 이미 노드에 연결된 상태에서 설정을 직접 수정하거나 클라이언트를 옮겨야 하는 독자에게 적합합니다.

세 형식은 각각 무엇인가

같은 노드 정보라도 어떤 그릇에 담느냐에 따라 모습이 완전히 달라집니다. base64 구독은 일괄 목록, 기본 JSON은 전체 설정, 공유 링크는 단일 레코드입니다.

세 형식의 정보량은 서로 같지 않습니다. 구독에 들어 있는 링크 한 줄은 보통 아웃바운드(outbound) 하나만 설명하지만, 기본 JSON은 인바운드, 라우팅, DNS, 로그 같은 클라이언트 측 설정까지 함께 담습니다. 이 차이를 헷갈리는 것이 이후 모든 변환 문제의 출발점입니다.

항목base64 구독기본 JSON공유 링크
담는 내용여러 줄의 공유 링크아웃바운드·인바운드·라우팅을 포함한 전체 설정단일 노드의 연결 파라미터
자동 업데이트클라이언트가 주기적으로 가져옴파일 직접 교체미지원
주요 출처패널 일괄 내보내기서버 설정 파일 또는 직접 작성클라이언트·패널에서 한 줄씩 복사
적합한 상황여러 기기에서 노드 목록 하나를 공유세밀한 분할 라우팅과 고정 로컬 포트임시 가져오기, 클라이언트 간 이동
1회
구독 전체 디코딩 횟수
2계층
vmess 노드 총 디코딩 계층 수
443
TLS와 Reality에서 자주 쓰는 포트
0
VMess alterId 기본값

base64 구독의 인코딩 규칙

base64 구독은 인코딩이 한 겹 더 붙는 구조입니다. 서버가 여러 줄의 공유 링크를 하나의 일반 텍스트로 합친 뒤 전체를 한 번 base64로 인코딩해 HTTP 응답으로 돌려줍니다. 클라이언트는 받아온 뒤 먼저 디코딩해서 한 줄에 링크 하나씩 있는 목록을 얻습니다.

디코딩에 실패하면 클라이언트는 평문으로 간주해 처리하므로, 같은 파싱 로직으로 base64 구독과 평문 구독을 모두 소화할 수 있습니다. 직접 디코딩할 때는 아래 명령 하나만 기억하면 됩니다.

# 구독이 반환한 원문을 sub.txt로 저장한 뒤 전체를 한 번 디코딩
base64 -d sub.txt > nodes.txt    # GNU coreutils
base64 -D sub.txt > nodes.txt    # macOS / BSD

wc -l nodes.txt                  # 줄 수는 보통 노드 개수와 같음
head -n 2 nodes.txt

디코딩 결과에서 각 줄 맨 앞이 바로 프로토콜 접두사이며, 흔한 것은 vmess://vless://입니다. 한 구독 안에 여러 접두사가 섞여 있어도 정상이며, 클라이언트는 줄 단위로 하나씩 파싱합니다.

풀어낸 첫 줄이 vmess://vless://도 아니라면 원문이 이미 평문 구독이라는 뜻이므로 더 디코딩할 필요가 없습니다.

공유 링크의 필드 구조

vmess와 vless의 차이는 인코딩 방식에 있습니다. vmess 링크는 'JSON을 base64로 한 겹 감싼' 형태이고, vless 링크는 'URI에 쿼리 파라미터를 붙인' 형태입니다. 앞쪽은 풀어낸 필드 이름이 전부 약어이고, 뒤쪽은 주소창에서 바로 읽을 수 있습니다.

vmess:// 뒤의 base64 전체를 한 번 디코딩하면 아래 객체가 나옵니다:

{
  "v": "2",              // 링크 형식 버전, 항상 2
  "ps": "홍콩-01",      // 비고, 가져오면 노드 이름이 됨
  "add": "example.com", // 서버 주소
  "port": "443",        // 포트, 여기서는 문자열
  "id": "b831381d-6324-4d53-ad4f-8cda48b30811",
  "aid": "0",           // alterId, VMess에만 있음
  "scy": "auto",        // 암호화 방식
  "net": "ws",          // 전송 계층
  "type": "none",       // 위장 유형
  "host": "example.com", // WS의 Host 헤더
  "path": "/ws",       // WS 경로
  "tls": "tls"          // TLS 사용 여부
}

vless 링크에는 내부 base64가 없고, 모든 파라미터가 ? 뒤의 쿼리 문자열에 들어가며 # 뒤는 비고입니다. 파라미터 이름이 vmess의 약어보다 직관적이지만 URI 규칙에 맞춰 URL 인코딩을 해야 합니다.

vless://[email protected]:443?encryption=none&security=reality&sni=www.example.com&fp=chrome&pbk=UuMBgl8KtNqHqY7p&sid=0123abcd&flow=xtls-rprx-vision&type=tcp#홍콩-01

두 링크는 같은 내용을 설명할 뿐 필드 이름과 배치만 다릅니다. 아래 네 개 카드에서 자주 쓰는 필드, 기본 JSON의 최상위 구조, 로컬 포트 관례를 한데 모아 대조합니다.

vmess 링크 필드

add / port
주소와 포트, port는 문자열
id / aid
UUID와 alterId
scy
암호화 방식, 보통 auto 또는 none
net / type
전송 계층과 위장 유형
path / host
WS 경로와 Host 헤더

전체가 base64(JSON)이므로 한 번만 풀면 읽을 수 있습니다.

vless 링크 파라미터

encryption
고정값 none, 생략 불가
security
none / tls / reality
sni
TLS 인증서 도메인
flow
Reality 노드는 xtls-rprx-vision 입력
pbk / sid
Reality 공개키와 short ID

파라미터는 쿼리 문자열에 들어가며 URL 인코딩에 주의합니다.

기본 JSON 최상위

inbounds
로컬 수신, 예: SOCKS 10808
outbounds
아웃바운드 노드, tag와 streamSettings 포함
routing
분할 라우팅 규칙, outboundTag로 아웃바운드 지정
dns
질의 방식과 업스트림 서버
log
로그 레벨, 문제 확인 시 debug

필드 이름은 대소문자를 구분하고, port는 반드시 숫자여야 합니다.

로컬 포트 관례

SOCKS
10808
HTTP
10809
로그 레벨
warning / debug
아웃바운드 tag
proxy, direct, block 세 가지 흔한 이름

포트와 tag는 로컬 설정이 정하며 구독과는 무관합니다.

세 형식은 서로 어떻게 변환할까

변환 경로는 네 단계로 고정됩니다. 구독에서 링크 목록을 풀고, 링크를 필드로 되돌리고, 필드를 다시 기본 JSON으로 조립합니다. 반대 방향으로 가면 내보내기가 됩니다.

  1. 구독 원문 꺼내기

    브라우저에서 구독 주소를 열고 응답 내용 전체를 sub.txt로 저장합니다. 응답은 base64 한 덩어리일 수도 있고 평문 링크 목록일 수도 있습니다.

  2. 링크 목록 풀어내기

    base64 -d sub.txt > nodes.txt를 실행하면 한 줄에 링크 하나씩 있는 공유 링크 목록이 나옵니다. 프로토콜 접두사는 줄 맨 앞에, 비고는 줄 끝 # 뒤에 있습니다.

  3. 단일 노드 복원하기

    vmess는 vmess:// 뒤 내용을 base64로 한 번 더 풀어 JSON을 얻고, vless는 ? 뒤의 쿼리 파라미터를 그대로 읽으면 되므로 추가 디코딩이 필요 없습니다.

  4. 기본 JSON으로 조립하기

    필드를 outboundsvnextstreamSettings에 채워 넣습니다. port는 숫자로 바꾸고, tag는 직접 이름을 정하고, address에는 프로토콜 접두사를 붙이지 않습니다.

네 번째 단계에서 조립한 아웃바운드는 대략 이런 모습이며, 필드는 위의 vless 링크와 하나씩 대응합니다:

{
  "outbounds": [{
    "tag": "proxy",
    "protocol": "vless",
    "settings": {
      "vnext": [{
        "address": "example.com",
        "port": 443,
        "users": [{
          "id": "b831381d-6324-4d53-ad4f-8cda48b30811",
          "encryption": "none",
          "flow": "xtls-rprx-vision"
        }]
      }]
    },
    "streamSettings": {
      "network": "tcp",
      "security": "reality",
      "realitySettings": {
        "serverName": "www.example.com",
        "publicKey": "UuMBgl8KtNqHqY7p",
        "shortId": "0123abcd",
        "fingerprint": "chrome"
      }
    }
  }] // 아웃바운드 배열
}

역방향 변환도 같습니다. 기본 JSON의 settings.vnext[0]streamSettings는 링크 파라미터를 펼쳐 놓은 형태이므로, address, port, id를 꺼내 프로토콜 규칙에 맞춰 다시 URI로 인코딩하면 됩니다. VMess는 alterIdaid로 되돌려 써야 합니다.

클라이언트에는 더 간편한 경로도 두 가지 있습니다. v2rayN은 '사용자 지정 설정' 유형의 서버를 지원하므로 완성된 JSON을 설정 상자에 붙여 넣으면 코어가 그대로 읽고, 클라이언트가 아웃바운드를 조립하지 않습니다. 반대로 구독 목록에서 단일 노드의 공유 링크를 복사해 다른 기기의 v2rayNG에 붙여 넣고 '⋮' → '클립보드에서 설정 가져오기'를 쓰면 됩니다.

변환할 때 가장 잘 빠지는 필드

필드가 빠지는 일은 거의 모두 수작업으로 옮기는 단계에서 생깁니다. 복사·붙여넣기 중 잘리거나, 문자열과 숫자를 혼용하거나, 약어에서 글자 하나를 놓치는 경우입니다. 아래 항목을 하나씩 대조하면 '가져오기는 됐는데 연결이 안 되는' 상황 대부분을 잡아낼 수 있습니다.

주의

기본 JSON을 직접 고칠 때는 저장 전에 편집기에서 JSON 문법 검사를 한 번 돌리세요. 후행 쉼표와 빠진 따옴표가 가장 흔한 두 가지 오류입니다. 문제를 찾는 단계에서는 log.logleveldebug로 두어 코어가 오류 필드를 로그에 남기게 하고, 원인을 찾은 뒤 warning으로 되돌립니다.

어떤 상황에 무엇을 쓸까

세 형식에 우열은 없고 역할만 다릅니다. 판단 기준은 두 가지뿐입니다. 노드 목록이 바뀌는지, 그리고 이 기기에 분할 라우팅 규칙이 필요한지.

선택 기준: 노드가 바뀌는지, 로컬 분할 라우팅이 필요한지

base64 구독
  • 주소 하나로 모든 노드 관리
  • 기기를 바꿔도 한 번만 입력하면 목록이 자동 동기화
  • 노드 추가·삭제는 서버가 결정하므로 로컬에서는 수정 불필요
  • 여러 기기를 쓰고 노드가 조정되는 상황에 적합
기본 JSON
  • routing 분할 규칙과 DNS 정책 작성 가능
  • 로컬 SOCKS 10808, HTTP 10809 포트 고정
  • 노드가 바뀌면 파일을 직접 교체해야 함
  • 단일 기기에서 세밀한 제어가 필요한 상황에 적합

둘은 함께 쓸 수 있습니다. 구독은 노드 목록을, 기본 JSON의 routing은 어떤 트래픽을 프록시로 보낼지를 담당합니다.

공유 링크는 그 중간에 있습니다. 구독보다 임시 가져오기에 적합하고, 기본 JSON보다 클라이언트 간 복사에 적합합니다. 같은 링크를 v2rayN과 v2rayNG에 붙여 넣어도 나오는 아웃바운드 파라미터는 같고, 차이는 로컬 포트와 분할 라우팅 규칙을 각 클라이언트가 자기 설정에 둔다는 점뿐입니다.

실제로 더 흔한 조합은 서버에서 구독 주소 하나를 관리하고, 클라이언트에 로컬 라우팅 규칙을 한 벌 더 두는 방식입니다. 노드는 구독을 따라 갱신되고 분할 라우팅 로직은 로컬에 남아 서로 간섭하지 않습니다.

자주 묻는 질문

구독 주소를 브라우저에서 열면 알 수 없는 문자열이 나오나요?

그것은 오류가 아니라 base64 원문입니다. 전체를 복사해 한 번 디코딩하거나, 주소를 클라이언트의 구독 설정에 넣고 업데이트하면 됩니다.

vmess 링크를 가져오면 노드 이름이 물음표로 바뀌나요?

ps 필드는 UTF-8로 인코딩된 비ASCII 문자인데, 디코딩 도구가 GBK로 처리하면 깨집니다. UTF-8로 다시 디코딩한 뒤 가져오세요.

vless 링크를 가져오면 flow가 없다는 오류가 뜨나요?

Reality 노드는 flowxtls-rprx-vision을 넣고, pbk, sid, fp 세 파라미터도 함께 채워야 합니다.

직접 작성한 JSON이 유효하지 않은 설정으로 판정되나요?

먼저 후행 쉼표와 따옴표를 확인하고, 다음으로 port를 문자열에서 숫자로 바꾸고, 마지막으로 routing.rules[].outboundTag와 아웃바운드 tag가 일치하는지 대조합니다.

세 형식의 변환 관계는 복잡하지 않습니다. 구독을 한 겹 풀면 링크가 나오고, vmess 링크를 한 겹 더 풀면 필드가 나오며, 필드를 펼치면 기본 JSON이 됩니다. 시간이 오래 걸리는 쪽은 디코딩이 아니라 필드를 하나도 빠뜨리지 않고 제자리에 옮기는 일입니다.

v2rayN / v2rayNG 다운로드

Windows, macOS, Linux 데스크톱 버전과 안드로이드 버전은 다운로드 페이지에서 받을 수 있고, 구독 가져오기와 분할 라우팅 설정은 튜토리얼에서 확인할 수 있습니다.

클라이언트 다운로드