JSON 설정 가이드

로컬 인바운드부터 아웃바운드 선택까지, 필드별 설정 구조와 처리 순서, 클라이언트 적용 범위를 살펴봅니다.

처음 설정한다면 먼저 사용 가이드에서 가져오기, 모드 선택, 연결 확인을 마치세요. 이 페이지에서는 설정이 적용되는 원리와 서로 연관된 필드, 변경 후 오류를 찾는 방법을 자세히 살펴봅니다. 데스크톱 예시는 주로 v2rayN을 기준으로 합니다. 설치 방법은 클라이언트 및 플랫폼 다운로드를 참고하세요.

JSON 구조와 처리 흐름

클라이언트와 코어 구분하기

v2rayN, v2rayNG, v2flyNG는 설정을 관리하는 인터페이스를 제공하고, 코어는 포트를 열어 프로토콜을 처리하고 연결을 전달합니다. 인터페이스에 표시되는 노드 정보는 대개 코어 전체 설정과 다릅니다. 클라이언트는 노드, 라우팅 템플릿, 로컬 리스닝 설정, 실행 옵션을 조합해 실행 파일을 만듭니다. 따라서 임시로 생성된 JSON을 수정해도 다음 실행 때 변경 사항이 유지된다는 보장은 없습니다. 내용을 살펴보기 전에 노드 정보, 사용자 지정 설정, 클라이언트가 생성한 실행 설정 중 무엇을 보고 있는지 확인하세요.

V2Fly와 Xray는 설정의 공통 기반을 공유하지만 완전히 같은 인터페이스로 볼 수는 없습니다. 지원 프로토콜, 전송 필드, DNS 확장 기능, 기본 동작이 다를 수 있습니다. 이 문서에서는 두 코어에서 공통으로 사용하는 구조를 우선 설명하고, 특정 프로토콜을 다룰 때는 적용 범위를 명확히 구분합니다. 서로 다른 코어의 예제를 잘라 붙인 뒤 오류가 나는 필드를 하나씩 지우는 방식은 피하세요. 실행에 성공해도 의도한 연결 경로로 동작한다는 뜻은 아닙니다.

최소 로컬 테스트 설정

아래 설정은 로컬 루프백 주소에서 SOCKS 인바운드를 열고, 받은 연결을 목적지로 직접 전달합니다. 설정 구조와 포트, 애플리케이션의 프록시 설정을 확인하기 위한 예제로 원격 노드 테스트용은 아닙니다. 실행 전에 포트가 비어 있는지 확인하세요. 클라이언트가 같은 이름의 리스너를 이미 생성했다면, 클라이언트에서 지원하는 사용자 지정 설정 메뉴로 별도 테스트해 두 프로세스가 같은 포트를 사용하지 않도록 하세요.

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "socks-local",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    }
  ]
}

연결 처리 과정은 애플리케이션이 인바운드에 연결하고, 인바운드가 목적지를 파악한 뒤, 라우팅이 아웃바운드를 선택하고, 아웃바운드가 연결을 만드는 순서로 볼 수 있습니다. DNS는 도메인 이름을 해석하지만 모든 요청이 설정된 내부 DNS를 거치는 것은 아닙니다. 로그는 문제를 기록하고 policy는 연결 동작을 제어합니다. 각 역할을 구분해야 문제가 입구, 라우팅 결정, 출구 중 어디에서 발생했는지 파악할 수 있습니다. 모든 접속 실패를 노드 문제로만 돌려서는 안 됩니다.

객체, 배열, 데이터 형식

최상위 요소는 객체입니다. inbounds와 outbounds는 여러 입구와 출구를 선언할 수 있어 배열로 구성됩니다. routing, dns, policy는 일반적으로 객체입니다. 배열 순서는 라우팅 규칙처럼 실제 처리에 영향을 줄 수 있지만, 객체의 필드 순서는 보통 실행 순서를 결정하지 않습니다. 최상위 설정 항목의 위치를 바꿔도 DNS가 라우팅보다 먼저 또는 나중에 처리되지는 않습니다.

엄격한 JSON에서는 필드 이름과 문자열을 큰따옴표로 묶고, 끝에 쉼표를 붙이거나 주석을 넣을 수 없습니다. 포트 같은 숫자를 임의로 문자열로 바꾸지 말고, 불리언 값은 true 또는 false로 작성하세요. 일부 로더는 느슨한 문법을 허용할 수 있지만, 호환성 높은 설정을 위해서는 엄격한 JSON을 사용해야 합니다. 특히 같은 객체에 동일한 필드를 중복 작성하지 마세요. 일부 파서는 마지막 값만 남기므로 파일이 읽히더라도 앞서 입력한 설정이 덮어써질 수 있습니다.

tag는 설정 내부에서 참조하는 이름이지 프로토콜 종류가 아닙니다. 아웃바운드 이름은 direct 외에 원하는 이름을 사용할 수 있지만, 라우팅 규칙에서는 정확히 같은 문자열을 참조해야 합니다. 대소문자, 공백, 철자 차이로도 참조가 실패할 수 있습니다. 규칙을 작성하기 전에 인바운드와 아웃바운드 태그를 목록으로 정리하세요. 한 번에 설정 항목 하나만 수정하고 복구 가능한 사본을 보관하면 실행 파일 전체를 한꺼번에 바꾸는 것보다 문제 원인을 찾기 쉽습니다.

inbounds 인바운드 설정

리스닝 주소로 인바운드 범위 정하기

인바운드는 코어가 연결을 받는 방식을 정의하며, 연결이 최종적으로 어떤 서버를 향할지는 결정하지 않습니다. listen은 바인딩할 로컬 주소, port는 리스닝 포트, protocol은 입구 프로토콜입니다. 현재 기기에서만 사용할 때는 127.0.0.1에 바인딩하는 것이 좋습니다. 이 주소는 원격 서버 주소와 무관하므로 구독 정보의 서버 도메인을 여기에 입력하면 안 됩니다. 본인 기기에 속하지 않은 주소에 바인딩하려고 해 리스닝이 실패할 수 있습니다.

