2026-11-02 · 설정 가이드 · 약 12분

V2Ray 설정 파일 JSON 구조 분석: inbounds·outbounds·routing 이해하기

log, inbounds, outbounds, routing, dns 순서로 설정 파일을 살펴보고 각 필드와 참조 관계를 설명해 클라이언트가 내보낸 파일을 이해하도록 돕습니다.

이 글의 핵심 내용

설정을 읽을 때는 먼저 인바운드와 아웃바운드, 이 둘을 연결하는 태그를 찾고 라우팅과 DNS를 살펴보세요. 이 글에서는 원격 서버 인증 정보가 없는 V2Ray 구형 JSON 설정을 예로 들어 각 필드와 규칙의 적용 순서, 점검 방법을 설명합니다. 구독을 가져온 뒤 v2rayN에서 내보낸 파일을 이해하고 싶은 사용자를 위한 내용입니다. 예시는 로컬 SOCKS 연결, 직접 연결, 차단만 다루며 원격 프록시 기능은 제공하지 않습니다.

1. 클라이언트 설정과 코어 실행 설정 구분하기

v2rayN은 관리 인터페이스이고 V2Ray와 Xray는 실제 연결을 처리하는 코어입니다. 구독에는 서버 정보나 설정 소스가 저장되고, 인터페이스에는 그룹, 현재 선택 항목, 라우팅 프리셋 등의 상태도 저장됩니다. 코어가 실행될 때 읽는 JSON은 리슨 포트, 아웃바운드 프로토콜, 라우팅 규칙을 정의합니다. 확장자가 같다는 이유만으로 이 파일들을 서로 바꿔 쓸 수는 없습니다.

이 글은 V2Ray의 구형 JSON 설정 구조를 다루며, 모든 코어의 전용 필드를 포함하지는 않습니다. v2rayNG는 Xray 코어를, v2flyNG는 v2fly 코어를 사용합니다. 두 설정에 inbounds와 outbounds가 모두 있어도 모든 프로토콜 옵션이 호환되는 것은 아닙니다. 특히 REALITY, 흐름 제어, 전송 관련 필드는 실제 실행 중인 코어의 문서를 확인하세요.

앱 연결 인바운드 수신 라우팅 규칙 적용 아웃바운드 처리 대상 서버

파일을 읽을 때는 이 흐름을 따라 참조 관계를 확인하면 됩니다. log는 처리 과정을 살펴보는 데 쓰이고, dns는 이름 해석 기능을 제공합니다. 두 항목은 네트워크 경로를 따라 반드시 순서대로 실행되는 노드가 아닙니다. JSON 객체에서 다섯 모듈이 배치된 순서는 처리 순서를 결정하지 않지만, 배열에 담긴 라우팅 규칙의 순서는 결과에 영향을 줍니다.

2. 전체 예시: 로컬 SOCKS 인바운드와 두 가지 아웃바운드

아래는 설정 구조를 이해하기 위한 전체 예시입니다. 로컬 루프백 주소에서만 수신하며 SOCKS 요청을 처리합니다. 목적지 포트가 25인 TCP 연결은 차단하고, 규칙에 해당하지 않는 나머지 연결은 기본적으로 직접 연결합니다. 앱이 자동으로 프록시를 사용하게 하거나 원격 프록시 서버에 연결하는 설정은 아닙니다.

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "local-socks",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": false
      }
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ],
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "inboundTag": ["local-socks"],
        "network": "tcp",
        "port": "25",
        "outboundTag": "block"
      },
      {
        "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:localhost"],
        "outboundTag": "direct"
      }
    ]
  },
  "dns": {
    "servers": ["localhost"],
    "queryStrategy": "UseIP"
  }
}
10808
예시 SOCKS 리슨 포트
2
아웃바운드: direct와 block
25
예시에서 차단하는 TCP 목적지 포트

아래 숫자는 예시 설정에서 정한 값이며 모든 클라이언트 버전의 기본값은 아닙니다. 로컬에서 다른 프로그램이 10808 포트를 사용 중이라면 비어 있는 포트로 바꾸고 앱의 SOCKS 주소도 함께 수정하세요. 예시의 사설망 직접 연결 규칙은 작성 방법을 보여 주기 위한 것으로, 로컬 네트워크 주소 전체 목록은 아닙니다.

3. log와 inbounds: 요청이 코어에 도달하는지 확인하기

