V2Ray 구독 형식 비교: Base64 구독, 네이티브 JSON, vmess:// 공유 링크 변환 가이드

Base64 구독을 디코딩하고 vmess:// 링크를 네이티브 JSON으로 변환하는 방법과, 각 클라이언트가 지원하는 형식을 알아봅니다.

이 글의 핵심

Base64는 인코딩 방식, 구독은 노드 목록을 가져오는 방법, 네이티브 JSON은 코어 실행 설정입니다. 서로 같은 종류의 형식이 아닙니다. 구독을 열었지만 가져오지 못하거나, 디코딩했는데도 문자열만 보이거나, 공유 링크를 설정 파일로 사용할 수 없는 경우에 유용한 안내입니다. 구독 응답, 개별 링크, 코어 설정 필드를 차례로 확인하면 디코딩, 가져오기, 설정 보완 중 무엇이 필요한지 판단할 수 있습니다.

세 가지 형식부터 구분하기: 구독 주소는 노드 설정이 아닙니다

결론: 먼저 받은 내용을 확인한 뒤 가져오기 방법을 선택하세요. https://로 시작하는 구독 주소는 노드 목록을 가져오는 경로일 뿐입니다. 클라이언트가 받는 형식은 응답 본문에 따라 Base64로 인코딩된 노드 목록, 일반 텍스트 공유 링크 또는 다른 구조일 수 있습니다. 주소 자체를 Base64로 디코딩해도 서버 설정은 나오지 않습니다.

구독 주소와 노드 목록

권장

흔히 여러 공유 링크를 줄바꿈으로 나열한 뒤 전체를 Base64로 인코딩해 응답합니다. 클라이언트는 구독 주소를 저장하고 업데이트할 때마다 노드 목록을 다시 가져옵니다. 노드 목록을 지속적으로 관리하기에 편리하지만, 모든 서비스가 이 응답 형식을 사용하는 것은 아닙니다.

적합한 경우: 유효한 구독 주소를 제공받아 노드를 계속 업데이트해야 할 때

vmess:// 공유 링크

이 글에서는 일반적인 v2 공유 형식을 다룹니다. 접두사 뒤에는 Base64로 인코딩된 노드 JSON이 들어 있습니다. VMess 아웃바운드 하나에 필요한 정보를 주로 담으며, 로컬 리스너, DNS, 라우팅 정책까지 포함하는 완전한 설정은 아닙니다.

적합한 경우: 단일 노드 이전, 클립보드 가져오기, QR 코드 전달

코어 네이티브 JSON

일반적으로 inbounds, outbounds가 포함되며 dns와 routing도 설정할 수 있습니다. 구조와 지원 필드는 코어 및 버전에 따라 다르므로 파일 확장자만으로 호환 여부를 판단할 수 없습니다.

적합한 경우: 사용자 지정 인바운드와 라우팅 규칙을 설정하거나 코어를 지정해 설정을 관리할 때

Base64는 정보를 보호하지 않습니다. 구독 주소의 액세스 토큰, 노드 UUID, 공유 QR 코드에는 연결 권한을 부여하는 정보가 들어 있을 수 있습니다. 문제를 확인할 때는 로컬 편집기를 사용하고 실제 내용을 온라인 디코딩 사이트에 붙여 넣지 마세요. 다른 사람에게 로그를 전달하기 전에도 이러한 식별 정보를 제거해야 합니다.

Base64 구독 디코딩: 바깥쪽 목록과 안쪽 노드를 따로 처리하기