0.0.0.0에 바인딩하면 모든 로컬 IPv4 인터페이스에서 연결을 받으므로 같은 네트워크의 다른 기기에서도 인바운드에 접근할 수 있습니다. 실제 접근 가능 여부는 방화벽과 네트워크 분리 설정에 달려 있지만, 방화벽이 설정 인증을 대신해 주지는 않습니다. 로컬 네트워크에서 공유해야 한다면 허용할 출발지를 제한하고 적절한 인증을 설정한 뒤 리스닝 인터페이스를 확인하세요. 연결 문제를 해결하려고 모든 인터페이스를 먼저 열면 접근 범위만 불필요하게 넓어질 수 있습니다.

필드역할중점 확인 사항
tag인바운드 식별라우팅의 inboundTag와 일치하는지 확인
listen로컬 주소 바인딩로컬 사용 시 루프백 주소 우선
port리스닝 포트애플리케이션 설정과 일치하고 사용 중이 아닌지 확인
settings프로토콜별 매개변수다른 프로토콜 설정을 그대로 적용할 수 없음
sniffing트래픽 목적지 식별 시도식별 결과와 실제 연결 목적지 구분

SOCKS 및 HTTP 인바운드

SOCKS 인바운드는 SOCKS 프록시를 지원하는 애플리케이션에, HTTP 인바운드는 HTTP 프록시 설정을 사용하는 애플리케이션에 적합합니다. 두 인바운드 모두 로컬 주소를 사용할 수 있지만 프로토콜은 서로 호환되지 않습니다. 애플리케이션에서 HTTP 프록시를 선택하고 SOCKS 리스닝 포트를 지정하면 TCP 연결은 성립해도 이후 핸드셰이크가 실패할 수 있습니다. 이때는 원격 노드를 바꾸기보다 애플리케이션의 프록시 종류와 인바운드 프로토콜이 일치하는지 먼저 확인하세요.

{
  "inbounds": [
    {
      "tag": "http-local",
      "listen": "127.0.0.1",
      "port": 10809,
      "protocol": "http",
      "settings": {}
    }
  ]
}

이 HTTP 인바운드는 첫 번째 장의 SOCKS 인바운드와 함께 사용할 수 있지만, 동일한 inbounds 배열에 합쳐야 합니다. 최상위에 같은 이름의 필드를 하나 더 추가하면 안 됩니다. 두 인바운드에는 서로 다른 포트를 지정하세요. 클라이언트 인터페이스가 포트를 자동으로 관리한다면 임시 파일만 수정하지 말고 인터페이스에서 변경하는 것이 좋습니다. 애플리케이션 포트, 클라이언트 설정, 실행 로그에 표시된 실제 리스닝 주소가 서로 일치하는지 확인하세요.

SOCKS 설정의 udp: true는 해당 인바운드에서 관련 UDP 전달 기능을 허용한다는 뜻일 뿐, 모든 애플리케이션의 UDP가 자동으로 코어에 전달된다는 뜻은 아닙니다. 애플리케이션이 해당 프록시 방식을 지원해야 하고, 이후 아웃바운드와 원격 서비스도 이를 지원해야 합니다. 일반적인 시스템 HTTP 프록시는 모든 UDP 트래픽을 가로채지 않습니다. 음성 통화나 다른 UDP 애플리케이션의 문제를 확인할 때는 이 불리언 필드의 유무만 보지 말고 트래픽이 실제로 인바운드에 들어오는지부터 확인하세요.

스니핑과 라우팅의 적용 범위

sniffing은 지원되는 프로토콜의 핸드셰이크에서 도메인 이름을 식별할 수 있습니다. 흔히 HTTP와 TLS를 대상으로 합니다. 하지만 모든 트래픽 내용을 분석하는 기능은 아니며, 모든 연결에서 도메인을 알아낼 수 있는 것도 아닙니다. 애플리케이션이 IP 주소로 직접 연결하고 핸드셰이크에 식별 가능한 호스트 이름이 없다면 도메인 규칙이 일치하지 않을 수 있습니다. 따라서 스니핑을 켜면 도메인 기반 분기가 반드시 성공한다고 볼 수 없습니다. 접속 로그에서 실제로 식별된 결과를 확인하세요.

일부 코어는 스니핑 결과를 라우팅에만 사용하고 실제 연결 목적지는 바꾸지 않는 기능을 지원합니다. 관련 필드와 동작은 사용 중인 코어의 최신 규격을 확인하세요. 이 문서의 공통 예제에는 이러한 확장 기능을 넣지 않았습니다. 사용 전에 라우팅 근거를 보완하려는 것인지 연결 목적지를 바꾸려는 것인지부터 명확히 하세요. 두 가지를 혼동하면 로그에는 도메인 규칙이 정상적으로 일치한 것처럼 보여도 실제 해석이나 연결 대상이 달라질 수 있습니다. 특히 로컬 서비스와 특정 IP에 영향을 줄 수 있습니다.

outbounds 아웃바운드 설정

아웃바운드와 기본 선택

아웃바운드는 이미 수신한 연결을 코어가 처리하는 방식을 설명합니다. 목적지에 직접 연결하거나 원격 프록시 서버를 통해 전달하거나 연결을 차단할 수 있습니다. 일치하는 규칙이 없으면 일반적으로 outbounds 배열의 첫 번째 아웃바운드를 사용합니다. 따라서 배열의 첫 번째 객체는 단순한 표시 순서가 아니라 기본 동작의 일부입니다. 직접 연결 항목을 첫 번째로 옮기면 이전에는 규칙이 적용되지 않던 연결이 직접 연결로 바뀔 수 있습니다.

