이 글의 핵심

구독을 가져오는 데는 익숙하지만 생성된 설정 파일을 어디서부터 봐야 할지 막막한 사용자를 위한 글입니다. 요청이 인바운드, 라우팅, 아웃바운드를 거치는 순서에 따라 설명하고, 코어에서 읽을 수 있는 로컬 직결 예시를 제공합니다. VLESS와 VMess 매개변수를 어느 계층에 넣어야 하는지, 수정 후 JSON 문법·포트 충돌·규칙 순서 문제를 어떻게 찾는지도 다룹니다.

먼저 설정의 바깥 구조부터 이해하기

V2Ray와 Xray의 실행 설정은 보통 JSON을 사용합니다. 가장 흔한 최상위 객체는 log, inbounds, outbounds, routing, dns입니다. 요청이 어디로 들어오고 어떤 경로를 선택하며 어디로 나가는지를 실제로 결정하는 핵심은 inbounds, routing, outbounds 세 영역입니다.

하나의 연결을 고정된 데이터 흐름으로 생각할 수 있습니다. 브라우저나 다른 앱이 먼저 로컬 수신 포트에 연결하면 코어가 대상 주소를 식별하고 라우팅 규칙에 따라 아웃바운드를 선택합니다. 구독 노드는 주로 outbounds를 채우고, 클라이언트의 라우팅 모드는 routing을 생성하며, 시스템 프록시 설정은 앱의 트래픽을 inbounds로 전달합니다.

앱에서 요청 시작로컬 포트로 진입대상 주소 식별규칙에 따라 분기해당 아웃바운드 선택
10808
SOCKS 인바운드 예시 포트
10809
HTTP 인바운드에서 자주 쓰는 포트
127.0.0.1
로컬 전용 수신 주소
3단계
인바운드, 라우팅, 아웃바운드

아래 예시는 원격 노드를 포함하지 않고 SOCKS 요청을 로컬에서 바로 전송합니다. JSON 구조, 포트 수신, 라우팅 로드가 정상인지 확인할 때 적합합니다. 코어는 이 설정을 읽고 실행할 수 있지만 원격 프록시 기능은 제공하지 않습니다.

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      },
      "sniffing": {
        "enabled": true,
        "destOverride": ["http", "tls"]
      }
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom"
    },
    {
      "tag": "blocked",
      "protocol": "blackhole"
    }
  ],
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      }
    ]
  }
}

inbounds: 로컬 앱은 어디로 코어에 들어오는가

inbounds는 배열이므로 하나의 설정에서 여러 진입점을 동시에 수신할 수 있습니다. 예를 들어 SOCKS는 10808, HTTP는 10809에서 수신할 수 있습니다. 시스템 프록시는 보통 HTTP 진입점을 사용하며, SOCKS를 지원하는 앱은 127.0.0.1:10808에 직접 연결할 수도 있습니다. 실제 포트는 클라이언트가 생성한 설정을 기준으로 확인해야 하며, 모든 설치 환경이 같다고 가정해서는 안 됩니다.

listen은 수신 범위를 결정합니다. 127.0.0.1로 설정하면 로컬 프로그램만 연결할 수 있고, LAN 주소나 모든 주소에서 수신하도록 설정하면 접근 범위가 달라집니다. 일반적인 데스크톱 사용에서는 로컬 수신을 유지하면 됩니다. “연결이 거부됨” 오류가 발생하면 먼저 코어가 실행 중인지 확인하고, 앱에 입력한 포트가 실제 인바운드 포트와 일치하는지 점검하세요.

로컬 SOCKS 진입점

수신 주소
127.0.0.1
수신 포트
10808
프로토콜
socks
UDP
true

SOCKS5 설정을 지원하는 브라우저, 다운로드 도구, 명령줄 프로그램에 적합합니다.

로컬 HTTP 진입점

수신 주소
127.0.0.1
수신 포트
10809
프로토콜
http
용도
시스템 프록시

포트는 클라이언트 실행 로그와 생성된 설정을 기준으로 확인하세요.

