CONFIGURATION REFERENCE · JSON

V2Ray 구성 파일 완벽 가이드

최상위 객체부터 시작해 inbounds, outbounds, routing, dns, policy 및 전송 계층 필드를 순서대로 살펴봅니다.

이 페이지에서는 필드, 객체 계층 및 매칭 순서를 체계적으로 확인할 수 있습니다. 처음 구독을 가져오고 모드를 선택한 뒤 연결을 테스트하려면 먼저 입문 가이드를 따라 진행하세요. 설치 패키지를 선택해야 한다면 클라이언트 페이지로 이동하세요. 두 페이지가 실제 사용 흐름을 안내한다면, 이 페이지에서는 구성이 왜 이런 구조로 이루어지는지 설명합니다.

01 / structure 02 / inbound 03 / outbound 04 / routing 05 / dns 06 / policy 07 / stream 08 / diagnosis
TABLE OF CONTENTS

예시는 표준 JSON을 사용합니다. 복사할 때 큰따옴표, 쉼표 및 괄호 계층을 유지하고, 본문 설명을 구성 파일에 넣지 마세요.

01
ROOT OBJECT

JSON 구조 개요와 구성 읽기 순서

V2Ray와 Xray의 기본 구성은 트래픽 처리 파이프라인을 설명하는 JSON 객체로 이해할 수 있습니다. 인바운드는 연결을 받고, 라우팅은 목적지를 판단하며, 아웃바운드는 연결을 수행합니다. DNS와 정책 객체는 이 파이프라인에 이름 해석과 리소스 제약을 더합니다.

최상위 객체는 실행 단계 목록이 아닙니다

구성 파일의 최외곽은 하나의 JSON 객체로 이루어지며, 일반적으로 log, dns, inbounds, outbounds, routing, policy, stats 키를 포함합니다. JSON 객체는 작성 위치가 아니라 키 이름으로 구조를 표현하므로, 이러한 키의 배치 순서는 대개 실행 순서를 결정하지 않습니다. 실제로 순서가 의미를 갖는 부분은 주로 배열입니다. 예를 들어 routing.rules는 앞에서부터 매칭하며, 먼저 일치한 규칙이 아웃바운드를 결정합니다. 여러 인바운드와 아웃바운드는 각각의 tag를 통해 다른 객체에서 참조됩니다.

구성을 읽을 때는 먼저 모든 태그를 기록한 다음 참조 관계를 따라 확인하는 방법이 안전합니다. 인바운드 태그는 라우팅 규칙의 inboundTag에서 사용될 수 있고, 아웃바운드 태그는 outboundTag가 가리키며, DNS 서버도 tag를 통해 라우팅 규칙과 연결될 수 있습니다. 태그 자체는 구성 내부 식별자일 뿐 자동으로 트래픽 분할을 만들지 않습니다. 존재하지 않는 태그를 규칙에 사용하면 시작 단계에서 오류가 발생하거나, 해당 경로가 실행될 때 트래픽의 목적지를 찾지 못할 수 있습니다. 구체적인 동작은 코어와 필드 위치에 따라 달라집니다.

{
  "log": {
    "loglevel": "warning"
  },
  "dns": {
    "servers": ["1.1.1.1", "localhost"]
  },
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "udp": true
      }
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom"
    },
    {
      "tag": "blocked",
      "protocol": "blackhole"
    }
  ],
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      }
    ]
  }
}

배열, 객체 및 값의 유형

inbounds, outbounds, routing.rules는 모두 배열이므로 대괄호를 사용합니다. 단일 인바운드, 아웃바운드 또는 규칙은 객체이므로 중괄호를 사용합니다. 포트는 숫자이며 단위가 붙은 문자열로 작성하면 안 됩니다. 불리언 값은 true 또는 false만 사용할 수 있습니다. 필드를 생략하는 것과 값으로 null을 지정하는 것은 같지 않습니다. 생략하면 코어가 기본 동작을 사용하지만, 명시적인 빈 값은 해당 필드 정의에서 허용할 때만 의미가 있습니다. 시작 실패의 상당수는 프로토콜 문제가 아니라 괄호 누락, 객체 사이의 쉼표 누락, 문자열에 중국식 따옴표 사용, 배열이어야 할 필드를 단일 문자열로 작성한 데서 발생합니다.

표준 JSON에서는 주석을 사용할 수 없고 마지막 멤버 뒤에 후행 쉼표를 둘 수도 없습니다. 온라인 예제는 설명을 위해 // 주석을 넣는 경우가 있지만, 클라이언트 코어 구성에 복사하기 전 반드시 삭제해야 합니다. v2rayN, v2rayNG, v2flyNG는 그래픽 인터페이스 외부에서 자체 구성 계층을 관리할 수 있으며, 인터페이스의 노드·구독·라우팅 설정은 변환된 뒤 코어에 전달됩니다. 따라서 직접 편집하기 전에 수정 대상이 클라이언트 관리 파일인지, 생성된 실행 구성인지, 독립 코어가 읽는 구성인지 확인해야 합니다. 파일 이름이 비슷하다는 이유만으로 이 셋을 같은 객체로 보면 안 됩니다.

최소 구성에서 복잡도를 단계적으로 높이기

구성을 점검할 때는 로컬 인바운드 하나, 명확하게 작동하는 아웃바운드 하나, 최소한의 라우팅만 남긴 뒤 DNS, 스니핑, 여러 전송 방식과 통계 정책을 단계적으로 추가해야 합니다. 여러 모듈을 한꺼번에 추가하면 오류 원인이 서로 가려집니다. 예를 들어 연결 실패는 원격 서버 매개변수 때문일 수도 있고, 도메인이 잘못된 DNS 경로로 먼저 해석되었기 때문일 수도 있으며, 선행 규칙이 연결을 blocked로 보냈기 때문일 수도 있습니다. 최소화란 필요한 보안 필드를 삭제하는 것이 아니라 변수의 연결 고리를 줄이는 것입니다. 서버가 요구하는 주소, 포트, 사용자 식별자, 전송 및 보안 매개변수는 유지하고, 연결성에 영향을 주지 않는 부가 규칙만 일시적으로 제거하세요.

저장하기 전 텍스트 인코딩이 UTF-8인지, 파일에 루트 객체가 하나만 있는지, 키 이름의 대소문자가 필드 정의와 일치하는지 확인해야 합니다. outboundTagoutboundtag는 서로 다른 이름이며, 프로토콜 이름도 인터페이스의 번역명을 보고 추측해서는 안 됩니다. 구조 검사가 끝나면 인바운드, 아웃바운드, 라우팅을 차례로 검증하세요. 대형 구성에서 포트만 반복해서 바꾸는 것보다 원인을 훨씬 명확하게 파악할 수 있습니다.

02
INBOUND HANDLERS

inbounds 인바운드, 수신 범위 및 프로토콜 설정