흔히 사용하는 2단계 구조에서는 바깥쪽 Base64를 디코딩해 여러 vmess:// 링크를 얻습니다. 그중 하나를 골라 접두사를 제거하고 다시 디코딩해야 노드 JSON이 나옵니다. 입력에 무조건 두 번 디코딩을 적용해서는 안 됩니다. 구독 본문이 이미 공유 링크로 시작한다면 바깥쪽 디코딩은 필요하지 않습니다.

  1. 응답 본문 확인

    로컬 도구로 구독 응답 내용을 확인하세요. 로그인 페이지, CAPTCHA 또는 오류 페이지가 표시된다면 먼저 접근 문제를 해결해야 합니다. HTML 페이지는 노드 목록이 아니므로 요청이 성공했더라도 구독을 사용할 수 있다는 뜻은 아닙니다.

  2. 바깥쪽 형식 확인

    본문에 vmess:// 또는 vless://가 바로 보이면 줄 단위로 읽습니다. 연속된 인코딩 문자열이라면 Base64 디코딩을 시도하고, { 또는 [로 시작하는 내용은 먼저 JSON인지 확인합니다.

  3. 노드별 줄 분리

    디코딩한 결과를 줄바꿈 기준으로 나누고 각 줄 앞뒤의 공백을 제거한 뒤 빈 줄을 걸러냅니다. 여러 링크를 하나로 합치거나 링크 안의 문자를 바꾸지 마세요.

  4. 개별 링크 파싱

    여기서 설명하는 VMess v2 형식은 vmess://를 제거한 뒤 디코딩해 JSON으로 파싱합니다. 내용이 이 구조와 다르면 필드를 억지로 맞추지 말고 공유 형식의 출처를 확인하세요.

아래 함수는 로컬 브라우저 콘솔에서 사용할 수 있습니다. 표준 Base64와 흔히 사용하는 URL 안전 문자를 지원하고, 생략된 끝부분 패딩을 보완하며, UTF-8을 기준으로 한글 메모를 복원합니다. 실행하기 전에 코드를 먼저 읽어 보세요. 네트워크 요청을 보내거나 클립보드를 자동으로 읽지 않습니다.

function decodeBase64Utf8(input) {
  let value = input.trim().replace(/\s+/g, "");
  value = value.replace(/-/g, "+").replace(/_/g, "/");

  if (!/^[A-Za-z0-9+/]*={0,2}$/.test(value)) {
    throw new Error("Base64가 아닌 문자가 포함되어 있습니다");
  }

  value = value.replace(/=+$/, "");
  if (value.length % 4 === 1) {
    throw new Error("Base64 길이가 올바르지 않습니다");
  }

  value += "=".repeat((4 - value.length % 4) % 4);
  const binary = atob(value);
  const bytes = Uint8Array.from(binary, char => char.charCodeAt(0));
  return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
}

function readSubscription(body) {
  const text = body.trim();
  const decoded = /^(vmess|vless):\/\//i.test(text)
    ? text
    : decodeBase64Utf8(text);

  return decoded.split(/\r?\n/)
    .map(line => line.trim())
    .filter(Boolean);
}

function readVmess(link) {
  const value = link.trim();
  if (!value.startsWith("vmess://")) {
    throw new Error("vmess:// 링크가 필요합니다");
  }
  return JSON.parse(decodeBase64Utf8(value.slice(8)));
}

readSubscription은 일반 텍스트 링크 목록 또는 그 Base64 인코딩이라는 한 가지 구독 형식만 보여 주는 예시이며, 모든 형식을 처리하는 파서는 아닙니다. 다른 구조라면 작업을 중단하고 서비스 제공자가 안내한 형식을 확인하세요. Base64 디코딩에 성공해도 인코딩된 내용을 읽을 수 있다는 뜻일 뿐, 노드가 유효하거나 계정에 여전히 권한이 있다는 뜻은 아닙니다.

vmess:// 링크 분석: 공유 필드를 네이티브 설정에 매핑하기

다음은 구조를 설명하기 위한 VMess v2 노드 객체입니다. example.com은 문서 예시용 도메인이며 UUID도 예시일 뿐이므로 프록시 서버 연결에 사용할 수 없습니다. 필드 v의 값 "2"는 공유 형식의 버전이지 클라이언트나 코어 버전이 아닙니다.

