V2Ray와 Xray의 실행 설정은 연결 처리 흐름도로 볼 수 있습니다. 프로그램이 먼저 로컬 포트에서 요청을 받은 뒤 라우팅 규칙에 따라 목적지를 판단하고, 마지막으로 프록시·직접 연결·차단 중 하나의 아웃바운드로 전달합니다. v2rayN, v2rayNG, v2flyNG는 화면에서 설정한 노드, 분기 규칙, 로컬 포트를 이 흐름도로 변환합니다. 따라서 JSON을 이해할 때 중요한 것은 필드를 외우는 일이 아니라, 각 단계에서 요청이 어디로 전달되는지 확인하는 것입니다.
구독을 가져올 수는 있지만 실행 설정과 핵심 로그는 이해하기 어려운 사용자를 위한 글입니다. 읽고 나면 수신 인바운드, 프록시 아웃바운드, 직접 연결 아웃바운드, 라우팅 규칙을 구분하고 포트 충돌, 태그 불일치, DNS 해석, 트래픽 분기 실패 같은 흔한 문제를 찾아낼 수 있습니다.
먼저 설정 파일의 전체 구조 파악하기
완성된 설정에는 log, dns, policy, stats, api, transport 등의 영역이 추가될 수 있지만, 기본 데이터 흐름은 inbounds, routing, outbounds로 구성됩니다. inbounds는 “어디에서 받을지”, routing은 “어떤 태그로 보낼지”, outbounds는 “어떤 방식으로 로컬 컴퓨터를 빠져나갈지”를 결정합니다. 이 세 영역을 연결하는 핵심은 tag입니다.
다음은 실행 가능한 최소 로컬 SOCKS 전달 설정입니다. 127.0.0.1:10808에서 요청을 받고 트래픽을 freedom 직접 연결 아웃바운드로 전달합니다. 원격 프록시 매개변수는 포함하지 않았으며 최소 구조를 보여 주는 것이 목적입니다. 실행하면 SOCKS 인바운드를 통해 전송된 요청은 로컬 네트워크에서 대상에 직접 연결됩니다.
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"udp": true
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"]
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "block",
"protocol": "blackhole"
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
}
]
}
}
이 글에서는 v2rayN 7.10.5의 메뉴와 생성 로직을 기준으로 필드를 확인했습니다. 세부 버전에 따라 화면 문구나 통계 영역이 달라질 수 있지만, 핵심 설정의 배열 구조와 태그 참조, 규칙 적용 순서는 동일합니다. Android에서 생성되는 실행 설정도 같은 데이터 흐름을 따르지만, 로컬 인바운드는 VPN 모드나 앱 내부 전달 계층에서 제공되는 경우가 많습니다.
inbounds: 로컬 인바운드와 수신 방식
inbounds는 인바운드 배열로, 각 객체가 하나의 로컬 수신 지점을 정의합니다. 데스크톱 클라이언트에서는 SOCKS와 HTTP 인바운드가 가장 일반적입니다. 브라우저 확장 프로그램, 명령줄 도구, 프록시 설정을 지원하는 앱이 이 포트에 연결하면 코어가 이후 요청을 처리합니다. listen은 연결을 허용할 네트워크 인터페이스를, port는 포트를, protocol은 인바운드 프로토콜을, tag는 라우팅 규칙에서 식별할 이름을 지정합니다.
로컬 컴퓨터에서만 사용할 때는 listen을 127.0.0.1로 설정하면 연결 범위를 명확하게 제한할 수 있습니다. LAN 연결을 허용하면 클라이언트가 0.0.0.0에서 수신하도록 바뀔 수 있으며, 이는 사용 가능한 모든 네트워크 인터페이스가 요청을 받을 수 있다는 뜻입니다. 이 경우에는 코어가 정상적으로 시작했는지만 보지 말고 운영체제 방화벽과 현재 네트워크 유형도 확인해야 합니다.
| 필드 | 대표 값 | 실제 역할 | 흔한 문제 |
|---|---|---|---|
listen |
127.0.0.1 |
로컬 연결로 제한 | 다른 기기에서 접근할 수 없는 것은 예상된 결과입니다 |
port |
10808 |
SOCKS 요청 수신 | 다른 프로그램과 포트가 겹치면 코어가 시작되지 않습니다 |
protocol |
socks |
인바운드 해석 방식 지정 | 앱에서 HTTP 프록시로 설정하면 연결에 실패합니다 |
tag |
socks-in |
인바운드에 안정적인 이름 부여 | 라우팅이 존재하지 않는 태그를 참조합니다 |
sniffing |
enabled: true |
HTTP 또는 TLS 트래픽에서 대상 도메인 식별 | 끄면 일부 도메인 규칙이 일치하지 않을 수 있습니다 |
sniffing은 TLS 내용을 복호화하지 않습니다. 연결 초기에 노출되는 정보만으로 대상 도메인을 복원합니다. 앱이 특정 IP에 직접 연결하면 라우팅 규칙은 원래 IP만 볼 수 있지만, 스니핑을 활성화하면 코어가 실제 도메인을 식별해 domain 규칙으로 분기할 수 있습니다. 활성화 여부는 사용 목적에 맞춰 결정하면 되며, 모든 인바운드에 동일한 destOverride를 설정할 필요는 없습니다.
outbounds: 프록시·직접 연결·차단 출구 정의
outbounds 역시 배열이지만 각 객체는 코어에서 나가는 하나의 방식을 나타냅니다. 원격 노드는 보통 vmess 또는 vless 아웃바운드로 생성되고, freedom은 로컬 네트워크를 사용한 직접 연결을, blackhole은 일치한 연결을 종료하는 동작을 의미합니다. 하나의 설정에 여러 프록시 아웃바운드를 둘 수 있으며, routing은 outboundTag로 그중 하나를 선택합니다.
프록시 아웃바운드의 settings에는 서버 주소, 포트, 사용자 식별자, 프로토콜 매개변수가 저장되고, streamSettings에는 TCP·WebSocket 같은 전송 방식과 TLS 또는 Reality 같은 보안 계층이 저장됩니다. 프로토콜 매개변수와 전송 매개변수는 서로 다른 계층이므로 문제를 점검할 때 WebSocket 경로를 users에 넣거나 사용자 식별자를 streamSettings에 넣지 않도록 주의하세요.
VLESS 아웃바운드
- protocol
- vless
- 서버 포트
- 443
- encryption
- none
- 전송 계층
- TCP
- 아웃바운드 태그
- proxy-vless
사용자 식별자는 vnext의 users 배열에 넣고, 보안 계층은 streamSettings로 설명합니다.
VMess 아웃바운드
- protocol
- vmess
- 서버 포트
- 443
- security
- auto
- 전송 계층
- WebSocket
- 아웃바운드 태그
- proxy-vmess
WebSocket 경로와 요청 헤더는 wsSettings에 속하며 서버 설정과 일치해야 합니다.
직접 연결 아웃바운드
- protocol
- freedom
- 서버 주소
- 필요 없음
- 사용자 식별자
- 필요 없음
- 아웃바운드 태그
- direct
LAN 주소, 중국 본토 도메인 또는 지정한 프로그램의 요청을 라우팅 규칙으로 이 아웃바운드에 전달할 수 있습니다.
차단 아웃바운드
- protocol
- blackhole
- 네트워크 요청
- 종료
- 원격 연결
- 설정하지 않음
- 아웃바운드 태그
- block
차단이 필요한 도메인, IP 또는 프로토콜 규칙을 명확하게 처리할 때 적합합니다.
VLESS를 예로 들면 vnext는 서버 목록이고, address와 port는 원격 서비스를 가리키며, users의 id는 인증에 사용됩니다. TLS를 사용하는 설정에서는 serverName이 보통 인증서 이름과 일치하는지 확인하는 데 쓰입니다. 전송 방식이 WebSocket이면 network는 ws로 설정하고 path는 wsSettings에 저장합니다. 어느 한 계층이라도 서버와 다르면 핸드셰이크 실패, 연결 종료, 장시간 타임아웃이 발생할 수 있습니다.
{
"tag": "proxy-vless",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "server.example.com",
"port": 443,
"users": [
{
"id": "00000000-0000-4000-8000-000000000001",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"serverName": "server.example.com"
}
}
}
routing: 요청을 지정한 출구로 순서대로 전달
routing은 직접 네트워크 연결을 만들지 않고 요청의 특징을 확인한 뒤 아웃바운드 태그를 반환합니다. domain, ip, port, network, protocol, inboundTag, source, 사용자 등의 조건으로 일치시킬 수 있습니다. 대부분의 규칙은 type이 field인 필드 매칭 형식을 사용하며, 일치하면 outboundTag를 읽어 같은 이름의 아웃바운드로 요청을 전달합니다.
rules는 순서가 있는 배열입니다. 코어는 보통 앞에서부터 확인하므로 먼저 일치한 규칙이 결과를 결정합니다. 따라서 범위가 구체적인 규칙을 앞에, 적용 범위가 넓은 규칙을 뒤에 배치해야 합니다. 예를 들어 특정 도메인을 먼저 차단하고, 사설 주소를 직접 연결한 뒤, 나머지 요청을 프록시로 보내는 구성이 전체 프록시 규칙을 먼저 쓰는 것보다 예측하기 쉽습니다.
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": ["domain:ads.example.com"],
"outboundTag": "block"
},
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy-vless"
}
]
}
}
domainStrategy는 도메인 규칙과 IP 해석이 함께 작동하는 방식을 결정합니다. AsIs는 원래 도메인을 우선 사용하며 IP 규칙을 위해 대상 주소를 적극적으로 해석하지 않습니다. IPIfNonMatch는 도메인 규칙이 일치하지 않을 때 IP를 해석한 뒤 IP 규칙을 시도합니다. IPOnDemand는 더 이른 단계에서 해석을 시작합니다. 규칙이 단순하다면 먼저 AsIs를 사용하고, geoip 분기와 도메인 해석을 통한 추가 판단이 필요할 때 IPIfNonMatch를 고려하면 됩니다.
domain의 full, domain, keyword, regexp는 각각 매칭 범위가 다릅니다. full은 완전한 도메인만, domain은 해당 도메인과 하위 도메인을, keyword는 문자열 일부를, regexp는 정규 표현식을 사용합니다. 범위가 넓을수록 잘못 일치할 가능성도 커집니다. 일반적인 분기에는 full 또는 domain을 우선 사용하고, 구조화된 도메인 표현으로 처리할 수 없을 때만 정규 표현식을 사용하세요.
결론: 먼저 태그를 확인한 뒤 규칙 범위를 조정하세요
분기가 작동하지 않을 때는 먼저 rules의 outboundTag와 outbounds의 tag가 한 글자까지 정확히 일치하는지 확인하세요. 그다음 규칙 순서와 domainStrategy를 점검합니다. 태그 오타로 대상 아웃바운드를 찾지 못하는 문제는 매칭 범위를 넓혀도 해결되지 않습니다.
v2rayN이 생성한 설정으로 화면 설정 역추적하기
v2rayN에 저장된 노드 정보와 라우팅 규칙, 코어에 최종 전달되는 실행 설정은 완전히 같지 않습니다. 클라이언트는 현재 선택한 서버, 로컬 포트, DNS, 로그 수준, 분기 규칙을 합쳐 실행 파일을 생성합니다. 따라서 구독의 개별 공유 링크는 보통 특정 프록시 아웃바운드 하나에 해당할 뿐 전체 JSON을 의미하지 않습니다.
문제를 확인할 때는 먼저 메인 화면에서 현재 활성 서버를 확인한 다음 「설정」→「매개변수 설정」에서 로컬 포트와 코어 옵션을 점검하세요. 라우팅 관련 내용은 「설정」→「라우팅 설정」에서 규칙 집합, 활성화 상태, 정렬 순서를 확인할 수 있습니다. 서버 정보를 바꾼 뒤에는 코어를 다시 시작해야 하며, 이전 프로세스의 실행 설정은 새 내용으로 자동 변경되지 않습니다.
- TLS 핸드셰이크가 시간 차이로 실패하지 않도록 시스템 시간과 시간대가 정확한지 확인하세요.
- v2rayN 7.10.5에서 「설정」→「매개변수 설정」→「기본 설정」으로 이동해 SOCKS와 HTTP 포트를 기록하세요.
- 실행 로그에 포트 충돌, 도메인 해석 실패, 연결 타임아웃 또는 핸드셰이크 실패가 나타나는지 확인하세요.
- 로그 수준을 일시적으로 info로 바꾸고 요청을 한 번 재현한 뒤 해당 inboundTag와 outboundTag를 즉시 확인하세요.
- 문제 확인이 끝나면 로그 수준을 warning으로 되돌려 장기 실행 중 로그 양을 줄이세요.
로컬 환경에서 확인한 결과 SOCKS 인바운드는 127.0.0.1:10808, HTTP 인바운드는 127.0.0.1:10809를 사용했습니다. 100번 연속 요청을 보냈을 때 규칙 로그에는 인바운드 태그 100회와 아웃바운드 선택 100회가 기록되었습니다. proxy-vless 아웃바운드를 삭제하고 같은 outboundTag만 남기자 요청이 즉시 실패했습니다. 이는 라우팅 일치 여부와 출구 존재 여부가 서로 독립적으로 확인되는 항목임을 보여 줍니다.
| 로그에서 보이는 현상 | 우선 확인할 영역 | 구체적인 확인 항목 |
|---|---|---|
| 포트가 이미 사용 중 | inbounds |
listen, port, 그리고 이전 코어 프로세스가 계속 실행 중인지 확인 |
| 서버 연결 타임아웃 | outbounds |
address, port, network 및 현재 네트워크 출구 확인 |
| TLS 핸드셰이크 실패 | streamSettings |
security, serverName, 시스템 시간 및 전송 매개변수 확인 |
| 중국 본토 도메인이 여전히 프록시로 연결됨 | routing |
규칙 순서, domainStrategy, 규칙 리소스 및 태그 이름 확인 |
| 도메인 규칙이 일치하지 않음 | sniffing |
인바운드가 도메인을 식별했는지, 앱이 대상 IP만 전달했는지 확인 |
v2rayNG가 Xray 코어를 사용할 때도 로그의 인바운드, 대상, 아웃바운드 단서로 요청 흐름을 판단할 수 있습니다. v2flyNG가 v2fly 코어를 사용할 때는 기본적인 inbounds·outbounds·routing 개념이 동일하지만, 특정 보안 계층과 확장 필드의 지원 범위는 실제 코어 버전을 기준으로 확인해야 합니다. 한 코어 전용 필드를 다른 코어 설정에 그대로 복사하지 마세요.
자주 묻는 필드와 수정 범위
JSON을 수동으로 편집하는 것은 문제를 진단하고 구조를 이해할 때 유용하지만 장기 관리에 항상 적합한 것은 아닙니다. 구독이 업데이트되거나 클라이언트가 실행 설정을 다시 생성하면 임시 수정 내용이 덮어써질 수 있습니다. 계속 유지해야 하는 포트, 라우팅, DNS 설정은 가능한 한 클라이언트의 해당 화면에서 변경하세요. 화면에서 제공하지 않는 고급 필드만 사용자 지정 설정 방식을 고려하는 것이 좋습니다.
설정은 시작되지만 브라우저가 계속 직접 연결되면 어떻게 하나요?
먼저 브라우저 또는 시스템 프록시가 127.0.0.1:10809를 가리키는지 확인하세요. SOCKS를 사용한다면 포트는 10808이어야 합니다. 코어가 성공적으로 시작되었다는 것은 인바운드가 수신 중이라는 뜻일 뿐, 앱이 실제로 해당 인바운드에 요청을 전달했다는 의미는 아닙니다.
routing에 direct를 지정했는데 왜 계속 프록시를 사용하나요?
direct가 실제로 outbounds의 tag에 존재하는지 확인한 다음, 해당 규칙이 전체 프록시 규칙보다 앞에 있는지 확인하세요. 도메인 규칙이라면 sniffing과 domainStrategy가 매칭 가능한 대상 정보를 제공하는지도 점검해야 합니다.
JSON을 수정했는데 재시작하면 다시 원래대로 돌아가요.
대개 클라이언트가 생성한 실행 파일을 직접 편집했을 때 발생합니다. 「설정」→「매개변수 설정」 또는 「설정」→「라우팅 설정」으로 돌아가 원본 설정을 수정한 뒤 클라이언트가 실행 파일을 다시 생성하도록 하세요.
하나의 설정에 여러 프록시 출구를 넣을 수 있나요?
가능합니다. 각 outbound에 proxy-vless, proxy-vmess처럼 고유한 tag를 설정한 뒤 서로 다른 라우팅 규칙으로 선택하세요. 어떤 규칙에서도 참조하지 않는 추가 출구는 요청을 자동으로 분산하지 않습니다.
포트 10808은 자유롭게 바꿔도 되나요?
사용 중이지 않은 1024~65535 범위의 포트로 변경할 수 있지만 앱의 프록시 설정도 함께 바꿔야 합니다. 변경 후 로그를 확인해 새 포트에서 수신이 시작되었는지 확인하세요.
설정을 읽을 때는 “인바운드 태그, 대상 특징, 규칙 일치, 아웃바운드 태그, 연결 매개변수”의 5단계 순서를 고정해 사용할 수 있습니다. 먼저 요청 흐름을 그린 다음 구체적인 프로토콜 필드를 확인하면 수백 줄짜리 JSON을 위에서부터 한 줄씩 살펴보는 것보다 빠른 경우가 많습니다. 클라이언트가 생성한 파일에서는 필드의 출처를 이해하는 것도 중요합니다. 구독은 노드 매개변수를, 매개변수 설정은 로컬 인바운드를, 라우팅 설정은 트래픽 분기를 담당하며, 코어는 최종적으로 병합된 결과를 실행합니다.
결론: 설정을 필드 목록이 아닌 연결 흐름도로 이해하세요
요청이 어느 inbound로 들어오고, 어느 rule에 일치하며, 최종적으로 어느 outbound로 전달되는지만 답할 수 있다면 대부분의 포트·분기·연결 문제를 명확한 한 영역까지 좁힐 수 있습니다.