SOCKS 진입점을 확인할 때는 먼저 코어 로그에 “127.0.0.1:10808에서 수신 대기”와 같은 기록이 표시되는지 확인한 다음 SOCKS5를 지원하는 도구로 해당 주소에 연결하세요. 도메인 규칙을 사용할 경우 테스트 도구가 도메인 해석을 프록시에 맡기도록 해야 합니다. 로컬에서 먼저 IP로 해석하면 도메인 매칭 조건이 사라질 수 있습니다.

outbounds: 원격 프로토콜 매개변수와 출구 태그

outbounds도 배열입니다. 첫 번째 아웃바운드는 보통 기본 출구 역할을 하며, 이후 항목은 직결·차단 또는 다른 노드로 사용할 수 있습니다. 각 아웃바운드는 tag, protocol, settings와 선택 사항인 streamSettings로 구성됩니다. routing에 서버 주소를 직접 입력하는 것이 아니라 outboundTag로 여기 정의된 아웃바운드를 선택합니다.

VLESS와 VMess의 계정 정보는 보통 settings.vnext에 저장되며 서버 주소, 포트, 사용자 식별자를 포함합니다. TCP, WebSocket, TLS 등의 전송 및 보안 매개변수는 streamSettings에 있습니다. 두 계층의 매개변수를 섞어서는 안 됩니다. 원격 계정이 올바르더라도 전송 경로가 잘못되면 핸드셰이크 단계에서 연결이 실패합니다.

VLESS + TCP + TLS

아웃바운드 프로토콜
vless
전송 방식
tcp
보안 계층
tls
사용자 암호화
none
자주 사용하는 포트
443

주소, 사용자 식별자, 서버 이름, 보안 매개변수는 서버 설정과 일치해야 합니다.

VMess + WebSocket + TLS

아웃바운드 프로토콜
vmess
전송 방식
ws
경로
/ws
보안 계층
tls
자주 사용하는 포트
443

WebSocket 경로, Host, TLS 서버 이름을 항목별로 대조해야 합니다.

{
  "tag": "proxy-main",
  "protocol": "vless",
  "settings": {
    "vnext": [
      {
        "address": "edge.example.com",
        "port": 443,
        "users": [
          {
            "id": "00000000-0000-4000-8000-000000000001",
            "encryption": "none"
          }
        ]
      }
    ]
  },
  "streamSettings": {
    "network": "tcp",
    "security": "tls",
    "tlsSettings": {
      "serverName": "edge.example.com"
    }
  }
}

위의 주소와 사용자 식별자는 필드 위치를 보여 주기 위한 예시일 뿐 실제 노드 연결에는 사용할 수 없습니다. 실제 설정은 구독 또는 서버 매개변수로 생성해야 합니다. 수동으로 확인할 때는 먼저 protocol, 다음으로 addressport, 그다음 사용자 식별자를 확인하고 마지막으로 network, TLS 서버 이름, WebSocket 경로를 점검하세요.

freedom은 대상에 직접 연결한다는 뜻이며 보통 direct 태그를 사용합니다. blackhole은 매칭된 연결을 종료할 때 사용하며 보통 blocked 태그를 지정합니다. 둘 다 원격 서버 매개변수가 필요하지 않습니다. 설정에 proxy, direct, blocked 세 종류의 아웃바운드를 함께 두어야 routing이 프록시·직결·차단을 각각 수행할 수 있습니다.

결론: 먼저 프로토콜 계층, 다음으로 전송 계층을 확인하세요

로그에 인증 또는 사용자 식별자 오류가 표시되면 settings를 확인하고, TLS·WebSocket 경로 또는 연결 종료 오류가 나타나면 streamSettings를 확인하세요. 포트를 계속 바꾸는 것보다 계층별로 원인을 좁히는 편이 효과적입니다.

routing: 규칙은 이름이 아니라 순서대로 매칭됩니다

routing.rules는 순서가 있는 규칙 배열입니다. 코어는 첫 번째 규칙부터 확인하며, 매칭되면 해당 규칙의 outboundTag를 사용합니다. 일반적으로 뒤의 규칙이 앞선 결과를 덮어쓰지 않으므로 더 구체적인 규칙은 앞에, 포괄적인 기본 규칙은 뒤에 배치해야 합니다.