{
  "v": "2",
  "ps": "문서 예시",
  "add": "example.com",
  "port": "443",
  "id": "00000000-0000-4000-8000-000000000001",
  "aid": "0",
  "scy": "auto",
  "net": "ws",
  "type": "none",
  "host": "example.com",
  "path": "/ws",
  "tls": "tls",
  "sni": "example.com"
}
공유 필드네이티브 아웃바운드 위치변환 시 확인 사항
add、portsettings.vnext[].address、port주소는 문자열이고 네이티브 설정의 포트는 숫자입니다.
id、aidsettings.vnext[].users[].id、alterId이 예시에서 aid는 0이며 최신 VMess AEAD 방식에 해당합니다.
scysettings.vnext[].users[].securityVMess 사용자 암호화 설정이며 TLS 사용 여부를 나타내는 스위치가 아닙니다.
netstreamSettings.network이 예시의 전송 방식은 ws입니다. 전송 방식이 다르면 필드 하나만 바꿔서는 안 됩니다.
host、pathwsSettings.headers.Host、wsSettings.path여기서는 WebSocket으로 해석합니다. 경로의 쿼리 매개변수도 그대로 유지해야 합니다.
tls、snistreamSettings.security、tlsSettings.serverNameTLS 서버 이름과 WebSocket Host는 서로 다른 계층에 속합니다.
ps、v메모 및 공유 형식 정보코어 연결에 필요한 필드가 아니므로 아웃바운드 설정에 그대로 넣으면 안 됩니다.

변환 판단: 전송 의미를 유지한 뒤 필드 유형 조정하기

주소, 포트, UUID, 전송 방식, TLS, SNI, Host, 경로를 하나씩 확인하세요. 공유 필드 type: "none"을 TLS 비활성화의 근거로 삼지 말고, 주소 필드로 서비스 제공자가 명시한 SNI를 덮어쓰지 마세요.

VMess와 VLESS는 서로 다른 프로토콜입니다. 일반적인 vless:// 링크는 사용자 정보, 호스트, 포트, 쿼리 매개변수가 포함된 URI 구조이므로, 접두사를 제거한 뒤 Base64로 디코딩해 JSON을 얻는 절차를 그대로 적용할 수 없습니다. VMess 링크의 접두사만 VLESS로 바꿔도 프로토콜이 변환되지는 않습니다. 서버가 해당 프로토콜과 인증 설정을 지원해야 합니다.

네이티브 JSON으로 변환하기: 노드 외에 인바운드도 설정해야 합니다

네이티브 설정은 디코딩한 노드 JSON의 파일 이름만 바꾸는 것이 아닙니다. 다음은 Xray에서 흔히 사용하는 VMess, WebSocket, TLS 구성을 담은 완전한 예시입니다. 로컬에는 SOCKS 인바운드를 열고, 아웃바운드에는 위의 예시 노드를 사용합니다. 구체적인 필드는 실제로 설치한 코어 버전을 기준으로 확인해야 합니다. 모든 V2Fly 버전에서 사용할 수 있는 공통 설정으로 간주해서는 안 됩니다.

10808
이 예시의 로컬 SOCKS 리스너 포트
443
이 예시의 원격 TLS 연결 포트
0
이 예시의 VMess alterId 값
{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "local-socks",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    }
  ],
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "example.com",
            "port": 443,
            "users": [
              {
                "id": "00000000-0000-4000-8000-000000000001",
                "alterId": 0,
                "security": "auto"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "security": "tls",
        "tlsSettings": {
          "serverName": "example.com",
          "allowInsecure": false
        },
        "wsSettings": {
          "path": "/ws",
          "headers": {
            "Host": "example.com"
          }
        }
      }
    }
  ]
}

이 예시에는 분할 라우팅 규칙이 없으므로 기본적으로 첫 번째 아웃바운드에 트래픽을 보냅니다. 시스템 프록시도 자동으로 설정하지 않습니다. 앱에서 127.0.0.1:10808 SOCKS 서비스를 명시적으로 사용해야 합니다. 127.0.0.1은 로컬 컴퓨터에서만 연결을 허용하므로 문제 해결을 위해 모든 네트워크 인터페이스에 공개되는 주소로 바꾸지 마세요.