log.loglevel은 로그 상세 수준을 정합니다. 예시에서는 경고와 오류를 확인하기 적합한 warning을 사용합니다. 문제를 진단할 때는 일시적으로 info로 바꾸고, 필요한 경우 debug를 사용하세요. access나 error 파일 경로를 지정하지 않아도 로그가 사라지는 것은 아닙니다. 실행한 클라이언트가 로그를 받아 화면에 표시할 수 있습니다.

inbounds는 인바운드 배열입니다. 예시에서는 127.0.0.1:10808로 들어오는 SOCKS 연결만 받으므로 앱에서 이 주소를 명시적으로 사용해야 합니다. 브라우저의 HTTP 프록시를 SOCKS만 제공하는 포트에 지정하면 프로토콜이 맞지 않습니다. 코어를 실행하는 것만으로 시스템 프록시가 바뀌지는 않습니다.

로그 확인 항목

loglevel
warning
임시 문제 해결
info 또는 debug
출력 위치
경로 설정과 실행 방식에 따라 다름

문제를 찾은 뒤에는 로그 상세 수준을 낮춰 연결 정보가 장기간 과도하게 기록되지 않도록 하세요.

로컬 인바운드 항목

listen
127.0.0.1
port
10808
protocol
socks
tag
local-socks

tag는 라우팅에서 참조하는 이름입니다. 리슨 주소나 원격 노드 이름이 아닙니다.

auth: "noauth"는 이 SOCKS 인바운드에서 인증을 요구하지 않는다는 뜻이므로, 예시에서는 로컬 주소에서만 수신하도록 제한합니다. 다른 기기에서도 연결할 수 있게 하려고 접근 제어를 무시한 채 리슨 주소를 모든 인터페이스로 바꾸지 마세요. udp: false는 이 인바운드에서 SOCKS UDP 전달을 사용하지 않는다는 뜻입니다. 이 설정으로는 UDP 앱의 정상 동작을 확인할 수 없습니다.

포트 충돌은 인바운드 시작 단계의 문제이고, 연결 시간 초과는 그다음 연결 경로에서 발생하는 문제입니다. 먼저 로그에서 리슨 실패 여부를 확인한 뒤 라우팅, DNS, 원격 서버를 점검하면 불필요한 설정 변경을 줄일 수 있습니다.

4. outbounds: 프로토콜은 연결을 처리하고 tag는 참조에 사용

outbounds 배열은 연결이 코어에서 나가는 방식을 정의합니다. 예시의 freedom은 대상에 직접 연결하고 blackhole은 조건에 맞는 트래픽을 버립니다. direct와 block은 임의로 지정한 태그일 뿐입니다. 태그 이름을 바꿔도 프로토콜 동작은 달라지지 않지만, 해당 태그를 참조하는 모든 규칙도 함께 수정해야 합니다.

필드예시 값확인할 내용
outbounds[0].tagdirect라우팅 참조 이름이며 기본 아웃바운드이기도 함
outbounds[0].protocolfreedom원격 프록시를 거치지 않고 대상에 직접 연결
outbounds[1].protocolblackhole라우팅에서 선택된 연결 차단
settings빈 객체이 예시에서는 기본 동작을 사용합니다. 프록시 프로토콜에는 보통 더 많은 매개변수가 필요합니다.

여기서 다루는 구형 설정 모델에서는 어떤 규칙에도 일치하지 않은 연결을 첫 번째 아웃바운드로 보냅니다. 따라서 배열 순서를 바꾸면 기본 동작도 달라질 수 있습니다. block을 첫 번째 항목에 두면 기본적으로 직접 연결되던 요청이 차단될 수 있습니다. 배열 정렬을 단순한 화면 정리로 생각하지 마세요.

실제 VMess 또는 VLESS 아웃바운드에는 서버 주소, 포트, 인증 정보와 경우에 따라 streamSettings가 포함됩니다. protocol은 프록시 프로토콜을 지정하며 전송 및 보안 계층 매개변수는 별도로 설정합니다. freedom을 vless로 바꾸는 것만으로 연결이 설정되지는 않습니다. 프로토콜이 다른 설정의 settings를 그대로 바꿔 쓸 수도 없습니다.

기본 동작 확인: 첫 번째 항목과 태그 참조부터 살펴보기

설정을 수정하기 전에 첫 번째 아웃바운드의 tag를 기록하고 모든 outboundTag를 검색하세요. 기본 경로와 명시적 경로를 모두 확인해야 연결이 직접 연결될지, 프록시를 거칠지, 차단될지 판단할 수 있습니다.

5. routing: 규칙 길이가 아니라 순서대로 매칭