tag는 각 아웃바운드를 참조할 이름이고, protocol은 사용할 아웃바운드 프로토콜을 정하며, settings 구조는 프로토콜에 따라 달라집니다. 라우팅의 outboundTag는 프로토콜 이름이 아니라 태그를 참조합니다. 하나의 설정에서 동일한 프로토콜을 쓰는 아웃바운드를 여러 개 만들 수 있지만 태그는 고유해야 합니다. 태그가 중복되면 규칙의 참조 대상을 명확히 구분할 수 없고 클라이언트의 설정 생성 과정에서 기존 객체가 덮어써질 수도 있습니다.

{
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ]
}

freedom은 현재 기기에서 목적지에 직접 연결한다는 뜻입니다. 이를 보고 요청이 어떤 DNS를 사용하는지 단정할 수는 없습니다. blackhole은 규칙에 일치하는 연결을 버리며, 애플리케이션에서는 시간 초과나 연결 실패로 나타날 수 있습니다. 위의 조각만 사용하면 기본 아웃바운드는 직접 연결이고, 차단 아웃바운드는 규칙으로 선택된 경우에만 사용됩니다. 아웃바운드를 선언하는 것만으로 트래픽이 자동으로 그곳을 통과하지는 않습니다. 기본 순서와 라우팅 참조를 모두 확인하세요.

원격 노드 매개변수는 서로 추정할 수 없습니다

VMess, VLESS, Trojan 등의 프록시 아웃바운드는 서버와 설정이 일치해야 합니다. 서버 주소, 포트, 사용자 인증 정보, 전송 방식, 보안 계층은 서로 다른 항목이므로 한 필드의 값으로 다른 필드를 추측할 수 없습니다. 주소가 맞아도 전송 경로가 다르거나 인증 정보가 맞아도 보안 계층이 일치하지 않으면 연결이 실패합니다. 실제 노드는 유효한 링크나 구독을 클라이언트로 가져오는 것이 좋습니다. 웹페이지의 일부 설정을 보고 알 수 없는 매개변수를 직접 입력하지 마세요.

일반적인 프록시 아웃바운드에서는 전송 방식과 보안 계층을 streamSettings로 지정하기도 합니다. 프로토콜은 프록시 요청을 어떻게 캡슐화하는지, 전송 방식은 바이트 스트림을 어떻게 전달하는지, 보안 계층은 연결을 어떻게 보호하거나 검증하는지를 다룹니다. 임의로 조합할 수 있는 세 가지 스위치가 아닙니다. 서버가 특정 조합만 지원한다면 클라이언트도 동일하게 설정해야 합니다. 보안 필드를 모두 켠다고 호환성이 자동으로 높아지는 것은 아니며, 서버가 이해하지 못하는 핸드셰이크가 만들어질 수 있습니다.

연결 주소와 TLS의 서버 이름도 구분해서 이해해야 합니다. 연결 주소는 네트워크 연결에 사용하고, 서버 이름은 서버 인증과 핸드셰이크에 사용됩니다. 두 값은 다를 수 있지만 서비스 설정 및 인증서 조건에 맞아야 합니다. 인증서 오류가 나면 이름, 기기 시간, 서버 인증서 체인을 확인하세요. 인증서 검증 건너뛰기를 일반적인 해결책으로 사용하지 마세요. 인증 조건을 바꾸는 데다 서버 이름을 잘못 입력한 문제를 가릴 수 있습니다.

코어와 아웃바운드의 지원 범위

v2rayNG는 Xray 코어를 사용하고, v2flyNG는 V2Fly 코어 기반 클라이언트입니다. v2rayN에서 실제로 어떤 코어를 사용하는지는 현재 설정과 실행 로그를 확인하세요. 공유 링크를 인터페이스가 인식하더라도 현재 선택한 코어가 모든 필드를 지원한다는 뜻은 아닙니다. 알 수 없는 프로토콜이나 지원되지 않는 전송 매개변수가 나오면 먼저 코어 계열을 확인하고, 필요한 경우 호환되는 설정을 선택하세요. 프로토콜 이름만 바꿔 노드를 변환할 수는 없습니다.

아웃바운드에는 UDP 전달, 다중화, 연결 재사용, 소켓 옵션이 포함될 수도 있습니다. 이러한 기능은 코어와 프로토콜, 서버의 조합에 따라 달라지므로 최소 설정에서 한꺼번에 켜지 않는 것이 좋습니다. 문제를 찾을 때는 클라이언트가 생성한 기본 아웃바운드로 단일 연결이 되는지 확인한 뒤 확장 설정을 하나씩 되돌리세요. 그렇지 않으면 한 번의 요청 실패에 인바운드 UDP, 원격 프로토콜, 하위 네트워크가 함께 얽혀 로그만으로 어느 단계에서 문제가 시작됐는지 파악하기 어렵습니다.

여러 노드를 관리할 때는 클라이언트 인터페이스에서 선택한 ‘현재 노드’와 코어 설정의 ‘여러 아웃바운드’를 구분해야 합니다. 인터페이스에서 노드를 바꾸면 프록시 출구 하나가 새로 생성될 수도 있고, 참조 중인 특정 아웃바운드만 바뀔 수도 있습니다. 구체적인 동작은 클라이언트에 따라 다릅니다. 구독을 업데이트한 뒤에는 태그와 규칙 참조가 그대로 있는지 다시 확인하세요. 코어 간 관계는 Project V, V2Fly, Xray의 분기 흐름에서 살펴본 다음 클라이언트를 선택할 수 있습니다.

routing 라우팅 규칙

규칙 순서와 조건 관계

routing.rules는 순서가 있는 규칙 배열입니다. 코어는 규칙을 순서대로 확인해 일치하는 항목을 찾으면 해당 아웃바운드를 선택하고, 일치하는 규칙이 없으면 기본 아웃바운드를 사용합니다. 구체적이고 범위가 좁은 조건은 앞에, 기본 처리용 조건은 뒤에 두세요. 첫 번째 규칙이 특정 인바운드의 모든 TCP와 UDP를 이미 처리한다면 뒤에 같은 인바운드의 도메인 규칙을 추가해도 적용되지 않습니다. 더 구체적인 규칙이라고 우선순위가 자동으로 높아지지는 않습니다.