역변환: 공유 링크에는 설정 일부만 담을 수 있습니다

VMess 아웃바운드 하나에서 공유 링크를 만들려면 네이티브 설정에서 서버, 사용자, 전송 필드를 추출해 앞서 소개한 v2 공유 객체를 구성한 다음 UTF-8로 인코딩해 Base64로 변환하고 마지막에 vmess:// 접두사를 붙여야 합니다. 네이티브 설정 전체를 바로 인코딩해 이 접두사를 붙이면 일반적인 노드 가져오기 규약에 맞지 않습니다.

function encodeBase64Utf8(text) {
  const bytes = new TextEncoder().encode(text);
  let binary = "";
  for (const byte of bytes) {
    binary += String.fromCharCode(byte);
  }
  return btoa(binary);
}

function createVmessLink(share) {
  return "vmess://" + encodeBase64Utf8(JSON.stringify(share));
}

function createBase64Subscription(links) {
  return encodeBase64Utf8(links.join("\n"));
}

createVmessLink는 필드 표에 맞춰 정리한 공유 객체를 받으며, 복잡한 설정을 자동으로 추출하거나 노드 매개변수를 검증하지 않습니다. createBase64Subscription은 공유 링크 배열을 받아 일반적인 구독 본문을 생성합니다. 업데이트 가능한 구독 주소를 만들어 주는 함수는 아니며, 구독 주소를 제공하려면 관리되는 서비스에서 응답을 제공해야 합니다.

이전 방법 판단: 노드 정보는 링크로, 정책은 백업으로

서버 연결 정보만 이전할 때는 공유 링크를 사용하세요. 라우팅, DNS, 로컬 리스너 설정까지 유지해야 한다면 검토를 마친 설정 백업을 사용하세요. 변환 후에는 주요 필드를 하나씩 대조해야 합니다. 가져오기에 성공했다는 이유만으로 정보가 모두 보존되었다고 볼 수는 없습니다.

클라이언트에 가져오기: 구독, 클립보드, 사용자 지정 설정은 따로 사용하기

클라이언트가 바깥쪽 형식을 인식한다고 해서 내부의 모든 프로토콜과 전송 방식을 코어가 지원하는 것은 아닙니다. v2rayN은 데스크톱 클라이언트이고, v2rayNG는 Xray 코어를 사용하며, v2flyNG는 V2Fly 코어를 사용합니다. 먼저 연결 매개변수와 코어 기능이 맞는지 확인한 뒤 가져오기 방법을 선택하세요. 아래 메뉴는 일반적인 중국어 인터페이스를 기준으로 하며, 버전에 따라 이름과 위치가 다를 수 있습니다.

입력 형식v2rayNAndroid 클라이언트
구독 주소「구독 그룹」→「구독 그룹 설정」에서 주소를 추가한 뒤 그룹을 업데이트합니다.v2rayNG에서는 사이드 메뉴의 「구독 그룹 설정」에서 주소를 추가한 뒤 기본 화면 메뉴에서 「구독 업데이트」를 선택합니다. v2flyNG는 현재 버전의 구독 메뉴를 사용하세요.
개별 공유 링크링크 전체를 복사한 뒤 「서버」→「클립보드에서 URL 일괄 가져오기」를 선택합니다.v2rayNG에서는 기본 화면 오른쪽 위의 「+」→「클립보드에서 가져오기」를 선택합니다. v2flyNG에서는 공유 링크 가져오기 메뉴를 사용하세요.
네이티브 JSON 파일「서버」 메뉴에서 「사용자 지정 설정 서버 추가」를 선택하고 사용할 코어를 확인합니다.현재 버전의 사용자 지정 설정 가져오기 기능을 사용하세요. 구독 주소 입력란에 붙여 넣지 말고, 다른 코어로 이전할 때는 먼저 필드를 확인하세요.