routing.rules는 위에서 아래로 확인하며, 일치하면 해당 아웃바운드를 사용합니다. 도메인이 더 길거나 IP 대역이 더 좁다고 우선 처리하지는 않습니다. 같은 규칙의 서로 다른 조건은 보통 모두 충족해야 하며, 한 조건 배열에 든 여러 값은 보통 그중 하나만 일치해도 됩니다. 설정할 때는 ‘모두 충족’과 ‘하나라도 일치’를 구분하세요.

  1. 첫 번째 규칙: 인바운드 태그가 local-socks이고 네트워크가 TCP이며 목적지 포트가 25여야 합니다. 세 조건을 모두 충족하면 block으로 보냅니다.
  2. 두 번째 규칙: 대상 IP가 나열된 대역 중 하나에 속하면 direct로 보냅니다. 대상이 사설 IP여도 앞선 TCP 25 규칙에 먼저 일치하면 차단됩니다.
  3. 세 번째 규칙: full:localhost는 해당 도메인과 정확히 일치한다는 뜻입니다. 이름에 localhost가 포함된 모든 도메인을 가리키지는 않습니다.
  4. 모든 규칙에 불일치: 첫 번째 아웃바운드를 사용합니다. 이 예시에서는 direct입니다. 두 번째와 세 번째 규칙의 결과는 기본 아웃바운드와 같지만, 규칙 작성 방법을 보여 주기 위해 남겨 두었습니다.

inboundTag는 인바운드의 tag를 참조하고 outboundTag는 아웃바운드의 tag를 참조합니다. 대소문자와 철자를 정확히 맞춰야 합니다. 이 값은 코어가 자동으로 인식하는 한글 그룹 이름이 아니며, 클라이언트에 표시되는 노드 이름이 바뀌어도 자동으로 변경되지 않습니다.

domainStrategy: "AsIs"는 라우팅 단계에서 IP 규칙을 적용하기 위해 도메인을 주소로 변환하지 않는다는 뜻입니다. 앱이 도메인을 전달하면 두 번째 IP 규칙과 일치하지 않을 수 있습니다. 앱이 IP를 전달한 경우에는 IP 대역을 바로 확인할 수 있습니다. IPIfNonMatch로 바꾸면 도메인 단계에서 일치하는 규칙이 없을 때 주소를 조회한 뒤 다시 매칭을 시도합니다. 모든 DNS 요청이 원격으로 전송된다는 뜻은 아닙니다.

6. dns: 이름 해석 정책과 트래픽 출구 구분하기

예시의 dns.servers에는 "localhost"만 있습니다. 이는 로컬 시스템의 이름 해석 기능을 사용한다는 뜻이지, 로컬 DNS 포트에서 요청을 수신한다는 뜻은 아닙니다. queryStrategy: "UseIP"는 IPv4와 IPv6 주소를 모두 조회하도록 허용합니다. 실제 응답은 도메인 레코드, 리졸버, 네트워크 환경에 따라 달라집니다.

dns 모듈을 설정했다고 해서 모든 앱의 DNS 요청이 코어로 들어가는 것은 아닙니다. 앱이 먼저 이름을 해석한 뒤 IP를 SOCKS에 전달할 수도 있고, 도메인을 코어에 전달할 수도 있습니다. 전자의 경우 도메인 기준 분기에 필요한 정보가 사라질 수 있지만, 후자는 대상 도메인이 보존됩니다. 인바운드가 요청을 받는 방식과 DNS 모듈의 이름 해석은 서로 다른 문제입니다.

설정 위치제어하는 내용혼동하면 안 되는 항목
dns.servers내장 DNS 모듈에서 사용할 수 있는 이름 해석 소스운영체제의 모든 프로그램에 적용되는 DNS 설정
dns.queryStrategy조회할 주소 체계에 대한 정책직접 연결 또는 프록시를 선택하는 라우팅 규칙
routing.domainStrategy라우팅 매칭에 조회 결과를 사용할지 여부모든 이름 해석 요청을 같은 출구로 강제 전송
아웃바운드의 이름 해석 정책해당 아웃바운드가 대상 도메인을 처리하는 방식모든 코어에서 공통으로 쓰는 단일 필드

도메인에 따라 리졸버를 선택하려면 DNS 서버 객체의 domains 같은 필드를 추가로 살펴보세요. 단, 조회 트래픽이 리졸버에 도달하는 경로도 확인해야 합니다. DNS 주소만 바꿨다고 조회 요청이 예상한 프록시 경로를 거친다는 뜻은 아닙니다. 문제를 진단할 때는 요청에 도메인과 IP 중 무엇이 들어왔는지, 최종적으로 어떤 아웃바운드가 선택됐는지 함께 확인하세요.