한 규칙에 서로 다른 조건 필드를 지정하면 보통 모든 조건을 동시에 충족해야 합니다. 같은 필드의 배열에 여러 항목을 넣으면 대개 그중 하나와 일치하면 됩니다. 예를 들어 inboundTag와 domain을 함께 지정하면 특정 인바운드로 들어오면서 대상 도메인도 일치하는 연결을 뜻합니다. 인바운드 또는 도메인 중 하나만 일치하면 되는 조건이 아닙니다. 서로 독립된 두 가지 상황을 처리하려면 조건을 한 객체에 몰아넣지 말고 규칙 두 개로 나누세요.

{
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "ip": ["127.0.0.0/8", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": ["full:example.com"],
        "outboundTag": "block"
      }
    ]
  }
}

이 조각은 세 번째 장에서 선언한 direct와 block에 의존합니다. 첫 번째 규칙은 지정된 IPv4 주소 범위를 처리하고, 두 번째 규칙은 정확히 일치하는 도메인만 차단합니다. 모든 사설 네트워크를 망라하거나 IPv6 전체를 다루는 설정은 아닙니다. 예제에서 AsIs를 사용하므로 아직 해석되지 않은 내부 도메인이 최종 IP를 기준으로 첫 번째 규칙에 자동으로 일치한다고 볼 수 없습니다. 목적지가 어떤 형태로 전달되는지도 규칙 조건의 일부입니다.

도메인 규칙과 리소스 파일

full:example.com은 정확히 일치하는 도메인을, domain:example.com은 해당 도메인과 하위 도메인을 대상으로 합니다. 전체 URL을 도메인 필드에 입력하지 마세요. 프로토콜 접두사, 경로, 쿼리 매개변수는 도메인에 포함되지 않습니다. 루트 도메인과 하위 도메인을 모두 처리하려면 일치 문법을 명확히 선택하세요. 정규식은 특정한 패턴이 필요할 때만 사용하는 것이 좋습니다. 일반 도메인에는 명시적인 접두사를 사용하면 검토하기 쉽고 범위가 의도치 않게 넓어지는 위험도 줄일 수 있습니다.

geosite:와 geoip:는 분류 리소스를 참조합니다. 코어가 임의의 한국어 분류 이름을 알아서 처리하는 것은 아닙니다. 리소스 파일이 존재해야 하고, 해당 범주가 파일에 실제로 포함되어야 합니다. 클라이언트마다 사용하는 규칙 리소스의 출처가 다를 수도 있습니다. 리소스 로드에 실패하면 먼저 파일 위치와 범주 철자를 확인하세요. 원격 연결을 시작하기도 전에 규칙 리소스 로드에서 실패했을 수 있으므로 아웃바운드 주소를 바꾸는 것은 해결책이 아닙니다.

domainStrategy의 DNS 조회 범위

AsIs는 원래 목적지 정보를 최대한 그대로 라우팅에 사용합니다. IPIfNonMatch는 도메인 규칙이 일치하지 않을 때 이름을 해석한 뒤 IP 조건을 확인할 수 있고, IPOnDemand는 매칭 중 IP 조건이 필요할 때 해석을 시작할 수 있습니다. 뒤의 두 옵션은 라우팅 단계에서 필요한 DNS 조회에 영향을 줍니다. ‘전체 프록시’나 ‘직접 연결 모드’와 같은 뜻이 아니며, 원격 프록시 서버가 최종 목적지를 어디서 해석하는지도 직접 결정하지 않습니다.

클라이언트 인터페이스의 라우팅 모드는 단일 domainStrategy 값이 아니라 전체 규칙 템플릿을 가리키는 경우가 많습니다. 모드를 변경하면 규칙 순서, 기본 아웃바운드, 분류 리소스가 함께 바뀔 수 있습니다. 분기 동작을 확인하려면 최종 생성된 routing을 살펴보고 대상 도메인, 인바운드 태그, 선택된 아웃바운드, 규칙 위치를 기록하세요. 브라우저에서 페이지가 열리는지만으로는 기본 아웃바운드가 사용됐는지 특정 규칙이 일치했는지 구분할 수 없습니다.

작은 테스트 목록을 만들어 정확한 도메인, 하위 도메인, 직접 IP, 로컬 서비스를 각각 확인하세요. 한 번에 규칙 하나만 변경해야 합니다. 접속 로그에 IP만 표시된다면 애플리케이션이 코어에 들어오기 전에 이름을 해석했는지, 인바운드가 도메인 정보를 제공하는지 확인하세요. DNS와 라우팅은 함께 동작하지만 서로를 대신할 수 없습니다. DNS 기반 분기 방법은 V2Ray DNS 분기 설정 가이드에서 자세히 확인할 수 있습니다.

dns DNS 설정

먼저 DNS 조회를 시작한 계층 확인

한 번의 접속에도 여러 DNS 조회가 발생할 수 있습니다. 시스템이 애플리케이션의 목적지를 해석하거나, 코어가 라우팅을 위해 도메인을 조회하거나, 아웃바운드가 원격 서버 주소를 해석하거나, 원격 서비스가 최종 목적지를 해석할 수 있습니다. dns 설정은 코어 내부의 이름 해석 방식을 정의할 뿐 시스템과 모든 애플리케이션의 DNS 조회를 자동으로 가로채지는 않습니다. 문제를 확인할 때는 먼저 ‘어떤 프로세스가 어떤 이름을 조회했는지’를 파악하세요. 그렇지 않으면 브라우저의 조회 결과를 코어 DNS의 결과로 오해하기 쉽습니다.