인바운드는 코어가 어디에서 연결을 받고, 어떤 프로토콜로 연결을 해석하며, 목적지 주소를 스니핑할지 정의합니다. 데스크톱 클라이언트는 보통 로컬 SOCKS와 HTTP 인바운드를 만들고, 모바일에서는 VPN 서비스가 트래픽을 코어로 전달할 수 있습니다.

listen, port 및 로컬 노출 범위

각 인바운드는 최소한 프로토콜과 해당 설정을 명확히 지정해야 합니다. 일반적인 필드로는 tag, listen, port, protocol, settings, sniffing, streamSettings가 있습니다. listen127.0.0.1로 설정하면 로컬 프로그램만 해당 포트에 연결할 수 있어 브라우저, 시스템 프록시 또는 로컬 도구의 진입점으로 적합합니다. 모든 네트워크 인터페이스에서 수신하도록 설정하면 같은 LAN의 다른 기기도 접근을 시도할 수 있으므로 운영체제 방화벽, 인증 및 실제 공유 필요성을 함께 고려해야 합니다. 명확한 LAN 공유 목적이 없다면 로컬 루프백 주소가 더 분명한 경계를 제공합니다.

port는 다른 프로그램이 사용하지 않는 포트여야 합니다. 동일한 주소와 포트 조합을 동시에 실행 중인 두 인바운드가 중복해서 수신할 수 없습니다. 그래픽 클라이언트는 SOCKS, HTTP 또는 혼합 진입점에 인접한 포트를 배정하는 경우가 많지만, 이 포트가 프로토콜의 고정값은 아닙니다. 다른 장치에 튜토리얼의 포트를 그대로 적용하면 개발 서버, 이전 클라이언트 프로세스 또는 다른 네트워크 도구와 충돌할 수 있습니다. ‘주소가 이미 사용 중’과 같은 오류가 발생하면 먼저 중복 인스턴스를 종료하거나 클라이언트 설정에서 수신 포트를 변경한 뒤 시스템 프록시 대상도 함께 업데이트하세요.

{
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      }
    },
    {
      "tag": "http-in",
      "listen": "127.0.0.1",
      "port": 10809,
      "protocol": "http",
      "settings": {}
    }
  ]
}

SOCKS, HTTP 및 투명 프록시 진입점의 차이

SOCKS 인바운드는 애플리케이션이 직접 시작한 프록시 연결을 전달할 수 있으며, udp를 활성화하면 SOCKS UDP 전달 절차에 맞는 요청도 받을 수 있습니다. 그렇다고 모든 시스템 UDP 트래픽이 자동으로 해당 포트로 들어오는 것은 아닙니다. HTTP 인바운드는 HTTP 프록시 설정을 지원하는 애플리케이션을 주로 처리합니다. 시스템 프록시는 운영체제 설정을 읽는 프로그램에만 영향을 주며, 장치의 모든 트래픽을 가로채는 기능과 같지 않습니다. 투명 프록시나 가상 네트워크 인터페이스 기반 방식은 운영체제 네트워크 규칙과 클라이언트의 협력이 필요하고 필드와 권한 조건도 더 복잡합니다. 일반 SOCKS 인바운드의 프로토콜 이름만 바꿔 적용해서는 안 됩니다.

v2rayN에서는 인터페이스가 로컬 진입점을 만들고 Windows, macOS 또는 Linux의 시스템 프록시 상태를 설정합니다. v2rayNG와 v2flyNG에서는 Android VPN 서비스가 선택한 앱의 트래픽을 코어로 전달합니다. 따라서 동일한 노드 아웃바운드 매개변수는 여러 클라이언트로 옮길 수 있지만, 인바운드 부분은 플랫폼 통합 방식에 종속되는 경우가 많습니다. 마이그레이션할 때는 서버 매개변수를 유지하고 대상 클라이언트가 로컬 진입점을 새로 생성하게 하세요. 실행 구성을 통째로 덮어쓰면 안 됩니다. 플랫폼 설치 및 클라이언트 선택은 클라이언트 다운로드 페이지에서 확인할 수 있습니다.

sniffing의 역할과 오인식 범위

스니핑은 연결 초기 데이터에서 도메인을 복원하여, 원래 IP 목적지만 포함한 요청도 도메인 라우팅 규칙으로 처리할 수 있게 합니다. destOverride의 일반적인 httptls는 각각 식별 가능한 HTTP 호스트 정보와 TLS 핸드셰이크 도메인에 해당합니다. 스니핑은 애플리케이션 콘텐츠를 복호화하지 않으며 모든 연결에서 도메인을 복원할 수 있는 것도 아닙니다. 암호화 핸드셰이크의 변화, 비표준 프로토콜, 연결 재사용 또는 IP를 직접 사용하는 앱에서는 유효한 도메인을 얻지 못할 수 있습니다.

스니핑을 활성화한 뒤 특정 앱의 목적지 주소가 변경되어 연결 문제가 발생하면, 먼저 해당 앱의 트래픽을 별도 인바운드로 분리하거나 덮어쓰기 유형을 제한하고 활성화·비활성화 상태의 로그를 비교하세요. 스니핑을 DNS의 대체 수단으로 보면 안 됩니다. DNS는 도메인을 어떻게 해석할지 결정하고, 스니핑은 연결이 들어온 뒤 원래 도메인을 식별하려고 시도하므로 서로 다른 단계에서 동작합니다. 라우팅 규칙에 도메인 조건과 IP 조건이 함께 있다면 domainStrategy를 확인하여 코어가 라우팅 목적을 위해 도메인을 추가로 해석하는지도 판단해야 합니다.

필드 일반적인 값 확인할 핵심 사항
listen 127.0.0.1 정말 다른 기기의 접근을 허용해야 하는가
port 유효한 포트 번호 다른 프로그램 또는 인바운드와 중복되는가
protocol sockshttp settings가 해당 프로토콜에 맞는가
tag 중복되지 않는 사용자 지정 이름 라우팅에서 참조가 완전히 일치하는가
03
OUTBOUND HANDLERS

outbounds 아웃바운드, 노드 매개변수 및 체인 관계

아웃바운드는 라우팅으로 선택된 연결을 목적지로 보냅니다. 원격 프로토콜 서버에 연결할 수도 있고, 목적지에 직접 연결하거나 연결을 거부하거나 다른 아웃바운드로 넘겨 계속 처리할 수도 있습니다.

프로토콜 필드는 전체 구조로 확인해야 합니다

원격 아웃바운드는 일반적으로 protocol, settings, streamSettings가 함께 정의합니다. VLESS를 예로 들면 서버 주소와 포트는 vnext 항목에, 사용자 식별자는 users에 있습니다. 전송 방식, 보안 계층, 서버 이름은 streamSettings에 지정합니다. 주소, 포트, 사용자 식별자만 확인해서는 구성이 일치한다고 볼 수 없습니다. 클라이언트와 서버의 네트워크 전송, TLS 계열 보안 설정, 경로, 호스트 이름 및 관련 확장 매개변수도 서로 대응해야 합니다.