7. 내보낸 파일 점검하기: 문법부터 실제 연결까지

편집하기 전에 설정을 복사해 두고 클라이언트가 자동 생성한 실행 파일을 직접 덮어쓰지 마세요. v2rayN은 노드 전환, 구독 업데이트, 코어 재시작 시 설정을 다시 만들 수 있습니다. 임시 실행 파일만 수정했다면 다음 실행 때 변경 사항이 사라질 수 있습니다. 오래 유지할 설정은 현재 버전의 인터페이스에 맞춰 클라이언트의 라우팅, DNS 설정 또는 사용자 지정 설정 항목에 저장하세요.

  1. JSON 문법 확인: 큰따옴표, 괄호, 쉼표가 올바르게 짝을 이루는지 확인하세요. Python이 설치되어 있다면 아래 명령으로 기본 문법을 검사할 수 있습니다. 검사에 통과해도 코어가 모든 필드를 지원한다는 뜻은 아닙니다.
  2. 실제 코어 확인: 클라이언트의 코어 선택 항목과 시작 로그에서 코어 이름, 버전, 읽어 들인 설정 파일 경로를 확인하세요. 클라이언트 이름만 보고 판단하지 마세요.
  3. 참조 관계 확인: inboundTag와 outboundTag를 하나씩 검색해 각각의 정의가 있는지 확인하고 첫 번째 아웃바운드도 점검하세요.
  4. 리슨 및 요청 확인: 127.0.0.1:10808에서 정상적으로 리슨하는지, 앱도 같은 포트와 SOCKS 프로토콜을 사용하는지 확인하세요.
  5. 항목별 검증: 한 번에 모듈 하나만 수정하세요. 일반 TCP 요청부터 확인한 뒤 도메인 규칙과 차단 규칙을 테스트해 여러 변수를 한꺼번에 섞지 않도록 합니다.
python -m json.tool config.json

문법 검사에 통과했는데 코어가 시작되지 않는다면 로그에서 필드 경로와 오류 유형을 확인하세요. 알 수 없는 필드, 호환되지 않는 프로토콜 옵션, 포트 충돌은 서로 다른 문제이며 DNS를 바꿔서 모두 해결할 수는 없습니다. 로그나 설정을 공유하기 전에는 서버 인증 정보, 구독 링크, 불필요한 개인 경로를 삭제하세요.

JSON 검사를 통과했는데도 시작에 실패하는 이유는 무엇인가요?

문법 검사는 파일을 파싱할 수 있는지만 확인합니다. 클라이언트 시작 로그를 열어 첫 번째 오류를 찾고 프로토콜 이름, 필드 자료형, 실제 코어를 확인하세요. 주소가 사용 중이라는 메시지가 나오면 10808을 사용하는 프로그램을 종료하거나 리슨 포트를 함께 변경하세요.

outboundTag를 바꾼 뒤 기존 노드가 사용되지 않는 이유는 무엇인가요?

새 태그가 아웃바운드의 tag와 정확히 일치하는지 먼저 확인하고 규칙 순서도 살펴보세요. 라우팅 참조만 바꾸고 아웃바운드 정의는 그대로 두지 않았는지 확인해야 합니다. 요청이 더 위에 있는 규칙에 먼저 일치했는지도 점검하세요.

이 설정을 복사했는데 구독 서버에 연결되지 않는 이유는 무엇인가요?

이 글에는 freedom과 blackhole 두 가지 아웃바운드만 있습니다. 원격 프록시를 사용하려면 유효한 구독을 바탕으로 클라이언트가 해당 아웃바운드를 생성하도록 한 다음, 라우팅에서 어떻게 참조하는지 확인하세요. 이 예시에 인증 매개변수를 임의로 채워 넣지 마세요.

v2rayN을 재시작한 뒤 직접 수정한 내용이 사라지는 이유는 무엇인가요?

대개 클라이언트가 실행 설정을 다시 생성했기 때문입니다. 수정 전후의 사본을 보관하고 장기간 유지할 라우팅이나 DNS 변경은 클라이언트의 영구 설정에 반영하세요. 그런 다음 재시작해 새로 생성된 파일을 확인하고 임시 파일을 반복해서 수정하지 마세요.

V2Ray 클라이언트 다운로드