인바운드가 도메인 이름을 받으면 코어는 이를 도메인 그대로 프록시 아웃바운드에 전달할 수도 있습니다. 인바운드가 IP만 받으면 DNS 도메인 분기 규칙에 사용할 원래 이름이 없을 수 있습니다. 라우팅 정책, 직접 연결 아웃바운드의 DNS 옵션, 클라이언트의 네트워크 가로채기 방식도 실제 조회 경로에 영향을 줍니다. 따라서 DNS 주소를 바꾼 뒤 접속 경로가 달라지지 않아도 설정이 적용되지 않았다고 단정할 수는 없습니다. 해당 요청이 내부 DNS를 사용하지 않았을 수도 있습니다.

servers, hosts 및 조회 유형

{
  "dns": {
    "hosts": {
      "full:example.com": "192.0.2.1"
    },
    "servers": [
      "localhost"
    ],
    "queryStrategy": "UseIPv4"
  }
}

이 조각은 정적 매핑과 시스템 DNS 조회 진입점을 보여줍니다. 192.0.2.1은 문서용 예시 주소이며 실제 웹사이트 주소가 아닙니다. 이 매핑을 남겨 두면 내부 DNS에 의존하는 연결이 정상적으로 접속되는지 확인할 수 없습니다. localhost는 시스템의 DNS 조회 방식을 사용한다는 뜻이지, 임의의 로컬 UDP 포트로 요청을 보낸다는 뜻이 아닙니다. 실제로 사용하려면 예시 매핑을 삭제하고 환경에 맞는 DNS 방식을 선택하세요.

hosts는 특정 이름의 조회 결과를 고정할 수 있어 문제 확인이나 내부 도메인 처리에 유용하지만, 해당 이름의 일반적인 동적 조회를 우회하게 됩니다. 서버 주소가 바뀐 뒤에도 예전 매핑이 남으면 잘못된 주소를 계속 가리킬 수 있습니다. 특정 도메인이 계속 이상한 주소로 해석된다면 코어 매핑뿐 아니라 시스템 hosts 파일과 애플리케이션 캐시도 확인하세요. 구독만 새로 고쳐서는 해결되지 않습니다. 세 계층은 서로 별개이므로 한 곳을 수정해도 다른 곳의 설정은 그대로 남습니다.

queryStrategy는 내부 DNS 조회에 사용할 주소 계열을 정합니다. 예를 들어 UseIPv4, UseIPv6, UseIP를 사용할 수 있습니다. 시스템의 네트워크 프로토콜을 바꾸는 옵션도 아니고 모든 연결이 한 주소 계열만 사용하도록 보장하지도 않습니다. 기기에 IPv6 주소가 있지만 연결 경로를 사용할 수 없다면 DNS 조회와 실제 연결을 따로 확인하세요. AAAA 레코드가 반환됐다는 사실은 조회가 성공했다는 뜻일 뿐 해당 주소로 연결할 수 있다는 의미는 아닙니다.

도메인별 DNS 서버 선택

servers 배열에는 서버 객체를 넣을 수 있으며, 흔히 address, domains, expectIPs 필드를 사용합니다. domains는 해당 서버에서 우선 처리할 도메인 범위를 지정하고, expectIPs는 허용할 결과 주소 범위를 제한합니다. 후자는 도메인에 IP를 정적으로 지정하는 설정도, 아웃바운드 규칙도 아닙니다. 결과가 필터링된 뒤 다른 서버로 다시 조회하는지는 다른 서버 설정과 사용 중인 코어의 대체 조회 설정에 따라 달라집니다.

범위가 넓은 도메인 집합에 지나치게 좁은 예상 IP 조건을 적용하지 마세요. 콘텐츠 전송 네트워크, IPv4·IPv6 병행 구성, 서비스 이전에 따라 정상적인 조회 결과도 달라질 수 있습니다. 엄격한 필터가 정상 응답을 차단해 원격 노드를 사용할 수 없는 것처럼 보일 수 있습니다. 설정 전에 분류 규칙과 실제 주소 분포를 확인하고, 설정 후에는 허용되거나 제외된 결과를 기록하세요. 이런 정보가 없다면 먼저 범위를 좁힌 규칙으로 확인하는 것이 좋습니다.

일반 DNS, 암호화 DNS, 로컬 시스템 조회는 서로 다른 연결 경로를 사용할 수 있습니다. 주소 표기 방식에 따라 일반 아웃바운드 처리를 우회하기도 하고 코어 라우팅에 참여하기도 합니다. 구체적인 동작은 현재 코어의 서버 주소 규격에 따라 확인해야 합니다. ‘암호화’라는 말만으로 프록시를 반드시 거친다고 추측할 수는 없습니다. DNS 서버 연결에 프록시가 필요하고 프록시 서버 이름을 다시 해당 DNS로 해석해야 한다면 시작 시점에 의존성 순환이 생깁니다. 서버 이름을 별도로 조회할 수 있는 경로를 먼저 마련하세요.

policy 연결 및 통계 정책

레벨은 라우팅 우선순위가 아닙니다

policy는 연결 수명과 일부 통계 동작을 설정하며 노드를 선택하지는 않습니다. levels 아래의 키는 사용자 레벨 번호이며, JSON 객체의 키이므로 문자열로 작성해야 합니다. 프로토콜 사용자나 해당 인바운드 설정에서 사용자 레벨을 참조할 수 있지만 참조 필드는 프로토콜마다 다릅니다. 레벨을 따로 지정하지 않으면 보통 기본 레벨이 사용됩니다. 숫자가 클수록 빨라지는 것도 아니며 라우팅 규칙 순서를 대신하지도 않습니다.

policy를 설정하기 전에 실제로 어떤 주체가 이를 사용하는지 확인하세요. 인바운드 프로토콜에 관련 사용자 설정이 없거나 클라이언트가 생성한 파일에 기대한 레벨이 기록되지 않았다면 사용자 지정 레벨은 참조되지 않을 수 있습니다. levels 객체가 있다는 사실만으로 적용됐다고 판단하지 말고 최종 실행 파일에서 연결된 필드를 찾으세요. 개인용 로컬 클라이언트라면 연결되지 않은 레벨을 여러 개 만들기보다 기본 레벨의 동작을 명확히 해 두는 편이 관리하기 쉽습니다.