type: "field"는 필드 조건으로 매칭한다는 뜻입니다. 자주 쓰는 조건은 domain, ip, port, network, inboundTag, protocol입니다. 하나의 규칙에 서로 다른 유형의 조건을 여러 개 넣으면 보통 모든 조건을 충족해야 하며, 같은 필드의 여러 값은 그중 하나와 일치하면 됩니다.

규칙 순서 매칭 조건 아웃바운드 태그 역할
1번째 규칙 domain: domain:example.net blocked 지정 도메인 차단
2번째 규칙 ip: geoip:private direct LAN 및 사설 주소 직결
3번째 규칙 domain: geosite:cn direct 해당 도메인 그룹 매칭
매칭되지 않음 명시적 조건 없음 기본 아웃바운드 보통 첫 번째 outbound 사용
{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": ["domain:example.net"],
        "outboundTag": "blocked"
      },
      {
        "type": "field",
        "ip": ["geoip:private"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": ["geosite:cn"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy-main"
      }
    ]
  }
}

domainStrategy: "AsIs"는 요청에 포함된 기존 도메인 또는 IP를 중심으로 처리합니다. IPIfNonMatch는 도메인 규칙이 매칭되지 않을 때 IP로 해석한 뒤 IP 규칙을 적용하려고 시도합니다. 전략을 선택할 때는 DNS 설정과 sniffing 결과를 함께 고려해야 하며, 단순히 더 많이 해석하는 옵션이 더 빠르다고 볼 수는 없습니다.

마지막 규칙인 network: "tcp,udp"는 포괄적인 기본 규칙입니다. 이를 첫 번째로 옮기면 대부분의 TCP와 UDP 요청이 proxy-main에 바로 매칭되어 뒤의 사설 주소 직결 규칙이 작동하지 않습니다. “규칙은 모두 있는데 분기가 적용되지 않는” 대표적인 원인입니다.

결론: 라우팅 이상이 생기면 첫 번째로 매칭된 규칙부터 확인하세요

대상 도메인, 해석 결과, 규칙 순서를 함께 점검하세요. 특정 규칙이 존재하는지만 확인해서는 부족합니다. 더 포괄적인 규칙보다 앞에 배치되어 있어야 하며, 실제로 존재하는 outbound 태그를 참조해야 합니다.

클라이언트가 생성한 설정은 어디를 수정해야 할까

v2rayN 7.x는 노드, 라우팅, 코어 옵션을 바탕으로 실행 설정을 생성합니다. 실행 중인 파일을 직접 수정하면 현재 프로세스에서만 적용될 수 있으며, 다음에 노드를 바꾸거나 구독을 업데이트하거나 코어를 재시작하면 다시 생성됩니다. 오래 유지할 설정은 가능한 한 클라이언트의 해당 메뉴에서 수정하세요.

기본 옵션은 「설정」→「매개변수 설정」에서 확인할 수 있습니다. 노드 매개변수는 「서버」 목록에서 대상을 선택한 뒤 편집 화면으로 들어가 조정합니다. 라우팅 관련 설정은 「설정」→「라우팅 설정」에서 관리하세요. 버전에 따라 메뉴 이름이 조금 다를 수 있지만 수정 대상은 인바운드, 노드 아웃바운드, 라우팅 규칙의 세 계층으로 동일합니다.

  1. 현재 정상 작동하는 설정을 먼저 복사하거나 클라이언트 설정을 내보내 복원 기준을 남겨 두세요.
  2. 한 번에 필드 하나만 수정하세요. 예를 들어 수신 포트만 바꾼 뒤 즉시 저장하고 코어를 재시작합니다.
  3. 먼저 JSON을 로드할 수 있는지 확인하고, 다음으로 로컬 포트를 테스트한 뒤, 마지막으로 특정 도메인의 라우팅 결과를 확인하세요.
  4. 라우팅을 수정했다면 대상 도메인, 매칭된 규칙, 최종 outboundTag를 기록하세요.
  5. 구독을 업데이트한 뒤 사용자 지정 설정을 다시 확인해 클라이언트가 로컬 변경 사항을 구독 필드로 덮어쓰지 않았는지 확인하세요.