구성 인터페이스에서는 이러한 필드를 ‘주소’, ‘사용자’, ‘전송’, ‘보안’ 등의 페이지에 나누어 표시하는 경우가 많지만, JSON에서는 인접한 객체에 배치됩니다. 구독 가져오기에 문제가 생기면 노드 표시 이름만 보고 판단하지 말고 클라이언트 상세 페이지에서 항목별로 확인하세요. 노드 이름은 대개 로컬 메모일 뿐 프로토콜 핸드셰이크에 관여하지 않습니다. 실제 연결을 좌우하는 것은 구조화된 필드입니다. 매개변수를 직접 옮길 때는 URI에서 인코딩된 텍스트를 JSON 원문으로 바로 사용하지 말고, 인터페이스에서 ‘기본값’을 의미하는 빈 항목을 임의로 "default" 문자열로 바꾸지도 마세요.

{
  "outbounds": [
    {
      "tag": "remote-vless",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "server.example.com",
            "port": 443,
            "users": [
              {
                "id": "11111111-1111-4111-8111-111111111111",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "security": "tls",
        "tlsSettings": {
          "serverName": "server.example.com"
        },
        "wsSettings": {
          "path": "/example-path",
          "headers": {
            "Host": "server.example.com"
          }
        }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom"
    },
    {
      "tag": "blocked",
      "protocol": "blackhole"
    }
  ]
}

direct와 blocked는 명확한 처리 경로입니다

freedom 아웃바운드는 보통 목적지에 직접 연결하는 데 사용하며 direct로 표시합니다. blackhole은 규칙에 선택된 연결을 종료하는 데 사용하며 blocked로 표시하는 경우가 많습니다. 이러한 태그는 관례적인 이름일 뿐 변경할 수 있지만, 라우팅 참조도 함께 수정해야 합니다. freedom을 아웃바운드 배열에 넣는 것만으로 로컬 주소가 자동으로 직접 연결되지는 않습니다. 해당 트래픽을 그 아웃바운드로 보내는 라우팅 규칙이 필요합니다. 마찬가지로 blackhole을 정의해도 아무 도메인이나 자동 차단되지 않으며, 매칭 규칙이 이를 참조해야 적용됩니다.

규칙에 일치하는 항목이 없으면 코어는 일반적으로 기본 아웃바운드를 선택하지만, 구체적인 동작은 구성 구조와 코어 구현에 따라 달라집니다. 구성 독자가 암묵적인 순서에 의존하지 않도록 대형 구성에서는 중요한 트래픽에 명시적인 규칙을 작성하는 편이 좋습니다. 아웃바운드 태그도 읽기 쉬워야 합니다. 원격 연결, 직접 연결, 차단 연결의 이름은 혼동하기 쉬운 연속 숫자보다 용도를 나타내야 합니다. 이름이 명확하면 로그의 아웃바운드 식별자를 구성과 대조하기도 쉽습니다.

아웃바운드 체인, 프록시 설정 및 순환 참조

일부 코어는 proxySettings 또는 다른 방식을 통해 한 아웃바운드가 다른 아웃바운드를 거쳐 연결하도록 허용합니다. 명확하게 설계된 체인형 출구에 적합하지만 DNS, 핸드셰이크 및 장애 분석 단계도 늘어납니다. 체인의 각 구간에는 고유 태그가 있어야 하며 A가 B를 가리키고 B가 다시 A를 가리키는 순환을 만들면 안 됩니다. 원격 서버 도메인을 어떻게 해석할지도 별도로 고려해야 합니다. 첫 번째 연결을 만들기 위한 DNS 조회가 아직 연결되지 않은 아웃바운드에 의존하면 시작 후 계속 시간 초과가 발생하는 순환 구조가 될 수 있습니다.

체인 구성은 실제 연결을 마지막으로 담당하는 단일 아웃바운드부터 독립적으로 작동하게 만든 뒤, 앞쪽 구간을 하나씩 추가하며 점검해야 합니다. 로그에 ‘연결이 종료됨’만 표시된다면 아웃바운드 태그를 함께 확인하여 어느 계층에서 실패했는지 판단하세요. 원격 서버의 거부, 도메인 해석 실패, TLS 서버 이름 불일치, 로컬 라우팅의 잘못된 선행 선택은 모두 앱에서 페이지가 열리지 않는 것처럼 보일 수 있습니다. 모든 프로토콜 매개변수를 동시에 바꾸기보다 계층별로 검증해야 원인을 추적할 증거를 보존할 수 있습니다.

데스크톱에서는 v2rayN으로 노드와 코어 구성을 관리하는 것이 좋고, Android에서는 코어 요구 사항에 따라 v2rayNG 또는 v2flyNG를 선택할 수 있습니다. Xray와 V2Fly의 용도를 비교하려면 Xray와 V2Fly 코어 차이 정리를 참고하세요. 코어 브랜치에 따라 지원되는 필드 범위가 다를 수 있으므로 복잡한 구성을 옮기기 전에 대상 클라이언트에서 실제로 어떤 코어를 활성화했는지 확인해야 합니다.

04
ROUTING RULES

routing 라우팅 규칙, 매칭 조건 및 우선순위

라우팅 객체는 연결을 만들지 않습니다. 인바운드가 식별한 목적지 정보를 받아 규칙 배열에 따라 아웃바운드를 선택합니다. ‘앞에서 뒤로, 처음 일치한 규칙’이라는 원칙을 이해하는 것이 트래픽 분할 구성을 관리하는 핵심입니다.

규칙 배열의 매칭 모델

routing.rules에서 흔히 사용하는 규칙 유형은 field입니다. domain, ip, port, network, protocol, inboundTag, user 등의 조건으로 연결을 필터링하고 outboundTag로 목적지를 지정할 수 있습니다. 한 규칙에 서로 다른 범주의 조건이 여러 개 있으면 일반적으로 모두 충족해야 하며, 같은 필드 배열의 여러 값은 보통 어느 하나라도 일치하면 됩니다. 관리할 때 특정 도메인 목록만 보지 말고 같은 규칙에 포트나 인바운드 태그 제한이 붙어 있는지도 확인하세요.

규칙은 배열의 첫 항목부터 뒤로 이동하며 검사합니다. 원격 아웃바운드를 사용해야 하는 내부 테스트 도메인처럼 더 구체적인 예외는 범위가 넓은 규칙보다 앞에 둬야 합니다. 포괄적인 규칙이 먼저 일치하면 뒤의 예외는 실행될 기회를 영원히 얻지 못합니다. 마지막에는 남은 연결을 포괄하는 규칙을 둘 수도 있고 기본 아웃바운드에 의존할 수도 있지만, 전자가 검토하기 더 편한 경우가 많습니다. 규칙을 조정할 때는 한 번에 한 그룹만 이동하고 이동 전후의 매칭 태그를 기록하여 ‘규칙이 매칭되지 않음’과 ‘아웃바운드를 사용할 수 없음’을 혼동하지 않도록 하세요.

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "domainMatcher": "hybrid",
    "rules": [
      {
        "type": "field",
        "domain": [
          "full:intranet.example",
          "domain:local.example"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "protocol": [
          "bittorrent"
        ],
        "outboundTag": "blocked"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "remote-vless"
      }
    ]
  }
}

domain 문법과 IP 조건

full:은 전체 도메인 이름을 일치시키며 특정 호스트 이름 하나만 처리할 때 적합합니다. domain:은 일반적으로 지정된 도메인과 하위 도메인 범위를 매칭합니다. regexp:는 정규 표현식을 제공하지만 복잡한 표현식은 유지 관리 비용을 높이고 점, 경계 또는 이스케이프를 잘못 작성하기 쉽습니다. 접두사가 없는 형식의 해석은 코어 정의를 따라야 합니다. geosite:geoip: 같은 규칙 집합 식별자는 코어가 읽을 수 있는 규칙 데이터에 의존하므로, 이름이 존재한다고 해서 로컬 데이터에 해당 항목이 반드시 포함된다는 뜻은 아닙니다.

IP 규칙에는 단일 주소와 CIDR 네트워크를 모두 사용할 수 있습니다. geoip:private는 사설 주소 범위를 처리하여 LAN 장치와 로컬 서비스를 원격 아웃바운드로 보내지 않을 때 자주 사용합니다. 하지만 도메인이 최종적으로 사설 주소로 해석될 때 IP 규칙에 들어가는지는 domainStrategy의 영향을 받습니다. AsIs이면 라우팅 단계에서 IP 규칙 매칭을 위해 도메인을 적극적으로 해석하지 않습니다. IPIfNonMatch를 사용하면 도메인 규칙이 일치하지 않은 뒤 계속 해석하여 IP 매칭을 시도할 수 있습니다. 더 적극적인 전략은 더 이른 시점에 해석할 수 있습니다. 전략이 적극적일수록 라우팅과 DNS의 결합도도 커집니다.

인바운드, 네트워크 및 프로토콜별 트래픽 분할

inboundTag는 서로 다른 로컬 진입점을 서로 다른 아웃바운드로 보낼 때 적합합니다. 예를 들어 테스트 진입점은 특정 원격 아웃바운드를 사용하고, 일반 시스템 프록시는 도메인 규칙에 따라 처리하게 만들 수 있습니다. 임시 실험을 격리할 때도 유용합니다. 별도 포트와 태그를 추가하면 주 진입점을 건드리지 않고 규칙을 검증할 수 있습니다. network는 TCP와 UDP를 구분할 수 있지만, 원격 프로토콜과 전송이 해당 네트워크를 완전히 전달할 수 있는지는 별도로 확인해야 합니다. protocol 조건은 코어의 식별 결과에 의존하며 인바운드 스니핑과 관련된 경우가 많으므로, 모든 연결이 안정적으로 분류된다고 가정해서는 안 됩니다.

트래픽 분할 결과는 클라이언트 인터페이스의 ‘전체’, ‘규칙’, ‘직접 연결’ 등의 모드와 관련이 있습니다. 인터페이스 모드는 서로 다른 라우팅 템플릿으로 전환하거나 기본 아웃바운드를 바꿀 수 있으며, 단일 규칙만 수정하는 것과는 다릅니다. 세 가지 일반적인 모드의 적용 범위는 시스템 프록시·전체 모드·중국 본토 우회 모드 비교에서 확인할 수 있습니다. 사용자 지정 규칙을 디버깅할 때는 클라이언트 모드를 고정해야 합니다. 인터페이스 전환으로 구성이 다시 생성되면 직접 수정한 내용이 무효화될 수 있습니다.

조건 적합한 표현 일반적인 오해
domain 전체 도메인, 접미사 범위, 규칙 집합 접두사 의미 또는 규칙 순서를 무시함
ip 단일 주소, CIDR, IP 규칙 집합 라우팅 단계에서 도메인이 해석되는지 고려하지 않음
inboundTag 로컬 진입점별 경로 격리 존재하지 않거나 표기가 다른 태그를 참조함
network TCP와 UDP 구분 네트워크 유형을 애플리케이션 프로토콜 범주로 오해함
05
NAME RESOLUTION

dns 설정, 서버 선택 및 라우팅 연동

DNS 구성은 코어가 도메인을 해석해야 할 때 어떤 서버에 조회하고, 특정 도메인을 어느 해석 경로로 우선 보낼지 결정합니다. 운영체제 DNS, 앱 자체 해석, 라우팅 단계의 해석과는 서로 다른 계층입니다.

먼저 누가 조회를 시작했는지 구분하기

앱이 먼저 시스템 계층에서 도메인을 해석한 뒤 프록시에 목적지 IP만 전달할 수 있습니다. 반대로 도메인을 SOCKS 또는 HTTP 인바운드에 그대로 전달할 수도 있으며, 자체 암호화 DNS를 사용하는 앱도 있습니다. 코어로 들어와 코어가 처리하는 조회만 최상위 dns 객체의 직접적인 영향을 받습니다. 따라서 구성을 바꾼 뒤 예상한 변화가 보이지 않으면 인바운드가 도메인을 받았는지 IP를 받았는지, 스니핑으로 도메인을 복원했는지 먼저 확인하세요. dns.servers만 바꾼다고 모든 시스템 프로그램이 자체 해석 경로를 포기하는 것은 아닙니다.

servers에는 단순 주소를 넣을 수도 있고, address, domains, expectIPs, skipFallback 등의 속성을 가진 객체를 넣을 수도 있습니다. 단순 배열은 단일 경로에 적합하고, 객체 형식은 도메인별 서버 선택에 적합합니다. 서버 목록이 항상 ‘첫 번째 서버가 실패하면 두 번째 서버를 사용’하는 전통적인 백업 방식으로 동작하는 것은 아닙니다. 도메인 필터, 폴백 설정 및 코어 구현이 함께 조회 대상을 결정합니다. 복잡한 DNS를 설계하기 전에는 역할이 분명한 서버 두 개로 먼저 검증한 다음 도메인 범위와 폴백 제한을 추가하세요.

{
  "dns": {
    "hosts": {
      "router.example": "192.168.1.1"
    },
    "servers": [
      {
        "address": "localhost",
        "domains": [
          "full:router.example",
          "domain:internal.example"
        ],
        "skipFallback": true
      },
      {
        "address": "1.1.1.1",
        "domains": [
          "domain:public.example"
        ]
      },
      "8.8.8.8"
    ],
    "queryStrategy": "UseIP"
  }
}

hosts, domains 및 예상 결과

hosts는 특정 이름에 정적 매핑을 제공하며, 수가 적고 안정적인 로컬 서비스 이름에 적합합니다. 대규모 동적 도메인 목록에는 적합하지 않습니다. 정적 매핑은 우선순위가 높은 편이므로 주소가 바뀐 뒤 갱신하지 않으면 ‘특정 이름 하나만 계속 이전 주소를 가리키는’ 현상이 발생합니다. 문제를 점검할 때는 운영체제 hosts 파일, 클라이언트 인터페이스의 호스트 덮어쓰기 항목, 코어 구성의 dns.hosts를 함께 확인하여 여러 계층의 충돌을 피하세요.

서버 객체의 domains는 해당 서버로 보낼 도메인을 필터링합니다. 문법은 라우팅 도메인 조건과 비슷하지만 용도는 다릅니다. 전자는 해석기를 선택하고 후자는 연결 아웃바운드를 선택합니다. expectIPs는 예상 반환 주소 범위를 제한하여 결과가 사전 설정에 맞는지 판단하는 데 사용합니다. 임의의 응답을 목표 범위로 바꾸는 기능은 아닙니다. 범위를 지나치게 좁히면 정상 응답도 제외되어 폴백으로 넘어갈 수 있습니다. skipFallback은 해당 서버가 폴백에 참여하는 방식을 바꿉니다. 함께 사용하기 전 ‘도메인 선택—서버 조회—결과 검사—연결 라우팅’의 네 단계 관계를 먼저 그려 보세요.

DNS 조회에서 아웃바운드를 선택하는 방식

DNS 서버 주소 자체도 연결을 수립해야 합니다. 서버를 도메인으로 지정하면 먼저 해석기 도메인을 해석해야 하는 문제가 생기고, IP로 지정하면 이 단계는 생략되지만 네트워크 아웃바운드는 여전히 라우팅으로 선택해야 합니다. 복잡한 구성에서는 DNS 트래픽에 태그를 부여한 뒤 라우팅에서 해당 태그나 프로토콜에 따라 특정 아웃바운드로 보낼 수 있습니다. 이때 순환을 피해야 합니다. 원격 아웃바운드가 도메인 해석에 의존하고, 그 도메인 해석이 아직 연결되지 않은 원격 아웃바운드를 요구하는 구조가 대표적인 순환입니다.

설명 가능한 경로를 만들려면 먼저 원격 서버 주소에 안정적인 기본 해석 경로를 마련한 뒤 일반 목적지 도메인의 분할 방식을 결정하세요. 구성에서 domainStrategy와 DNS 규칙을 함께 사용하면 라우팅이 IP 조건을 판단하기 위해 시작한 해석도 DNS 모듈로 들어갑니다. 따라서 겉으로는 라우팅 문제처럼 보여도 실제 원인은 DNS 서버 선택이나 폴백 결과일 수 있습니다. 로그를 점검할 때는 마지막 시간 초과 한 줄만 보지 말고 조회, 주소 획득, 아웃바운드 선택, 연결 대상의 순서를 시간 흐름에 따라 확인하세요.

캐시 및 IPv4·IPv6 선택

queryStrategy는 조회 결과의 주소 계열을 제한하거나 우선시합니다. 지원 범위는 코어마다 다릅니다. 한 주소 계열만 강제하면 로컬 네트워크가 불완전한 문제를 피할 수 있지만, 원래 접근 가능한 목적지까지 제외할 수 있습니다. 먼저 운영체제가 해당 네트워크에 연결할 수 있는지 확인한 뒤 조회 제한 여부를 결정하세요. 클라이언트, 코어, 시스템 해석기가 결과를 각각 캐시할 수 있으므로 DNS를 바꾼 직후 재시도해도 새 조회가 발생하지 않을 수 있습니다. 관련 클라이언트 프로세스를 재시작하고 연결을 다시 만들 수는 있지만, 캐시 삭제를 장기적인 구성 해결책으로 삼아서는 안 됩니다.

‘도메인은 접속할 수 없지만 IP로는 접속되는’ 경우 먼저 조회가 주소를 반환했는지 확인하고, 반환된 주소가 라우팅 규칙에 의해 예상한 아웃바운드로 전달되는지 점검하세요. ‘일부 도메인만 간헐적으로 실패’한다면 실패와 성공 시 선택된 DNS 서버, 주소 계열, 아웃바운드 태그를 비교해야 합니다. 서버를 바꾸는 것은 해석기 경로를 검증하는 방법일 뿐 규칙 조건 점검을 대신할 수 없습니다. 일반적인 클라이언트 연결 흐름과 검증 방법은 입문 가이드에서 단계별로 확인할 수 있습니다.

06
POLICY AND STATS

policy 정책, 연결 시간 제한 및 통계 스위치

policy는 트래픽이 어느 노드로 갈지 결정하지 않습니다. 사용자 등급과 시스템 수준 동작에 연결 시간 초과, 유휴 시간, 통계 스위치를 설정합니다. 라우팅 선택과는 별도의 계층에 있지만 장시간 연결의 수명과 관찰 가능성에 영향을 줍니다.

level과 levels의 참조 관계

policy.levels는 사용자 등급을 키로 사용하는 객체입니다. 프로토콜 사용자 설정의 level 숫자가 해당 정책을 참조하며, 사용자가 명시적으로 설정하지 않으면 보통 기본 등급이 사용됩니다. 등급은 속도 점수나 권한 순위가 아니라 사용자 연결을 정책 매개변수 집합에 매핑하는 식별자입니다. 등급을 0에서 1로 바꾼다고 성능이 자동으로 향상되는 것은 아닙니다. levels["1"]을 정의하고 다른 필드를 설정해야 실제 차이가 생깁니다.

클라이언트가 로컬 연결을 시작하는 경우 대부분의 사용자는 기본 등급만 필요합니다. 여러 등급은 서로 다른 인바운드 사용자를 구분해야 하는 서버 구성에서 더 자주 사용됩니다. 그렇더라도 모든 사용자에게 거의 같은 정책을 하나씩 만들기보다 실제 관리 요구를 기준으로 설계해야 합니다. 정책이 많아질수록 이전할 때 참조를 빠뜨리기 쉽습니다. 점검할 때는 먼저 모든 level을 검색한 뒤 policy.levels에 해당 키가 있는지 확인하고, JSON 객체 키가 텍스트에서는 문자열로 작성된다는 점에 유의하세요.

{
  "policy": {
    "levels": {
      "0": {
        "handshake": 4,
        "connIdle": 300,
        "uplinkOnly": 2,
        "downlinkOnly": 5,
        "statsUserUplink": false,
        "statsUserDownlink": false
      }
    },
    "system": {
      "statsInboundUplink": true,
      "statsInboundDownlink": true,
      "statsOutboundUplink": true,
      "statsOutboundDownlink": true
    }
  },
  "stats": {}
}

핸드셰이크, 유휴 상태 및 단방향 연결 시간 제한

handshake는 연결 초기 설정 단계에서 기다릴 수 있는 시간을 제어합니다. 너무 짧으면 부하가 높은 장치, 느린 네트워크 또는 여러 단계의 핸드셰이크가 필요한 연결이 완료되기 전에 종료될 수 있습니다. 너무 길면 실패한 연결이 리소스를 더 오래 점유합니다. connIdle은 활동이 없을 때 연결을 얼마 동안 유지할지 판단합니다. 메신저, 푸시, 원격 터미널, 스트리밍은 유휴 동작이 서로 다를 수 있으므로 웹 브라우징만으로 모든 장시간 연결 값을 결정해서는 안 됩니다.

uplinkOnlydownlinkOnly는 연결이 단방향 전송만 남은 뒤의 수명을 처리합니다. 업로드·다운로드 속도 제한이 아니며 어느 방향에 대역폭을 배정하는 기능도 아닙니다. 앱이 일정 시간 단방향 전송을 한 뒤 조기에 끊긴다면 이 값들을 확인하세요. 양방향 모두 데이터가 없어진 뒤 끊긴다면 connIdle과 관련되었을 가능성이 큽니다. 원격 서버, 중간 네트워크 장비, 앱 자체도 연결을 종료할 수 있으므로 로컬 policy는 문제 해결 과정의 일부일 뿐입니다.

통계 필드는 완전한 활성화 경로가 필요합니다

statsUserUplinkstatsUserDownlink는 사용자별 통계를 제어하고, policy.system의 필드는 인바운드 및 아웃바운드 방향별 통계를 제어합니다. 불리언 값을 true로 설정하는 것만으로 클라이언트 인터페이스에 데이터가 표시되지는 않습니다. 최상위 stats 객체, 관련 API 또는 클라이언트의 읽기 로직도 함께 작동해야 합니다. 반대로 인터페이스에 표시되지 않는다고 코어에 통계가 없다고 단정할 수도 없습니다. ‘카운터가 활성화되지 않음’, ‘카운터는 있지만 읽히지 않음’, ‘읽기 인터페이스와 클라이언트 표시가 맞지 않음’을 구분해야 합니다.

통계를 활성화하면 추가 상태를 관리해야 하므로 진단 및 관리 요구에 따라 결정해야 합니다. 통계 결과를 읽지 않는 개인 데스크톱 구성은 단순하게 유지해도 됩니다. 특정 인바운드나 아웃바운드에 트래픽이 있는지 분석해야 한다면 시스템 수준 카운터를 일시적으로 활성화하고 로그에서 태그를 확인하세요. 통계값을 연결 품질 판단의 유일한 기준으로 삼아서는 안 됩니다. 통계값은 해당 처리기를 통과한 데이터량의 변화를 보여줄 뿐 핸드셰이크 시간, 앱 응답 또는 DNS 선택을 직접 설명하지 않습니다.

정책 변경을 검증하는 방법

연결 시간 제한을 바꾼 뒤에는 문제를 안정적으로 재현할 수 있는 상황에서 검증해야 합니다. 예를 들어 장시간 연결을 기존 임계값보다 오래 유휴 상태로 둔 다음 데이터를 보내 연결이 재생성되는지 관찰하세요. 웹 페이지를 빠르게 새로 고치는 것만으로 유휴 정책을 판단하면 안 됩니다. 특정 프로토콜이나 앱만 이상하다면 해당 연결이 실제로 수정한 사용자 등급에 매핑되었는지 먼저 확인하세요. 클라이언트가 구성을 생성할 때 수동 policy를 덮어쓸 수도 있으므로 실행 시 구성이나 로그에서 최종값을 확인해야 합니다.

policy는 명확한 연결 수명 및 통계 요구를 해결하는 데 적합하며, 잘못된 라우팅·전송·원격 매개변수를 수정하는 용도가 아닙니다. 연결이 처음부터 수립되지 않으면 아웃바운드와 전송 계층으로 돌아가야 합니다. 특정 도메인만 연결되지 않으면 라우팅과 DNS를 확인하세요. 연결은 수립되지만 일정한 유휴 단계에서 끊긴다면 그때 정책 객체를 확인합니다. 이 순서를 따르면 시간 제한을 무작정 늘려 실제 핸드셰이크 실패를 가리는 일을 피할 수 있습니다.

07
TRANSPORT LAYER

streamSettings, 전송 방식 및 보안 매개변수

원격 프로토콜은 신원과 요청 형식을 정의하고, streamSettings는 해당 데이터가 네트워크 연결에 실리는 방식을 정의합니다. 양쪽의 프로토콜 매개변수가 맞더라도 전송 계층이 다르면 연결을 완료할 수 없습니다.

network가 결정하는 후속 설정 객체

streamSettings.network는 전송 유형을 지정하며, 일반적인 구성에는 TCP, WebSocket, gRPC, mKCP 등이 사용될 수 있습니다. 특정 네트워크를 선택한 뒤에는 이에 맞는 설정 객체를 사용해야 합니다. 예를 들어 WebSocket은 wsSettings를, gRPC는 해당 서비스 이름 설정을 사용합니다. 다른 전송의 필드를 구성에 남겨둔다고 두 방식이 자동으로 결합되지는 않으며, 오히려 잘못 읽게 만들 수 있습니다. 노드를 이전할 때는 먼저 인터페이스에 표시된 전송 유형을 확인한 뒤 전용 필드를 항목별로 점검하세요.

전송 유형은 클라이언트가 일방적으로 최적화할 수 있는 옵션이 아닙니다. 서버가 어떤 전송을 수신하고 어떤 경로나 서비스 이름을 사용하는지에 맞춰 클라이언트도 같은 구조로 연결해야 합니다. 오류가 발생했을 때 TCP, WebSocket, gRPC 사이를 계속 바꾸면 대개 변수만 늘어납니다. 원본 구성에 따라 전송 유형을 고정하고, 주소 해석 여부와 포트 접근성을 확인한 다음 경로, 호스트 필드, 보안 계층을 점검하는 편이 안전합니다.

{
  "streamSettings": {
    "network": "grpc",
    "security": "tls",
    "tlsSettings": {
      "serverName": "edge.example.com",
      "allowInsecure": false,
      "alpn": ["h2"]
    },
    "grpcSettings": {
      "serviceName": "example-service",
      "multiMode": false
    },
    "sockopt": {
      "tcpKeepAliveIdle": 100
    }
  }
}

WebSocket 경로, Host 및 TLS 이름

WebSocket 구성의 path는 HTTP 핸드셰이크 경로입니다. 앞에 슬래시가 필요한지, 쿼리 부분을 포함하는지는 서버 진입점과 일치해야 합니다. headers.Host는 WebSocket 핸드셰이크 헤더이고, tlsSettings.serverName은 TLS 서버 이름 검증에 사용됩니다. 둘이 같을 수도 있지만 배포 구조에 따라 다를 수도 있습니다. 두 필드를 하나처럼 취급해 동시에 바꾸면 한 계층은 통과하고 다른 계층은 실패할 수 있습니다.

서버 주소 address는 최초로 연결할 호스트를 결정하고, TLS 이름은 인증서와 핸드셰이크가 대상으로 삼을 이름을 결정하며, WebSocket Host는 HTTP 계층에서 처리됩니다. 문제를 점검할 때는 연결 수립 순서에 따라 이 세 항목을 이해해야 합니다. 주소로 TCP 연결은 되지만 TLS가 실패하면 시스템 시간, 서버 이름, 보안 매개변수를 확인하세요. TLS 성공 후 WebSocket이 거부되면 경로와 Host를 점검해야 합니다. 인증서 검증을 단순히 느슨하게 바꾸는 것은 오류를 숨기므로 일반적인 해결책으로 사용해서는 안 됩니다.

gRPC, mKCP 및 전송 전용 필드

gRPC 구성에는 대개 정확한 serviceName이 필요하며 HTTP/2 관련 협상에 의존합니다. 서비스 이름은 구성값이지 노드 메모가 아니며 URL 형식의 슬래시를 임의로 추가해서도 안 됩니다. 중간 계층이 필요한 연결 방식을 지원하지 않으면 핸드셰이크 직후 연결이 끊길 수 있습니다. mKCP는 UDP 기반 전송이므로 양쪽 매개변수뿐 아니라 현재 네트워크가 UDP를 안정적으로 전달할 수 있는지도 중요합니다. TCP에 연결할 수 있다고 해서 UDP 경로도 연결 가능하다는 뜻은 아닙니다.

전송 전용 매개변수가 많다면 클라이언트가 노드 정보에 따라 생성한 구조를 우선 사용하고, 명확한 요구가 있을 때만 수정하세요. 인터넷의 서로 다른 코어와 시기에 작성된 예제에는 이미 변경된 필드 이름이 포함될 수 있습니다. v2rayN은 일반적으로 데스크톱 코어 관리와 함께 사용되고, v2rayNG는 Xray 코어 경로를, v2flyNG는 V2Fly 코어를 대상으로 합니다. 같은 이름의 전송이라도 기본 개념은 비슷할 수 있지만 확장 필드가 완전히 같지는 않습니다. 지원 범위를 확신할 수 없다면 불필요한 확장을 먼저 제거하고 서버가 요구하는 핵심 필드만 유지하세요.

security, TLS 및 Reality의 계층

security는 사용할 보안 계층을 결정하며, 이에 대응하는 설정 객체도 일치해야 합니다. TLS 매개변수는 tlsSettings에, Reality 매개변수는 코어가 정한 독립 설정 객체에 둡니다. security 문자열만 바꾸고 기존 필드를 전부 재사용해서는 안 됩니다. 서버 이름, 공개 키 계열 매개변수, 짧은 식별자, 지문 선택은 특정 보안 방식의 핸드셰이크 조건이므로 동일한 유효 구성에서 가져와야 합니다.

보안 계층 오류와 사용자 식별자 오류는 인터페이스에서 모두 연결 테스트 실패로 나타날 수 있습니다. 따라서 로그에서 DNS, TCP, TLS, 프로토콜 인증이 각각 어느 단계에서 발생했는지 구분해야 합니다. 서버 포트에 연결조차 되지 않는다면 서버 이름을 계속 바꿔도 의미가 없습니다. TCP는 연결되었지만 보안 핸드셰이크가 실패했다면 먼저 라우팅 규칙을 수정해서는 안 됩니다. 장애가 발생한 계층을 특정한 뒤 매개변수를 바꾸면, 오류 형태만 잠시 바뀌고 근본 원인은 남는 일을 막을 수 있습니다.

계층 대표 필드 원격 측과 일치해야 하는 항목
연결 대상 addressport 호스트 및 수신 포트
전송 network 전송 유형, 경로 또는 서비스 이름
보안 계층 security 서버 이름 및 해당 핸드셰이크 매개변수
애플리케이션 프로토콜 protocolsettings 사용자 식별자 및 프로토콜 속성
08
VALIDATION WORKFLOW

구성 검증 및 문제 해결의 계층별 접근

효율적인 문제 해결은 매개변수를 계속 바꾸는 것이 아니라 연결이 어느 계층까지 진행되었고 어디에서 멈췄는지 확인하는 방식입니다. 구조, 수신, 해석, 라우팅, 아웃바운드, 애플리케이션 설정을 정해진 순서로 점검해야 합니다.

첫 번째 계층: JSON을 읽을 수 있는지 확인

시작에 실패하면 먼저 클라이언트 또는 코어 로그의 첫 번째 구조 오류를 확인하고 줄 번호와 필드 경로를 기록하세요. 흔한 문제로는 쉼표 누락, 괄호 유형 불일치, 닫히지 않은 문자열, 잘못된 객체에 필드 배치, 숫자를 문자열로 작성한 경우, 표준 JSON에 주석을 넣은 경우가 있습니다. 편집기가 표시한 오류 위치가 실제 오류의 다음 줄일 때도 있습니다. 파서가 이후 문자를 읽고 나서야 앞 항목이 완성되지 않았음을 알아채기 때문입니다. 따라서 오류 줄 이전 객체의 끝부분도 함께 확인해야 합니다.

구조적으로 유효하다고 해서 필드 의미까지 올바른 것은 아닙니다. 문법이 맞는 JSON에도 코어가 인식하지 못하는 필드, 잘못된 프로토콜 설정, 존재하지 않는 태그가 들어갈 수 있습니다. 이때는 로그의 객체 경로를 따라 해당 장으로 돌아가 필드가 인바운드, 아웃바운드, 전송 설정 중 어디에 속하는지 확인하세요. 클라이언트가 시작할 때마다 구성을 다시 작성한다면 생성된 결과물을 편집하고 있다는 뜻입니다. 클라이언트 인터페이스나 사용자 지정 구성 진입점으로 돌아가 원본 설정을 수정해야 합니다. 클라이언트를 처음 사용하는 전체 순서는 입문 가이드에서 확인할 수 있습니다.

{
  "log": {
    "access": "",
    "error": "",
    "loglevel": "warning"
  }
}

두 번째 계층: 올바른 인바운드로 연결되는지 확인

구성이 로드된 뒤 로컬 수신 주소와 포트가 나타나는지 확인하세요. 애플리케이션 프록시 주소는 인바운드와 일치해야 하며 SOCKS와 HTTP 유형도 혼용할 수 없습니다. 시스템 프록시를 켰는데 앱이 계속 직접 연결된다면 해당 앱이 시스템 설정을 읽는지 확인해야 합니다. 반대로 클라이언트에서 시스템 프록시를 껐더라도 브라우저 확장에 독립 프록시가 남아 있으면 트래픽이 이전 포트로 들어갈 수 있습니다. 문제를 해결하는 동안 진입 방식은 하나만 유지하면 중복 프록시와 불명확한 경로를 크게 줄일 수 있습니다.

포트가 수신되지 않으면 먼저 사용 중인 포트인지, 클라이언트 코어가 시작되었는지, 다른 프로세스가 구성을 읽고 있는지 확인하세요. 포트는 열려 있지만 로그에 접근 기록이 전혀 없다면 문제는 대개 애플리케이션과 인바운드 사이에 있습니다. 로그에 목적지 주소가 기록되었다면 진입점은 정상이며 라우팅과 아웃바운드를 계속 확인하면 됩니다. 모바일에서는 VPN 서비스 상태와 앱별 프록시 범위도 확인해야 합니다. 제외된 앱은 v2rayNG 또는 v2flyNG 코어 경로를 통과하지 않습니다.

세 번째 계층: DNS, 라우팅 및 아웃바운드 태그 추적

고정된 테스트 도메인 하나로 요청을 보내고, 코어가 도메인을 받았는지, 해석을 시작했는지, 어느 라우팅 규칙이 매칭되었는지, 어떤 아웃바운드를 선택했는지를 차례로 기록하세요. 도메인만 실패하고 IP는 성공한다면 DNS와 도메인 규칙을 중점적으로 확인합니다. 모든 목적지가 잘못된 아웃바운드로 들어간다면 포괄적인 규칙과 기본 경로를 확인하세요. 특정 앱만 실패한다면 인바운드 태그, 네트워크 유형, 스니핑 결과를 비교합니다. 계속 바뀌는 여러 테스트 사이트를 동시에 사용하지 마세요. 캐시, 주소 계열, 도메인 규칙의 차이가 불필요한 변수를 만들 수 있습니다.

라우팅이 올바르게 매칭되었는데 원격 아웃바운드가 실패한다면 주소 해석, 포트 접근성, 프로토콜 사용자 매개변수, 전송 유형, 보안 계층을 확인하세요. 문제를 해결하는 동안 로그 수준을 적절히 높일 수 있지만, 기록이 끝나면 일상 사용에 맞는 수준으로 되돌려야 중요한 이벤트가 많은 로그에 묻히지 않습니다. 로그에는 대상 도메인, 내부 주소, 로컬 경로가 포함될 수 있으므로 내용을 공유하기 전 문제와 관계없는 개인 구성 데이터를 삭제하세요.

네 번째 계층: 클라이언트 상태와 코어 상태 구분

v2rayN, v2rayNG, v2flyNG는 모두 클라이언트 관리 계층을 포함하며, 코어는 그중 연결 처리를 담당하는 일부입니다. 구독 업데이트 성공은 클라이언트가 구독을 가져와 해석했다는 뜻이지 모든 노드에 연결할 수 있다는 뜻은 아닙니다. 지연 시간 테스트 실패도 모든 앱 연결 실패와 같지 않습니다. 테스트 방식, 대상 주소, 실제 앱 프로토콜이 다를 수 있기 때문입니다. ‘구독이 업데이트되었는가’, ‘노드가 선택되었는가’, ‘코어가 시작되었는가’, ‘시스템 또는 VPN 진입점이 활성화되었는가’, ‘실제 요청이 통과했는가’를 나누어 판단해야 합니다.

v2rayN의 Avalonia 데스크톱 버전은 Windows, macOS, Linux를 지원하고 WPF 버전은 Windows 전용입니다. 두 배포 라인은 인터페이스와 시스템 통합 방식이 다릅니다. 데스크톱 버전을 선택할 때는 v2rayN 데스크톱 버전과 WPF 버전 비교를 참고하세요. Linux 설치와 로그인 세션 시작 설정은 Linux에서 v2rayN 설치하기에서 확인할 수 있습니다. 플랫폼 차이는 주로 클라이언트 외부 동작에 영향을 주며, 이를 근거로 노드 프로토콜 매개변수를 임의로 바꿔서는 안 됩니다.

되돌릴 수 있는 변경 기록 만들기

매번 하나의 논리 계층만 변경하고, 변경 전 작동하던 복사본을 저장하세요. 로컬 기록은 ‘구조 정리, 인바운드, DNS, 라우팅, 아웃바운드, 전송, 정책’ 순서로 이름을 붙이고 예상 결과와 실제 로그도 적어 두면 좋습니다. 한 번에 여러 필드를 바꾸면 연결이 복구되어도 실제 원인을 확인할 수 없어 이후 마이그레이션에서 같은 문제가 재발하기 쉽습니다. 구성을 복구할 때는 같은 라운드의 버전을 통째로 되돌려 이전 라우팅과 새 태그가 섞이지 않게 하세요.

구독으로 관리되는 노드는 클라이언트가 제공하는 편집 진입점에서 우선 조정하고, 구독 업데이트가 로컬 변경 사항을 덮어쓰는지 확인해야 합니다. 장기간 유지할 라우팅과 DNS 규칙은 임시 실행 파일을 반복해서 수정하지 말고 클라이언트가 지원하는 사용자 지정 구성 계층에 넣는 것이 좋습니다. 구성이 커지면 참조되지 않는 태그, 중복 규칙, 오래된 실험용 인바운드를 정기적으로 삭제하여 로그의 모든 경로가 현재 용도와 대응하도록 관리하세요.

01파싱JSON 및 필드 위치
02수신주소, 포트 및 진입점
03도메인 해석DNS 및 주소 계열
04규칙 매칭순서 및 태그 참조
05아웃바운드 연결프로토콜, 전송 및 보안 계층

참조 구성에서 클라이언트 작업으로 돌아가기

최소 구성이 작동하면 도메인 규칙, DNS 분할, 여러 아웃바운드, 정책 설정을 차례로 복원하고, 각 그룹을 복원할 때마다 동일한 테스트를 반복하세요. 특정 그룹을 복원한 뒤에만 문제가 생긴다면 조사 범위를 해당 그룹과 참조 객체로 좁힐 수 있습니다. 클라이언트를 다시 설치하거나 전환해야 한다면 클라이언트 다운로드 페이지에서 Windows, macOS, Android, Linux에 맞는 진입점을 선택하세요. 다운로드 페이지의 FAQ에는 설치 패키지 선택, CPU 아키텍처, 버전 전환에 관한 설명도 정리되어 있습니다.

구성 파일은 서로 참조하는 선언의 집합이지 고립된 매개변수 모음이 아닙니다. 인바운드 태그는 라우팅 조건에 영향을 주고, 라우팅 정책은 DNS를 호출할 수 있으며, DNS 조회에는 다시 아웃바운드가 필요합니다. 전송 및 보안 계층은 최종적으로 원격 연결 수립 여부를 결정합니다. 의존성의 흐름에 따라 읽으면 ‘연결할 수 없음’을 구조, 진입점, 해석, 규칙, 핸드셰이크 문제로 나누어 검증할 수 있습니다. 한 번 계층별 문제 해결 과정을 기록해 두면 이후 노드 마이그레이션과 클라이언트 업그레이드에도 같은 방법을 적용할 수 있어 무작위로 설정을 바꿀 필요가 없습니다.