v2rayN에서 흔히 구독을 업데이트하는 메뉴는 「구독 그룹」→「현재 구독 업데이트(프록시 사용 안 함)」입니다. 이 항목은 구독을 가져올 때 프록시를 사용할지 정하며 노드 연결을 직접 연결로 바꾸지는 않습니다. 구독 사이트에 프록시를 통해 접속해야 한다면 프록시를 사용해 업데이트하는 항목을 선택하고 기존 프록시 연결이 작동하는지 먼저 확인하세요.

  1. 업데이트에 실패하면 응답부터 확인하세요. 주소가 만료되었거나 액세스 토큰이 유효하지 않거나 웹페이지가 반환되었다면 노드 형식을 변환하지 마세요. 업데이트 로그와 구독 권한을 먼저 확인하세요.
  2. 가져오기에 실패하면 구조부터 확인하세요. 따옴표를 불필요하게 함께 복사했는지, 접두사가 빠졌는지, 전체 JSON을 공유 링크로 잘못 처리했는지 확인하세요. 한글 메모가 깨지면 UTF-8 인코딩과 디코딩을 확인하세요.
  3. 연결에 실패하면 매개변수를 확인하세요. 노드가 목록에 표시되는데 연결되지 않는다면 Base64 인코딩을 반복하는 대신 UUID, 포트, WebSocket 경로, Host, TLS, SNI를 확인하세요.
  4. 수동 수정은 별도로 저장하세요. 구독을 업데이트하면 노드 항목이 다시 생성될 수 있습니다. 임시로 수정한 노드는 별도 그룹에 복사하고 구독 원본 값과 달라진 부분을 기록해 두세요.

자주 묻는 질문: 디코딩에 성공했는데 왜 사용할 수 없나요?

디코딩한 결과가 여전히 vmess://인데, 디코딩에 실패한 건가요?

아닙니다. 바깥쪽 구독에 공유 링크 목록이 들어 있는 경우 vmess://가 보이면 대개 노드 목록을 가져온 것입니다. 노드 JSON을 확인하려면 개별 링크에서 접두사 뒤의 내용을 디코딩하세요. 클라이언트에 가져오기만 하면 된다면 공유 링크 전체를 그대로 사용할 수 있습니다.

어떤 JSON이든 V2Ray 네이티브 설정으로 사용할 수 있나요?

아니요. VMess 공유 객체, 클라이언트 설정 백업, 코어 설정은 모두 JSON을 사용할 수 있지만 필드의 의미는 서로 다릅니다. 먼저 해당 코어에서 요구하는 인바운드와 아웃바운드 구조가 있는지 확인한 뒤 프로토콜과 전송 필드를 점검하세요. JSON 문법이 올바르다는 것은 텍스트를 파싱할 수 있다는 뜻일 뿐입니다.

로컬 노드 목록을 인코딩하면 자동 업데이트되는 구독이 만들어지나요?

구독 본문만으로는 구독 서비스가 만들어지지 않습니다. 자동 업데이트를 하려면 안정적이고 접근이 제어되는 가져오기 주소도 필요합니다. 본문을 로컬에 저장해도 다른 기기에 변경 사항이 자동으로 전달되지 않습니다. 노드를 한 번 전달할 때는 공유 링크가 더 간편합니다.

클라이언트에서 가져오기에 성공하면 연결 매개변수가 모두 갖춰진 건가요?

반드시 그렇지는 않습니다. 파서는 기본 필드를 받아들이면서 지원하지 않는 확장 매개변수를 무시할 수 있습니다. 가져온 뒤 노드 편집 화면에서 전송 유형, 경로, Host, TLS 서버 이름을 대조하고 실제 연결을 테스트하세요. QR 코드는 텍스트를 전달하는 수단일 뿐 누락된 매개변수를 보완하지 않습니다.

v2rayN 다운로드플랫폼 및 설치 옵션 보기