v2rayNG는 Xray 코어를 사용할 때 해당 실행 설정을 생성하며 필드 구성 방식은 데스크톱 버전과 비슷합니다. v2flyNG는 v2fly 코어를 사용할 때 해당 코어가 실제로 지원하는 프로토콜과 필드를 기준으로 해야 합니다. 일부 Xray 확장 매개변수는 v2fly 코어 설정에 그대로 복사할 수 없으므로 알 수 없는 필드 오류가 발생하면 먼저 코어 계열을 확인하세요.

로드 실패와 라우팅 이상을 점검하는 순서

설정 문제는 JSON 파싱 실패, 코어는 실행되지만 인바운드를 사용할 수 없는 경우, 코어와 인바운드는 정상이나 라우팅 결과가 예상과 다른 경우의 세 가지로 나눌 수 있습니다. 이 순서대로 확인하면 문법 오류를 노드 장애로 잘못 판단하는 일을 피할 수 있습니다.

저장 후 코어가 즉시 종료되면 어디부터 확인해야 할까?

먼저 코어 로그 앞부분의 오류 행을 확인하세요. invalid character, unexpected token 또는 구분자 누락 메시지가 표시되면 큰따옴표·쉼표·대괄호를 점검합니다. JSON의 마지막 항목 뒤에는 쉼표를 남길 수 없습니다.

10808 포트에 연결할 수 없을 때는 어떻게 해야 할까?

inbounds에서 listen이 127.0.0.1이고 port가 10808인지 확인한 뒤, 로그에 address already in use가 표시되는지 살펴보세요. 포트가 사용 중이면 10810으로 변경하고 앱의 SOCKS 주소도 함께 수정해야 합니다.

노드는 정상인데 특정 도메인이 직결되지 않을 때는?

도메인이 sniffing으로 인식되었는지 확인한 다음, 포괄적인 프록시 규칙이 직결 규칙보다 앞에 있는지 살펴보세요. 구체적인 domain 규칙을 network 기본 규칙 위로 옮기고 코어를 재시작한 뒤 연결을 다시 만드세요.

로그에 outboundTag를 찾을 수 없다고 표시될 때는?

routing의 outboundTag와 outbounds의 tag를 한 글자씩 대조하세요. proxy-main, proxy_main, Proxy-Main은 서로 다른 이름으로 처리됩니다. 아웃바운드를 삭제할 때는 이를 참조하는 규칙도 함께 정리해야 합니다.

도메인 규칙은 있는데 IP 규칙이 매칭되지 않을 때는?

domainStrategy를 확인하세요. 도메인이 매칭되지 않은 뒤 IP를 계속 해석해야 한다면 IPIfNonMatch를 사용할 수 있으며 DNS가 결과를 반환하는지도 확인해야 합니다. 수정 후에는 기존 연결을 끊고 다시 테스트해 이전 세션을 재사용하지 않도록 하세요.

포트 테스트가 통과한 뒤에는 원격 핸드셰이크 로그를 확인하세요. VLESS와 VMess의 주소, 포트, 사용자 식별자, 전송 방식, 보안 계층이 완전한 조합을 이루어야 합니다. 한 필드만 바꾸면 TCP 연결은 성공하더라도 TLS, WebSocket 또는 프로토콜 인증 단계에서 중단될 수 있습니다.

routing을 확인할 때 웹페이지가 열리는지만 보지 마세요. 코어 액세스 로그에서 대상 도메인 또는 IP에 대응하는 outboundTag를 확인하는 것이 더 정확합니다. 규칙을 수정한 뒤에는 기존 연결을 닫고 새로 요청해야 합니다. 이미 연결된 장시간 연결은 새 아웃바운드로 자동 전환되지 않습니다.

설정을 이해하는 핵심은 모든 필드를 외우는 것이 아니라 계층을 명확히 구분하는 데 있습니다. inbounds는 “트래픽이 어떻게 들어오는가”, outbounds는 “트래픽이 어디로 나가는가”, routing은 “이 요청이 어느 출구를 선택하는가”를 담당합니다. 오류가 발생하면 실제 요청 흐름을 따라 각 계층을 점검하세요. 대부분 하나의 포트, 규칙 하나 또는 프로토콜 매개변수 묶음으로 원인을 좁힐 수 있습니다.