{
  "policy": {
    "levels": {
      "0": {
        "handshake": 4,
        "connIdle": 300,
        "uplinkOnly": 2,
        "downlinkOnly": 5
      }
    },
    "system": {
      "statsInboundUplink": false,
      "statsInboundDownlink": false
    }
  }
}

이 시간 값은 초 단위 정책을 보여주는 일반적인 예시이지 모든 환경에 권장되는 최적화 값은 아닙니다. 코어마다 기본값과 지원 항목이 다를 수 있으므로 따로 확인해야 합니다. 연결이 끊길 때 무작정 더 큰 시간 제한을 복사하지 마세요. 핸드셰이크가 끝나지 않는지, 연결이 오랫동안 유휴 상태였는지, 한쪽 방향이 먼저 종료됐는지부터 파악해야 합니다. 정책은 해당 단계에서만 적용되며 인증 오류, 인증서 오류, 원격 서비스의 리스닝 실패를 해결하지는 못합니다.

네 가지 시간 제한이 적용되는 단계

handshake는 연결 핸드셰이크 단계에서 기다릴 수 있는 시간을 제한합니다. 네트워크 연결이 느리다면 값이 너무 짧을 때 원래 완료될 수 있었던 핸드셰이크가 먼저 종료될 수 있습니다. 그렇다고 값을 지나치게 늘리면 실패를 확인하기까지 더 오래 기다릴 뿐입니다. connIdle은 연결이 유휴 상태인 시간을 관리하며 오랫동안 활동이 없는 연결을 정리할 때 사용합니다. 애플리케이션의 요청 시간 초과나 원격 리버스 프록시의 시간 제한과는 다른 타이머입니다. 실제 연결 종료는 어느 계층에서든 먼저 발생할 수 있습니다.

uplinkOnly와 downlinkOnly는 연결이 한 방향으로만 활동할 때 유지할 시간을 다룹니다. 다운로드, 장시간 연결, 반쪽 닫기 상태에 영향을 줄 수 있지만 이름의 상·하향을 ‘업로드 속도 향상’이나 ‘다운로드 속도 향상’으로 단순 해석하면 안 됩니다. 애플리케이션이 전송을 마친 뒤에도 응답을 오래 기다린다면 한 방향 시간 제한이 너무 짧아 연결이 먼저 종료될 수 있습니다. 애플리케이션 프로토콜과 로그를 함께 살펴보세요.

정책을 수정해야 하는지 판단하려면 문제가 비슷한 유휴 시간이 지난 뒤 반복되는지, 다시 활동하면 연결 중단을 피할 수 있는지 관찰하세요. 연결이 시작되자마자 실패한다면 프로토콜과 인증을 확인하는 것이 우선입니다. 네트워크를 바꾼 뒤에만 실패한다면 연결 재수립과 시스템 네트워크 상태를 먼저 확인하세요. 모든 문제를 시간 초과로 돌리면 원인을 놓칠 수 있고, 사용되지 않는 연결이 리소스를 더 오래 점유할 수도 있습니다.

통계 활성화와 통계 조회 인터페이스는 별개입니다

policy.system의 인바운드 및 아웃바운드 트래픽 통계 옵션은 관련 카운터를 제어합니다. 사용자 레벨에도 사용자 통계 옵션이 있을 수 있습니다. 이 필드를 켠다고 인터페이스에 트래픽 그래프가 자동으로 표시되거나 외부 조회 API가 만들어지는 것은 아닙니다. 클라이언트에서 통계 모듈, 조회 서비스, 태그 연결을 추가로 설정해야 할 수 있습니다. 클라이언트에 트래픽을 표시하려는 목적이라면 클라이언트 내장 옵션부터 확인해 중복 인터페이스를 수동으로 만들지 마세요.

통계 서비스나 관리 인터페이스가 리스닝 주소를 사용한다면 적절한 로컬 범위로 제한하고, 로컬 네트워크용 인바운드와 함께 외부에 공개하지 마세요. 통계 태그도 실제 인바운드와 아웃바운드에 맞춰야 빈 카운터나 잘못된 통계를 피할 수 있습니다. 지원되지 않는 통계 필드를 추가한다고 코어가 해당 기능을 자동으로 지원하는 것은 아닙니다. 필드나 서비스 로드 오류가 발생하면 먼저 기본 policy로 되돌린 뒤 확장 기능의 지원 여부를 하나씩 확인하세요.

재현 가능한 단일 연결 상황에서 정책을 확인하세요. 웹페이지가 열리는 느낌만으로 판단하지 말고 수정 전후의 대기 단계, 연결 종료 이유, 애플리케이션 동작을 기록해 어떤 변경을 유지할지 결정하세요. 코어를 다시 시작하면 기존 연결과 메모리 통계에 영향을 주므로 비교 조건을 동일하게 맞춰야 합니다. 일반적인 클라이언트 사용에서는 생성기가 제공하는 합리적인 기본 정책을 유지하고 증거가 있는 필드만 수정하는 편이 업데이트와 문제 해결에 유리합니다.

클라이언트와 설정 적용

계속 적용되는 설정 출처 찾기

그래픽 클라이언트는 보통 노드 정보, 구독 그룹, 라우팅 템플릿, 인터페이스 설정을 각각 저장한 뒤 현재 선택에 맞춰 코어 실행 파일을 생성합니다. 이 항목들은 같은 데이터가 아닙니다. 구독 업데이트는 주로 원격 노드 정보를 바꾸고, 라우팅 모드 변경은 주로 규칙을 바꾸며, 시스템 프록시는 애플리케이션의 진입 경로에 영향을 줍니다. 수정 전에 필요한 변경이 어느 계층에 해당하는지 확인하세요. 브라우저의 진입 경로를 바꾸려고 원격 아웃바운드를 수정하거나, 라우팅을 바꾸려고 구독 전체를 다시 가져오는 일을 피할 수 있습니다.

v2rayN에서는 일반적인 변경을 위해 해당 로컬 리스닝, 라우팅 설정, 코어 설정 메뉴를 사용하는 것이 좋습니다. 전체 JSON을 직접 수정해야 할 때는 클라이언트에서 제공하는 사용자 지정 설정 기능을 사용하세요. 메뉴 이름은 인터페이스에 따라 달라질 수 있으므로 다른 화면의 파일 경로를 그대로 따라 하지 말고 필요한 기능을 확인하세요. 특히 실행 중인 임시 설정 파일만 수정하지 마세요. 노드를 다시 선택하거나 재시작할 때 설정 생성기가 해당 파일을 덮어쓸 수 있습니다.

출처주요 내용흔히 덮어쓰이는 시점
노드 정보원격 프로토콜, 주소, 인증, 전송 방식노드 수정 또는 구독 업데이트
라우팅 템플릿규칙 순서와 아웃바운드 선택라우팅 모드 변경
클라이언트 설정로컬 인바운드와 실행 옵션설정 저장 또는 재시작
사용자 지정 설정파일에 지정된 코어 동작파일 다시 불러오기 또는 설정 변경

가져오기, 저장, 실행은 각각 다른 단계입니다

클라이언트가 파일을 받아들였다는 것은 형식이나 링크를 인식했다는 뜻일 수 있습니다. 해당 설정을 선택하고 코어를 실행한 뒤 실행 로그를 확인해야 합니다. 저장 후 다시 불러오지 않았다면 기존 프로세스가 이전 내용을 계속 사용할 수 있습니다. 실행 여부를 확인하려면 시작 로그와 실제 리스닝 정보를 살펴보세요. 목록의 이름이 바뀐 것만으로는 충분하지 않습니다. 클라이언트에서 생성 설정을 미리 볼 수 있다면 실행 전후의 주요 필드를 비교해 이번 실행에서 의도한 인바운드 태그와 아웃바운드 참조를 사용하는지 확인하세요.

Android에서 v2rayNG와 v2flyNG는 보통 시스템 권한을 받아 가상 네트워크 인터페이스를 통해 트래픽을 가로챕니다. 애플리케이션 선택과 백그라운드 실행 설정도 어떤 트래픽이 들어오는지에 영향을 줍니다. 데스크톱 시스템 프록시의 동작을 여기에 그대로 적용할 수는 없습니다. SOCKS 인바운드를 수동으로 추가해도 클라이언트의 네트워크 가로채기 절차를 대신하지 않습니다. 반대로 시스템 가로채기가 켜져 있어도 사용자 지정 파일의 모든 인바운드가 실제로 사용된다는 뜻은 아닙니다.

세 클라이언트 간에 옮길 때는 노드 정보와 전체 설정을 각각 따로 확인해야 합니다. 공유 링크에는 보통 노드 정보만 들어 있으며 로컬 포트, DNS, 라우팅 리소스, policy가 포함되지 않을 수 있습니다. 전체 JSON의 모든 필드가 대상 코어에서 지원되더라도 클라이언트가 특정 태그, 인바운드, 실행 방식을 요구할 수 있습니다. 이전 후에는 노드 목록에 나타나는지만 확인하지 말고 인바운드, 기본 아웃바운드, DNS, 규칙 리소스를 다시 검증하세요.

설정 병합 시 안전한 순서

설정 조각을 합칠 때는 현재 실행 가능한 설정을 바탕으로 삼고 먼저 백업한 다음, 완전한 설정 항목 하나씩 교체하세요. 배열은 요소끼리, 객체는 필드끼리 합쳐야 합니다. 최상위 객체 두 개를 그대로 이어 붙이면 안 됩니다. 태그가 충돌하면 먼저 이름을 바꾸고 모든 참조를 함께 수정하세요. 특히 라우팅 규칙이 새 태그를 가리킨다면 해당 아웃바운드가 이미 있는지 확인해야 합니다. 출구를 추가하기 전에 규칙부터 활성화하면 코어가 설정을 읽는 단계에서 실행을 거부할 수 있습니다.

구독 주소와 노드 인증 정보는 민감한 데이터입니다. 설정 사본을 보관하거나 화면을 캡처해 공유하거나 다른 사람에게 문의할 때 주소의 접속 매개변수, 인증 정보, 구독 링크를 제거하세요. 로그에 서버 주소나 접속 목적지가 포함될 수도 있으므로 공유 전에 확인해야 합니다. 이 문서의 예제에는 로컬 인바운드와 문서용 주소만 들어 있습니다. 원격 서비스 설정으로 사용하면 안 됩니다. 실제 인증 정보는 서비스 설정에서 확인하고 공개 문서에 입력하지 마세요.

시스템 프록시와 코어 실행은 따로 확인해야 합니다. 코어가 정상이어도 시스템 프록시가 이전 포트를 가리키면 애플리케이션 연결이 실패할 수 있습니다. 클라이언트를 종료한 뒤 시스템 프록시가 복구되지 않으면 존재하지 않는 인바운드에 계속 연결을 시도할 수도 있습니다. 반대로 일부 애플리케이션은 시스템 프록시를 무시해 별도로 설정해야 합니다. 한 애플리케이션만 접속되지 않는다면 코어 파일 전체를 바꾸기 전에 해당 애플리케이션의 연결 경로부터 확인하세요.

클라이언트를 업데이트하거나 코어를 바꾼 뒤에는 이전 설정 사본을 보관하고 확장 필드와 설정 생성 방식을 다시 확인하세요. 인터페이스에 예전 옵션이 남아 있어도 새 코어에서 같은 방식으로 처리된다는 보장은 없습니다. 기본 사용 방법은 빠른 시작 가이드를 참고하세요. 구독 문제는 구독 갱신 및 자동 업데이트 설정에서 확인해 구독을 가져오지 못하는 문제와 코어 전달 문제를 구분하세요.

설정 검증 및 로그 문제 해결

설정 로드, 리스닝, 연결 순서로 확인

가장 먼저 실패한 단계부터 확인해야 합니다. 첫째는 JSON을 파싱할 수 있는지, 둘째는 코어가 필드와 태그를 받아들이는지, 셋째는 인바운드가 리스닝하는지, 넷째는 애플리케이션 트래픽이 들어오는지, 마지막으로 라우팅, DNS 조회, 원격 연결이 정상인지 확인합니다. 로그에 이미 포트 바인딩 실패가 표시된다면 DNS를 바꿔도 소용없습니다. 코어가 시작되지 않았다면 브라우저의 연결 실패만으로 아웃바운드 프로토콜이 올바른지 판단할 수 없습니다.

먼저 클라이언트의 로그 화면에서 선택한 코어와 이번 실행 결과를 확인한 다음 가장 먼저 나타난 오류를 살펴보세요. 뒤이어 표시되는 ‘프로세스 종료’나 ‘연결 거부’는 앞선 오류의 결과일 수 있습니다. 로그의 시간 순서를 유지하고 시작 오류와 접속 오류를 구분하세요. 같은 창에 이전 실행 기록이 섞일 수 있으므로 수정 후 새 실행이 시작된 지점을 확인해야 합니다. 그래야 이전 오류를 수정 후에도 해결되지 않았다는 근거로 오해하지 않습니다.

{
  "log": {
    "loglevel": "info"
  }
}

연결 과정을 살펴볼 때는 로그 수준을 잠시 info로 설정할 수 있습니다. 더 자세한 디버그 수준은 필요한 경우에만 짧게 사용하세요. 로그 설정은 기존 log 객체에 합쳐 같은 항목을 중복 선언하지 않도록 합니다. 접속 로그와 오류 로그 출력 방식은 클라이언트가 관리할 수 있으므로 쓰기 권한이 없는 경로를 임의로 지정하지 마세요. 문제 해결이 끝나면 적절한 수준으로 되돌려 접속 대상이 계속 기록되거나 불필요한 파일이 많이 생성되지 않도록 하세요.

오류 종류별로 설정 항목 찾기

파싱 오류는 보통 따옴표, 쉼표, 괄호, 데이터 형식 문제입니다. 편집기에 표시된 위치는 오류가 발견된 곳일 뿐 실제 시작 지점이 아닐 수 있습니다. 바로 앞 항목에 구분 기호가 빠지지 않았는지 거슬러 확인하세요. 알 수 없는 프로토콜이나 필드, 잘못된 열거형 값은 코어 호환성 문제일 가능성이 큽니다. 먼저 현재 코어를 확인하세요. 규격에서 대응 관계를 명확히 설명하지 않는 한, 철자가 비슷한 다른 이름으로 바꾸지 마세요.

리스닝 실패 시에는 다른 프로세스가 포트를 사용 중인지, 바인딩 주소가 로컬 기기에 속하는지, 클라이언트가 같은 인바운드를 이미 만들었는지 확인하세요. 라우팅 로드가 실패하면 대상 태그가 존재하는지, 리소스 파일을 읽을 수 있는지, 범주 이름이 올바른지 확인해야 합니다. DNS 실패라면 조회 대상, 서버 연결 가능 여부, 대체 조회 조건을 점검하세요. 문제 발생 위치가 서로 다르므로 클라이언트를 바로 재설치하기보다 유형별로 확인하는 편이 문제 해결 단서를 보존할 수 있습니다.

증상우선 확인할 항목우선 수정하지 말 것
설정 로드 직후 종료JSON, 필드 지원 여부, 태그 참조애플리케이션 프록시 설정
로컬 인바운드 연결 거부프로세스, 리스닝 주소, 포트원격 DNS 분기
도메인으로만 접속 실패조회 경로와 반환 주소모든 인바운드 매개변수
규칙이 예상대로 적용되지 않음목적지 형식, 순서, 태그관련 없는 연결 시간 초과
원격 핸드셰이크 실패프로토콜, 전송 방식, 보안 계층, 시간로컬 규칙 리소스

복구 가능한 테스트 흐름 만들기

안정적으로 실행되는 기본 설정을 기준으로 준비하고, 인바운드 확장, 프록시 아웃바운드, 규칙, DNS, policy를 하나씩 추가하세요. 각 항목을 추가할 때마다 먼저 실행을 확인한 다음 해당 기능을 테스트합니다. 직접 연결 기준 설정은 로컬 인바운드와 기본 네트워크만 확인할 수 있으며 원격 노드가 정상이라는 뜻은 아닙니다. 프록시로 접속에 성공해도 기본 아웃바운드를 사용했을 수 있으므로 분기 규칙이 올바르다는 증거는 아닙니다. 테스트 결과는 실제로 확인한 범위 안에서만 해석하세요.

변경한 필드, 예상 결과, 실제 로그, 복구 방법을 매번 기록하세요. 라우팅은 도메인과 직접 IP를 모두 대상으로 테스트해야 합니다. DNS는 주소 계열과 캐시 여부를 구분하고, policy는 연결 수립 단계와 유휴 단계를 나누어 확인하세요. 결과가 예상과 다르면 이전 기준 설정으로 복구해 문제가 변경 사항과 함께 나타나는지 확인한 뒤 범위를 좁혀 가세요. 이미 손상된 설정에 패치를 계속 덧붙이지 마세요.

설정 파일은 역할이 분명한 여러 객체를 조합한 것이지, 길수록 기능이 완전해지는 목록이 아닙니다. 용도를 설명하는 필드만 남기고 더 이상 필요하지 않다고 확인된 테스트 설정은 제거하세요. 클라이언트가 생성하는 부분은 해당 설정 메뉴에서 관리해야 합니다. 자주 묻는 내용은 자주 묻는 질문을, 시작 오류를 확인하는 순서는 코어 시작 실패 및 로그 확인 가이드를 참고하세요. 문제 해결이 끝나면 최종 실행 설정을 저장하고 정상적으로 사용하세요.