01 / CONFIG ROOT
JSON 구조 개요와 데이터 흐름
설정은 단순한 노드 정보 모음이 아닙니다
V2Ray 설정 파일의 루트는 하나의 JSON 객체입니다. 일반적인 최상위 필드에는 log, dns, inbounds, outbounds, routing, policy 및 stats가 포함됩니다. 인바운드는 로컬 애플리케이션의 연결을 받고, 아웃바운드는 연결이 최종적으로 빠져나갈 경로를 결정하며, 라우팅은 각 연결을 특정 아웃바운드에 매핑합니다. DNS는 도메인 매칭과 대상 조회 결과를 제공하고, 정책과 통계는 연결 단위 동작을 제어합니다. 필드를 외우는 것보다 이 흐름을 이해하는 것이 중요합니다. 애플리케이션이 인바운드 포트에 연결하면 코어가 대상 도메인 또는 IP를 식별하고, 라우팅 규칙을 위에서부터 비교해 일치하는 아웃바운드 태그를 선택합니다. 필요하면 DNS 모듈이 조회를 수행하고, 해당 아웃바운드가 연결을 설정합니다.
그래픽 클라이언트가 생성한 설정은 수동 예제보다 복잡할 수 있습니다. 로컬 관리 인터페이스, 통계용 인바운드, 여러 DNS 서버 또는 호환 필드가 추가되기 때문입니다. 문제를 해결할 때 낯선 필드를 발견했다고 해서 해당 블록 전체를 삭제하지 마세요. 먼저 어느 최상위 모듈에 속하는지 확인하고, 다른 모듈이 태그로 참조하는지 살펴보세요. 예를 들어 라우팅 규칙의 outboundTag는 특정 아웃바운드의 tag와 일치해야 합니다. 정책의 레벨 번호는 사용자나 인바운드가 사용하는 레벨과 대응해야 하며, DNS의 tag도 라우팅 규칙에서 독립적인 트래픽 진입점으로 처리될 수 있습니다.
JSON 문법과 타입 제약
JSON은 구두점과 데이터 타입을 엄격하게 요구합니다. 객체는 중괄호, 배열은 대괄호를 사용하며 문자열은 큰따옴표로 감싸야 합니다. 객체 멤버 사이에는 쉼표가 필요하지만 마지막 멤버 뒤에는 후행 쉼표를 둘 수 없습니다. 불리언 값은 true 또는 false로 작성해야 하며 문자열로 쓰면 안 됩니다. 포트는 보통 숫자이므로 "10808"처럼 작성하면 JSON 문법 검사는 통과하더라도 코어 필드 검사는 통과하지 못할 수 있습니다. 주석은 표준 JSON에 포함되지 않으므로 // 또는 블록 주석이 있는 예제를 복사하면 “invalid character”와 같은 파싱 오류가 발생하기 쉽습니다.
필드 이름은 대소문자를 구분합니다. outboundTag와 outboundtag는 서로 다른 필드이며, domainStrategy도 임의로 바꿔 쓸 수 없습니다. 또 자주 발생하는 문제는 계층을 잘못 배치하는 것입니다. 프로토콜 전용 매개변수는 보통 해당 객체의 settings 안에, 전송 매개변수는 streamSettings 안에 있어야 하며 서버 주소를 아웃바운드 루트에 직접 넣어서는 안 됩니다. “unknown field” 오류가 발생하면 네트워크를 의심하기 전에 필드의 소속 계층부터 확인하세요.
| 최상위 필드 | 주요 역할 | 일반적인 참조 관계 |
|---|---|---|
inbounds |
로컬 포트를 열고 SOCKS, HTTP 등의 연결 수신 | 인바운드 tag를 통해 라우팅 규칙에서 식별 |
outbounds |
프록시, 직접 연결, 차단 등의 출구 정의 | outboundTag로 선택 |
routing |
도메인, IP, 포트, 프로토콜 및 인바운드 태그에 따른 트래픽 분기 | 인바운드 태그를 읽고 아웃바운드 태그로 연결 |
dns |
도메인 조회 및 DNS 서버 선택 제공 | 라우팅 정책과 도메인 매칭 방식의 영향 |
policy |
타임아웃, 통계 활성화 및 시스템 수준 정책 설정 | 사용자 레벨 및 stats와 함께 사용 가능 |
최소 설정부터 단계적으로 확장
설정을 수동으로 관리할 때는 실행 가능한 최소 구성부터 시작해야 합니다. 로컬 인바운드 하나, 사용 가능한 아웃바운드 하나, 직접 연결 아웃바운드 하나와 소수의 라우팅 규칙이면 충분합니다. 코어가 파일을 읽는 것을 확인한 뒤 DNS, 복잡한 규칙과 정책 항목을 추가하세요. 이렇게 하면 “문법 오류”, “프로토콜 매개변수 오류”, “라우팅 논리 오류”를 나누어 처리할 수 있습니다. 수백 줄의 설정을 한 번에 붙여 넣는 것은 편해 보여도 괄호 하나만 어긋나면 원인을 찾는 데 드는 시간이 급격히 늘어납니다.
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom"
}
]
}
그래픽 클라이언트는 설정을 저장한 뒤 설정 파일을 다시 생성할 수 있으므로 임시 파일을 직접 수정해도 영구적으로 유지되지 않을 수 있습니다. 장기간 사용할 규칙은 클라이언트가 제공하는 사용자 지정 설정, 라우팅 규칙 또는 DNS 설정 메뉴에 우선 입력하세요. 시작 실패만 분석하려는 경우 현재 설정을 별도 위치로 내보내거나 복사한 뒤, 블록별로 줄여 가며 테스트하면 다음 구독 업데이트가 문제 해결 기록을 덮어쓰는 일을 피할 수 있습니다.
02 / INBOUNDS
inbounds 인바운드: 수신, 인증 및 트래픽 식별
인바운드는 로컬 애플리케이션의 접속 방식을 결정합니다
inbounds는 배열이므로 하나의 설정에서 여러 로컬 진입점을 동시에 제공할 수 있습니다. 데스크톱 클라이언트에서는 SOCKS와 HTTP 인바운드가 일반적입니다. 브라우저나 프록시 설정을 지원하는 프로그램은 HTTP 진입점에 연결하고, SOCKS5를 지원하는 프로그램은 SOCKS 진입점에 연결합니다. 투명 프록시, 터널 인터페이스 또는 LAN 공유는 더 복잡한 접속 방식이므로 기본 로컬 프록시가 정상적으로 작동한 뒤 활성화하는 것이 좋습니다. 각 인바운드에는 socks-in, http-in처럼 알아보기 쉽고 고유한 tag를 지정하면 라우팅 규칙에서 진입점별로 구분하기 편합니다.
listen은 수신 주소를 결정합니다. 127.0.0.1로 설정하면 일반적으로 현재 장치에서만 연결할 수 있어 개인 데스크톱 환경에 적합합니다. LAN에서 접근 가능한 주소로 변경하면 연결 가능한 범위가 넓어지므로 시스템 방화벽, 인바운드 인증 및 네트워크 경계를 함께 고려해야 합니다. “애플리케이션이 로컬 포트에 연결되지 않는다”는 이유만으로 수신 범위를 바로 넓히지 마세요. 먼저 클라이언트 실행 여부, 포트 점유 여부, 애플리케이션의 프록시 유형과 인바운드 프로토콜의 일치 여부를 확인해야 합니다.
port는 로컬 수신 포트이며 시스템 프록시 또는 애플리케이션 내부 프록시 설정과 일치해야 합니다. 포트 번호 자체에 정해진 값은 없지만, 같은 주소에서 두 프로그램이 동일한 포트를 동시에 사용할 수는 없습니다. 로그에 address already in use가 나타나면 충돌하는 프로세스를 종료하거나 수신 포트를 변경하고, 클라이언트가 중복 실행되지 않았는지도 확인하세요. 포트를 변경한 뒤에는 브라우저, 터미널 환경 변수 및 다른 애플리케이션의 프록시 주소도 업데이트해야 합니다. 그렇지 않으면 코어가 정상적으로 시작되어도 애플리케이션 트래픽이 유입되지 않습니다.
SOCKS 및 HTTP 인바운드 매개변수
SOCKS 인바운드의 settings에는 보통 auth와 udp가 포함됩니다. 로컬 루프백 주소에서 개인적으로 사용하는 경우에는 noauth를 자주 사용하지만, 수신 범위를 넓혔다면 클라이언트 기능에 맞춰 접근 제어를 설정해야 합니다. udp는 해당 인바운드가 UDP 요청을 받을지 결정할 뿐이며, 원격 프로토콜·아웃바운드 경로·대상 서비스가 UDP를 지원한다는 뜻은 아닙니다. HTTP 인바운드는 HTTP 프록시 요청과 CONNECT 터널을 주로 처리하므로 애플리케이션이 HTTP 프록시 모드를 명시적으로 지원해야 합니다. 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": {}
}
]
}
sniffing의 역할과 한계
sniffing은 연결 초기에 전달되는 데이터에서 대상 도메인을 식별합니다. 따라서 원래 대상 IP만 확인되는 트래픽도 도메인 규칙에 따라 분기할 수 있습니다. destOverride에는 보통 http와 tls가 사용되며, 각각 식별 가능한 HTTP 호스트 정보와 TLS 핸드셰이크의 서버 이름에 해당합니다. 웹 콘텐츠를 복호화하는 기능은 아니며 모든 연결에서 도메인을 복원할 수 있는 것도 아닙니다. 암호화된 클라이언트 인사말의 변경, 비표준 프로토콜 또는 IP 직접 접속에서는 라우팅이 IP만 확인할 수 있습니다.
트래픽 식별을 활성화한 뒤 일부 애플리케이션의 대상이 변경되거나 연결 동작이 이상해지면, 먼저 필요한 오버라이드 유형만 남기고 로그를 확인하세요. 라우팅을 식별 결과에 전적으로 의존해서는 안 됩니다. 중요한 로컬 네트워크, 예약 주소 및 알려진 IP 대역은 여전히 IP 규칙으로 설정해야 합니다. 반대로 식별을 끄면 많은 도메인 규칙이 매칭되지 않을 수 있습니다. 특히 시스템이 먼저 조회를 수행한 뒤 대상 IP만 전달하는 애플리케이션에서 그렇습니다. 활성화 여부는 인바운드 방식과 애플리케이션 동작을 함께 고려해 결정해야 하며, 모든 환경에 같은 설정을 기계적으로 적용해서는 안 됩니다.
여러 인바운드의 역할 분담
여러 인바운드는 서로 다른 프록시 유형을 지원하기 위한 것만이 아니라 서로 다른 라우팅 정책을 적용하는 데에도 사용할 수 있습니다. 예를 들어 한 SOCKS 인바운드는 일반적인 분기를 사용하고, 다른 인바운드는 지정된 아웃바운드로만 보낼 수 있습니다. 라우팅 규칙에서 inboundTag로 진입점을 매칭한 뒤 대상 outboundTag를 지정하면 됩니다. 진입점 전용 규칙은 일반적인 도메인 규칙보다 앞에 배치해야 합니다. 그렇지 않으면 연결이 더 포괄적인 규칙에 먼저 가로채일 수 있습니다.
인바운드를 점검할 때는 세 단계로 확인할 수 있습니다. 먼저 코어 로그에 수신 성공이 표시되는지 보고, 다음으로 로컬 장치에 해당 수신 포트가 실제로 열려 있는지 확인하고, 마지막으로 애플리케이션 요청이 실제로 유입되는지 확인하세요. 코어가 연결을 받지 못했다면 문제는 대개 애플리케이션 프록시 설정, 시스템 프록시 상태 또는 포트 충돌에 있습니다. 연결은 받았지만 대상에 도달하지 못한다면 라우팅, 아웃바운드 및 DNS로 범위를 좁히세요. 첫 단계가 확인되기 전에 서버 프로토콜 매개변수를 반복해서 바꾸지 마세요.
03 / OUTBOUNDS
outbounds 아웃바운드: 프로토콜, 서버 및 전송 계층
아웃바운드 배열과 태그 설계
outbounds는 연결이 코어를 빠져나가는 방식을 설명합니다. 일반적인 설정에는 프록시 아웃바운드 하나, freedom 직접 연결 아웃바운드 하나, blackhole 차단 아웃바운드 하나가 최소한 포함됩니다. 프록시 아웃바운드는 원격 서버에 연결하고, 직접 연결 아웃바운드는 로컬 네트워크로 대상에 접근하며, 차단 아웃바운드는 특정 연결을 명시적으로 거부합니다. 라우팅 모듈은 태그로 출구를 선택하므로 proxy, direct, block처럼 안정적이고 짧으며 용도를 드러내는 태그를 사용하는 것이 좋습니다. 노드를 교체할 때 proxy 내부의 서버 매개변수만 수정하면 전체 라우팅 규칙을 다시 작성하지 않아도 됩니다.
명시적인 라우팅 결과가 없을 때 배열 순서가 기본 출구에 영향을 줄 수 있습니다. 숨은 동작에 의존하지 않으려면 중요한 트래픽은 규칙에서 태그를 명시적으로 지정하고, 주요 프록시 아웃바운드는 알아보기 쉬운 위치에 유지하세요. 그래픽 클라이언트는 현재 노드에 따라 첫 번째 항목을 동적으로 변경할 수 있으므로 설정을 수동으로 병합할 때 배열 위치만 보고 출구 용도를 판단하지 말고 tag, protocol 및 프로토콜 설정을 함께 확인해야 합니다.
프로토콜 매개변수와 전송 매개변수의 계층
프록시 아웃바운드는 보통 두 부분으로 나뉩니다. settings에는 프로토콜 자체에 필요한 서버, 포트 및 사용자 정보가 들어가고, streamSettings에는 하위 네트워크, TLS, REALITY 또는 WebSocket 등의 전송 설정이 들어갑니다. 두 부분은 서버 설정과 일치해야 합니다. 프로토콜은 올바르지만 전송 계층이 다르면 TCP 연결 후 핸드셰이크 실패가 흔히 발생하고, 전송 계층은 올바르지만 사용자 식별자가 틀리면 원격 서버가 즉시 거부할 수 있습니다.
다음 예제는 VLESS 아웃바운드의 구조적 위치를 보여 줍니다. 도메인, 식별자 및 공개 키는 구조 설명을 위한 예시 값이므로 실제 설정으로 교체해야 합니다. security는 사용자 객체 안에서 VLESS 사용자 계층 설정을 설명하고, streamSettings 안의 security는 전송 보안 방식을 나타냅니다. 이름이 같은 두 필드라도 서로 다른 계층에 있으므로 서로 대체할 수 없습니다.
{
"outbounds": [
{
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "server.example.com",
"port": 443,
"users": [
{
"id": "00000000-0000-4000-8000-000000000000",
"encryption": "none",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "www.example.com",
"fingerprint": "chrome",
"publicKey": "replace-with-server-public-key",
"shortId": "0123456789abcdef"
}
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {
"response": {
"type": "none"
}
}
}
]
}
address, serverName 및 대상 도메인은 서로 다릅니다
address는 클라이언트가 실제로 연결하는 서버 주소이며 도메인 또는 IP가 될 수 있습니다. TLS 또는 REALITY 관련 serverName은 핸드셰이크에 포함되는 서버 이름이며, 두 값이 같을 때도 있고 서버 설정에 따라 다를 때도 있습니다. 라우팅에서 사용하는 대상 도메인은 애플리케이션이 원래 접속하려는 사이트입니다. 문제를 해결할 때 이 세 가지를 반드시 구분하세요. 서버 주소 조회 실패는 연결 진입점 문제이고, 서버 이름 불일치는 보통 핸드셰이크 실패로 나타나며, 애플리케이션 대상 도메인이 잘못된 출구로 가는 것은 라우팅 문제입니다.
서버 주소가 도메인이라면 코어는 프록시 연결을 설정하기 전에 해당 도메인도 조회해야 합니다. DNS 규칙이 지나치게 공격적으로 설정되면 서버 도메인 자체의 조회가 아직 연결되지 않은 프록시 경로로 전송되어 순환 의존성이 생길 수 있습니다. 안정적인 방법은 서버 도메인에 사용할 수 있는 초기 조회 경로를 마련하거나, 클라이언트가 제공하는 서버 주소 처리 방식에 맞춰 설정하는 것입니다. DNS를 변경한 뒤 모든 노드가 동시에 작동하지 않는다면 노드를 하나씩 다시 입력하기보다 이 계층부터 확인하세요.
여러 프록시 아웃바운드와 선택 관계
하나의 설정에 proxy-main과 proxy-alt처럼 여러 프록시 아웃바운드를 포함할 수 있습니다. 그러나 V2Ray 코어 설정에서 여러 아웃바운드를 지정한다고 해서 그래픽 클라이언트의 지연 시간 선택이나 자동 장애 조치가 이루어지는 것은 아닙니다. 실제 선택은 라우팅 규칙, 부하 분산 정책 또는 클라이언트 생성 로직에 따라 결정됩니다. 여러 노드 객체를 배열에 추가하는 것만으로 자동 전환될 것이라고 기대하지 마세요. v2rayN, v2rayNG 및 v2flyNG의 노드 선택 화면은 해당 설정을 생성하지만, 수동 설정에서는 각 태그를 어떤 규칙이 참조하는지 명확히 해야 합니다.
아웃바운드 실패는 외부에서 내부 순서로 점검하세요. 서버 주소가 조회되는지 확인하고, 대상 포트에 연결할 수 있는지 확인한 다음, 프로토콜 사용자 필드를 대조하고, 마지막으로 전송 보안과 네트워크 유형을 확인합니다. 로그의 timeout은 주소·포트 또는 경로에 접근할 수 없음을 가리키는 경우가 많고, handshake failed는 전송 계층 매개변수에 더 가깝습니다. invalid user 또는 인증 관련 메시지는 사용자 식별자를 다시 확인해야 합니다. TLS 오류의 세부 분류는 TLS 인증서 오류 문제 해결 체크리스트에서 확인할 수 있습니다.
04 / ROUTING
routing 라우팅 규칙: 매칭 순서와 분기 작성법
규칙은 위에서부터 매칭됩니다
routing.rules는 순서가 있는 규칙 배열입니다. 코어는 연결 속성을 규칙별로 확인하고, 적용 가능한 규칙을 찾으면 해당 아웃바운드를 선택하므로 규칙 순서가 결과를 직접 결정합니다. 더 구체적이고 우선순위가 높은 규칙을 앞에 두고, 기본 처리 규칙은 뒤에 배치해야 합니다. 예를 들어 불필요한 프로토콜을 차단하고, 내부 네트워크 주소를 처리하고, 특정 도메인을 직접 연결한 다음 프록시 또는 기본 출구를 배치할 수 있습니다. 범위가 매우 넓은 도메인 규칙을 먼저 작성하면 뒤의 정밀한 규칙은 문법이 올바르더라도 적용될 기회를 잃을 수 있습니다.
규칙의 여러 매칭 차원은 하나의 연결에 여러 조건을 함께 적용하는 데 사용됩니다. 예를 들어 하나의 규칙에 inboundTag와 domain을 함께 넣으면 지정한 인바운드에서 들어오면서 도메인 조건도 만족해야 합니다. 하나의 차원 안에 여러 항목을 넣으면 보통 그중 하나만 일치해도 매칭됩니다. 복잡한 규칙을 설계할 때는 먼저 “socks-special 인바운드에서 들어오고 대상이 example.com에 속하는 연결은 proxy-alt로 보낸다”처럼 자연어로 적은 뒤 필드로 옮기세요. 이렇게 하면 ‘그리고’와 ‘또는’의 관계를 뒤집는 실수를 줄일 수 있습니다.
domainStrategy와 도메인 매칭
domainStrategy는 라우팅 과정에서 IP 규칙에 사용하기 위해 도메인을 언제 조회할지 결정합니다. 일반적으로는 가능한 한 도메인으로 매칭하고 필요할 때만 IP로 조회하거나, 도메인 규칙이 매칭되지 않은 뒤 IP 규칙을 시도하는 방식이 사용됩니다. 지원되는 값과 세부 동작은 코어와 설정 환경에 따라 다르므로 현재 클라이언트의 코어 동작을 기준으로 확인해야 합니다. 원칙은 동일합니다. 조회 작업은 DNS 의존성을 추가하므로 정책이 적극적일수록 DNS 경로가 안정적인지 확인해야 합니다.
도메인 항목에는 완전 일치, 하위 도메인 범위, 키워드 및 규칙 데이터셋을 자주 사용합니다. full:example.com은 완전한 도메인만 매칭하고, domain:example.com은 해당 도메인과 하위 도메인을 포함하며, keyword:example은 범위가 더 넓어 오매칭 위험도 커집니다. geosite: 항목은 코어에서 사용할 수 있는 도메인 데이터 분류를 참조합니다. 규칙 데이터는 현재 코어의 리소스와 맞아야 하며, 분류가 없거나 리소스가 로드되지 않은 경우 이를 네트워크 장애로 판단해서는 안 됩니다.
IP, 포트 및 프로토콜 규칙
IP 규칙에는 단일 주소, CIDR 네트워크 또는 geoip: 데이터 분류를 사용할 수 있습니다. 루프백, 사설 네트워크 및 링크 로컬 범위와 같은 내부 주소는 보통 직접 연결로 명시하는 것이 좋습니다. 포트는 단일 포트나 범위로 작성해 특정 서비스 트래픽을 제한할 수 있지만, 포트만으로 애플리케이션 유형을 정확히 판단할 수는 없습니다. 같은 포트가 서로 다른 서비스를 전달할 수도 있기 때문입니다. 프로토콜 식별은 코어가 인식할 수 있는 연결 특성에 의존하므로 명확한 대상에만 사용하고 도메인 및 IP 규칙을 대신하게 해서는 안 됩니다.
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": [
"geoip:private"
],
"outboundTag": "direct"
},
{
"type": "field",
"domain": [
"full:intranet.example.com",
"domain:local.example"
],
"outboundTag": "direct"
},
{
"type": "field",
"domain": [
"geosite:category-ads-all"
],
"outboundTag": "block"
},
{
"type": "field",
"inboundTag": [
"socks-special"
],
"outboundTag": "proxy"
}
]
}
}
기본 출구와 규칙의 마지막
모든 대상을 덮는 규칙을 반드시 마지막에 작성해야 하는 것은 아닙니다. 규칙에 매칭되지 않았을 때 어떤 아웃바운드를 사용하는지는 코어의 기본 동작과 아웃바운드 배열 순서에 따라 달라집니다. 설정을 검토하기 쉽게 하려면 주요 출구의 위치를 일정하게 유지하고 예외 트래픽을 명시적으로 작성하세요. 여러 장치나 팀에서 규칙을 공유한다면 관리자의 기억에 의존하지 말고 “기본 경로”를 문서에 적어 두는 것이 좋습니다. 새 노드를 가져온 뒤 아웃바운드 순서가 바뀌었는지 확인하는 것도 필요합니다.
분기가 작동하지 않을 때는 라우팅 단계의 대상이 도메인으로 표시되는지 IP로 표시되는지 먼저 확인하세요. 규칙은 도메인인데 로그에는 IP만 보인다면 인바운드 식별과 DNS 처리를 점검하고, 대상 도메인은 보이지만 매칭되지 않는다면 접두사와 규칙 순서를 확인하세요. 올바른 태그가 매칭되었는데도 연결에 실패한다면 해당 아웃바운드로 넘어가야 합니다. “매칭되지 않음”과 “매칭 후 아웃바운드 실패”를 구분하면 규칙 목록에 중복 항목을 계속 추가하는 일을 피할 수 있습니다.
클라이언트 사용자 지정 규칙의 적용 위치
v2rayN의 라우팅 설정과 v2rayNG 및 v2flyNG의 분기 설정은 최종적으로 코어가 읽을 수 있는 규칙으로 변환됩니다. 클라이언트마다 규칙 집합, 사전 설정 모드 및 사용자 지정 항목의 병합 순서가 다를 수 있습니다. 수정하기 전에 현재 설정을 내보내거나 실행 설정을 확인해 사용자 지정 규칙이 사전 설정 규칙보다 앞에 오는지 뒤에 오는지 확인하세요. 클라이언트의 “LAN 우회”, “전체”, “규칙” 같은 모드는 단순한 화면 스위치가 아니라 설정 생성 로직을 제어합니다.
중국 본토 직접 연결과 해외 프록시처럼 흔히 쓰는 구성은 도메인 분류, IP 데이터 및 규칙 순서가 함께 작용하므로 규칙 한 줄만 복사해서는 완성되지 않습니다. 전체 작성법과 문제 해결 과정은 V2Ray 라우팅 규칙 설정 실전 가이드에서 확인하세요. 규칙을 이전할 때는 대상 클라이언트가 사용하는 코어 계열과 리소스 파일이 동일한 분류 이름을 지원하는지도 확인해야 합니다.
05 / DNS
DNS 설정: 서버 선택, 도메인 규칙과 출구 관계
V2Ray DNS는 어떤 문제를 해결하나요?
DNS 모듈은 코어가 조회해야 하는 도메인에 결과를 제공하고, 도메인 유형에 따라 서로 다른 서버를 선택할 수도 있습니다. 시스템 DNS를 완전히 대체하는 관계는 아닙니다. 애플리케이션이 시스템 계층에서 먼저 조회한 뒤 IP만 프록시에 전달할 수도 있고, 도메인을 그대로 SOCKS 또는 HTTP 인바운드에 전달할 수도 있습니다. 서버 주소 자체도 시스템 또는 코어가 초기 조회를 수행해야 할 수 있습니다. 따라서 DNS 문제를 판단하기 전에 누가 조회를 시작했는지, 대상 도메인이 어느 계층에서 조회되는지, 조회 결과가 라우팅에 사용되는지를 먼저 확인해야 합니다.
가장 간단한 servers 배열에는 localhost 또는 DNS 서버 주소를 넣을 수 있습니다. 더 세밀한 객체 형식에서는 서버 주소, 적용 도메인 및 조회 기대치를 지정할 수 있습니다. 서버 순서를 “첫 번째가 실패하면 항상 두 번째를 사용한다”라고 단순하게 이해해서는 안 됩니다. 실제 동작은 도메인 매칭, 조회 유형 및 코어 구현의 영향도 받습니다. 여러 서버를 설정할 때는 더 나은 결과를 기대하며 주소를 많이 쌓기보다 각 서버가 어떤 도메인을 담당하는지 명확히 정하세요.
도메인에 따라 DNS 서버 선택
서버 객체에 domains를 설정하면 매칭되는 도메인에 해당 서버를 우선 사용할 수 있습니다. 도메인 표현 방식은 라우팅 규칙과 비슷하며 완전한 도메인, 도메인 범위 및 사용 가능한 데이터 분류를 사용할 수 있습니다. 이 규칙은 “어느 서버에 조회할지”를 담당하고, 라우팅 규칙은 “조회 트래픽 또는 최종 연결이 어느 출구로 나갈지”를 담당하므로 서로 다른 계층입니다. DNS 도메인 조건만 작성하고 해당 출구를 처리하지 않았다고 해서 조회가 예상한 경로로 나가는 것은 아닙니다.
{
"dns": {
"hosts": {
"router.example": "192.168.1.1"
},
"servers": [
{
"address": "localhost",
"domains": [
"full:router.example",
"domain:local.example"
]
},
{
"address": "1.1.1.1",
"domains": [
"geosite:geolocation-!cn"
],
"skipFallback": true
},
"localhost"
],
"queryStrategy": "UseIP"
}
}
hosts는 특정 이름에 정적 매핑을 제공하므로 고정된 로컬 서비스 이름이나 테스트 환경에 적합합니다. 대규모이거나 자주 변경되는 주소 목록을 관리하는 용도로는 적합하지 않습니다. 정적 매핑은 일반 조회를 우회하므로 주소가 바뀌면 오래된 값 때문에 연결 이상이 계속될 수 있습니다. 특정 도메인의 조회 결과가 시스템과 다를 때는 클라이언트 화면에서 생성한 사용자 지정 호스트 기록을 포함해 hosts도 확인하세요.
조회 정책과 주소 계열
queryStrategy는 조회할 주소 유형을 제어합니다. 실제로 선택 가능한 값과 세부 동작은 사용하는 코어에 따라 다르지만, 일반적으로 IPv4와 IPv6를 함께 사용하거나 한쪽만 조회하거나 환경에 따라 선택하는 방식이 있습니다. 한 번 IPv6 경로를 사용할 수 없었다고 관련 기능을 모두 영구적으로 삭제하지 마세요. 먼저 로컬 네트워크, 원격 아웃바운드 및 대상 사이트가 완전한 경로를 구성하는지 확인하는 편이 합리적입니다. 시스템에 주소는 있지만 사용 가능한 경로가 없으면 조회가 성공해도 연결이 시간 초과될 수 있으며, 이는 DNS가 결과를 반환하지 않은 문제가 아니라 네트워크 경로 문제입니다.
도메인 규칙에서 IP 분류를 사용할 때 코어는 먼저 대상을 조회한 뒤 결과를 IP 규칙과 비교할 수 있습니다. 이때 조회 정책이 라우팅 결과에 간접적으로 영향을 줍니다. 같은 도메인이라도 서로 다른 주소 계열이 반환되면 다른 네트워크 규칙에 매칭될 수 있습니다. 설정을 설계할 때 라우팅 결론이 우연한 한 번의 조회 결과에 지나치게 의존하지 않도록 하세요. 안정적으로 직접 연결해야 하는 내부 네트워크 이름은 명확한 도메인 규칙과 내부 네트워크 대역 규칙을 함께 적용하는 편이 유지 관리하기 쉽습니다.
DNS 조회는 아웃바운드를 어떻게 선택하나요?
DNS 서버 주소 자체도 네트워크 대상이므로 전용 태그나 라우팅 규칙으로 출구를 제어할 수 있습니다. 일반 IP 주소를 DNS 서버로 사용한다면 대상 IP와 포트로 식별할 수 있습니다. 암호화된 DNS를 도메인 형식으로 사용한다면 해당 서버 도메인의 초기 조회도 먼저 해결해야 합니다. 흔한 순환은 프록시 서버 조회에 DNS가 필요하고, DNS가 프록시 아웃바운드로 라우팅되며, 프록시 아웃바운드는 다시 서버 주소를 먼저 조회해야 하는 경우입니다. 시작 경로에 프록시에 의존하지 않는 사용 가능한 조회 진입점을 남겨 두거나, 클라이언트가 지원하는 명시적인 부트스트랩 설정을 사용하세요.
DNS 조회는 성공했지만 웹 페이지가 열리지 않는다면 조회 결과에서 멈추지 말고 최종 연결을 계속 확인해야 합니다. 조회된 IP가 잘못된 아웃바운드로 라우팅되거나, 원격 측이 해당 주소 계열을 지원하지 않거나, 대상 포트가 차단되었거나, 애플리케이션이 코어 DNS를 사용하지 않는 경우가 있을 수 있습니다. 반대로 웹 페이지가 열린다고 해서 모든 DNS 조회가 설정대로 수행된다는 뜻도 아닙니다. 애플리케이션 자체의 조회 방식이 로컬 프록시를 우회할 수 있기 때문입니다. 정확히 확인하려면 로그의 대상 형식, 인바운드 프로토콜 및 애플리케이션 프록시 방식을 함께 살펴보세요.
캐시, FakeDNS 및 문제 해결의 범위
일부 클라이언트와 코어 환경에서는 투명한 접속 시 도메인 매핑을 유지하기 위해 캐시 또는 FakeDNS를 사용합니다. FakeDNS는 내부 매핑 주소를 반환하고, 코어는 연결을 받은 뒤 실제 도메인으로 복원합니다. 이 주소가 다른 애플리케이션이나 시스템 구성 요소에서 사용되거나 호환되지 않는 인바운드가 처리하면 대상 IP가 이상해 보일 수 있습니다. 활성화하기 전에 현재 접속 방식에 정말 필요한지 확인하고, 관련 주소 범위가 로컬 네트워크와 충돌하지 않도록 유지하세요.
DNS 문제를 해결하는 가장 효과적인 방법은 계층별로 바꿔 보는 것입니다. 먼저 확실히 사용할 수 있는 일반 서버 하나로 기본 조회를 검증하고, 도메인 그룹을 복원한 다음 조회 정책과 전용 라우팅을 추가하세요. 매번 변수 하나만 변경하고 대상 도메인, 반환 주소 및 최종 아웃바운드 태그를 기록합니다. 설정 메뉴에 대한 자세한 설명은 사이트의 V2Ray 사용 절차 클라이언트 장에서 함께 확인할 수 있습니다.
06 / POLICY
policy 정책: 연결 타임아웃, 사용자 레벨 및 통계 설정
정책 객체의 두 계층 구조
policy는 연결 수명과 통계 동작을 한곳에서 설정하며, 일반적으로 levels와 system을 포함합니다. levels는 사용자 레벨을 키로 사용하고 각 레벨에서 핸드셰이크, 유휴 연결 및 업로드·다운로드 종료 후 대기 시간 등의 매개변수를 정의합니다. system은 인바운드 및 아웃바운드 통계를 활성화할지 제어합니다. 대부분의 개인 클라이언트에는 복잡한 레벨이 필요하지 않지만, 이 구조를 이해하면 일정 시간 유휴 상태인 연결이 종료되는 이유나 통계 모듈에 데이터가 생성되지 않는 이유를 설명하는 데 도움이 됩니다.
레벨 번호는 속도 우선순위가 아니며 특정 사용자에게 더 높은 대역폭을 자동으로 제공하지도 않습니다. 사용자 또는 프로토콜 객체가 참조하는 level을 하나의 정책 그룹에 매핑할 뿐입니다. 설정에 레벨 0만 있다면 기본 레벨을 사용하는 모든 연결은 이 값을 사용합니다. 레벨을 추가해도 이를 참조하는 사용자가 없으면 실제 효과가 없습니다. 서버용 설정을 클라이언트로 이전할 때 흔한 문제는 복잡한 레벨 표는 남겨 두고 원래 이를 참조하던 사용자 객체를 삭제해 이해하기 어려운 불필요한 설정을 만드는 것입니다.
연결 수명 매개변수
handshake는 일반적으로 연결 설정 단계에서 허용되는 대기 시간을 제어합니다. connIdle은 데이터 활동이 없는 연결을 얼마나 오래 유지할지 결정하고, uplinkOnly와 downlinkOnly는 한쪽 데이터가 끝난 뒤 다른 쪽을 계속 기다리는 시간을 설정합니다. 구체적인 단위와 지원 범위는 현재 코어의 필드 정의를 기준으로 확인해야 합니다. 유휴 시간이 너무 짧으면 장시간 연결, 메시지 푸시 또는 다운로드 제어 연결이 자주 다시 설정될 수 있고, 너무 길면 이미 무효화된 연결이 더 오래 리소스를 점유합니다.
타임아웃은 길수록 안정적인 것이 아닙니다. 서버 주소에 접근할 수 없을 때 핸드셰이크 대기 시간이 너무 길면 장애 피드백이 늦어지고, 네트워크가 자주 바뀌는 환경에서는 이전 연결을 오래 유지해도 자동으로 복구되지 않습니다. 정책을 조정하기 전에 로그에서 연결 종료 원인을 확인하세요. 원격 서버가 먼저 연결을 닫았다면 로컬 유휴 시간을 늘려도 의미가 없고, 애플리케이션 자체가 주기적으로 재연결한다면 모든 재연결을 코어 정책 탓으로 돌려서는 안 됩니다.
{
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300,
"uplinkOnly": 2,
"downlinkOnly": 5,
"statsUserUplink": false,
"statsUserDownlink": false
}
},
"system": {
"statsInboundUplink": false,
"statsInboundDownlink": false,
"statsOutboundUplink": false,
"statsOutboundDownlink": false
}
}
}
통계 설정은 통계 결과가 아닙니다
정책의 통계 필드는 코어가 해당 차원의 데이터를 수집하도록 허용할 뿐이며, 최상위 stats 객체와 통계를 읽을 수 있는 인터페이스 또는 클라이언트 기능도 필요합니다. 모든 스위치를 true로 바꾼다고 해서 화면에 데이터가 자동으로 나타나는 것은 아닙니다. 반대로 클라이언트가 트래픽 정보를 표시하기 위해 통계 설정을 생성할 때 API 인바운드나 내부 라우팅이 함께 추가될 수도 있으므로 policy만 남기고 관련 객체를 삭제해서는 안 됩니다.
통계는 일정한 상태 관리 비용을 추가하므로 개인 환경에서는 실제로 필요한 차원만 활성화해야 합니다. 아웃바운드 전체량만 확인하려면 모든 사용자의 업로드·다운로드 통계를 함께 켤 필요가 없습니다. 설정을 검토할 때는 세 가지를 확인하세요. 어떤 차원을 관찰할지, 어느 인터페이스에서 읽을지, 어느 클라이언트 화면에서 표시할지입니다. 답할 수 없다면 “필드가 모두 갖춰져야 한다”는 이유로 불필요한 모듈을 추가하지 말고 단순한 설정을 우선하세요.
클라이언트가 생성한 정책 처리 방식
v2rayN, v2rayNG 및 v2flyNG는 트래픽 통계, 연결 테스트 또는 로컬 관리 기능에 따라 정책 필드를 설정에 기록할 수 있습니다. 수동으로 설정을 덮어쓸 때는 먼저 관련 클라이언트 기능을 끄거나 클라이언트가 지원하는 사용자 지정 메뉴를 사용해야 합니다. 그렇지 않으면 다음 실행 시 설정이 다시 생성될 수 있습니다. 특히 데스크톱에서 시스템 프록시, 연결 테스트 및 통계 표시를 동시에 사용하면 실행 설정은 구독에 포함된 단일 노드 링크와 일치하지 않는 경우가 많습니다.
정책 문제 해결은 네트워크 문제 해결과 분리해야 합니다. 코어 시작 실패가 policy 필드를 명확히 가리킨다면 타입, 레벨 키 및 현재 코어의 지원 여부를 확인하세요. 연결은 설정되지만 너무 빨리 끊긴다면 유휴 시간과 애플리케이션 동작을 비교하고, 통계가 비어 있다면 전체 데이터 수집 경로를 확인해야 합니다. 이 세 가지를 나누어야 설정 구조 문제인지, 연결 수명 문제인지, 클라이언트 표시 문제인지 판단할 수 있습니다.
언제 기본값을 유지해야 하나요?
일반적인 웹 브라우징, 명령줄 프록시 및 일상적인 구독 사용에서는 보통 policy를 수동으로 조정할 필요가 없습니다. 기본값은 일반적인 환경을 고려해 설정되어 있으므로 로그와 재현 절차를 통해 특정 연결이 실제로 정책 시간의 영향을 받는다는 증거가 없다면 “더 빠르게” 만들기 위해 변경하지 않는 것이 좋습니다. 정책 매개변수는 대기와 상태를 제어할 뿐 원격 회선 품질이나 서버 처리량을 높이지 않습니다.
정말 조정해야 한다면 현재 값과 재현 조건을 먼저 기록하고, 한 번에 하나의 매개변수만 변경한 뒤 같은 애플리케이션과 네트워크 경로에서 결과를 관찰하세요. 변경 후 연결 문제가 그대로라면 기본값으로 되돌리고 아웃바운드와 시스템 네트워크를 계속 확인하세요. 설정 가이드의 목적은 모든 필드를 바꾸게 하는 것이 아니라 필요한 변경에 명확한 근거를 제공하는 것입니다.
07 / LOG & STATS
로그, 통계 및 실행 설정: 관찰 가능한 문제 해결 환경 만들기
log 필드와 로그 레벨
log는 코어가 어떤 실행 정보를 출력할지 결정합니다. 일반적인 레벨은 상세 디버그 정보에서 경고와 오류 중심으로 점차 줄어드는 형태입니다. 일상적인 사용에서는 warning과 같이 비교적 간결한 레벨을 선택하고, 복잡한 문제를 재현할 때만 일시적으로 상세도를 높인 뒤 문제가 확인되면 되돌리세요. 가장 상세한 로그를 장기간 유지하면 중복 정보가 많아져 중요한 오류를 찾기 어려워지고 디스크 공간도 추가로 사용할 수 있습니다.
로그는 보통 액세스 기록과 오류 기록으로 나뉩니다. 액세스 기록은 “어떤 연결이 들어왔고, 대상이 무엇이며, 어떤 출구를 선택했는가”를 보여 주고, 오류 기록은 “어느 단계에서 어떤 이유로 실패했는가”를 보여 줍니다. 마지막 한 줄만 보면 실제 원인이 앞부분의 DNS, 라우팅 또는 핸드셰이크 정보에 있는데도 단순히 “연결 종료”로 오해할 수 있습니다. 문제를 해결할 때는 코어 시작부터 장애가 발생한 시점까지의 전체 시간대와 재현 동작을 함께 보존하세요.
{
"log": {
"access": "",
"error": "",
"loglevel": "warning"
},
"stats": {}
}
빈 경로를 처리하는 구체적인 방식은 코어와 클라이언트의 시작 매개변수에 따라 달라지며, 그래픽 클라이언트는 보통 로그 출력을 가로채 화면에 표시합니다. 수동으로 특정 파일 경로를 입력하면 클라이언트가 반드시 해당 파일을 읽는다고 가정하지 마세요. Windows, macOS, Android 및 Linux는 애플리케이션 데이터 디렉터리와 권한 모델이 다르므로 클라이언트 내장 로그 창이나 내보내기 기능을 우선 사용하세요. 클라이언트를 다시 설치해야 한다면 설치 패키지 페이지에서 플랫폼에 맞는 버전을 선택할 수 있습니다.
로그를 읽는 단계별 순서
시작 로그에서는 먼저 설정 파싱을 확인하세요. JSON 문자 위치, 알 수 없는 필드 또는 타입 오류가 나타난다면 코어는 아직 네트워크 연결 단계에 들어가지 않은 것이므로 노드 주소를 수정해도 의미가 없습니다. 설정 로드에 성공한 뒤에는 인바운드 수신을 확인하고 포트와 주소를 점검하세요. 이어 DNS와 라우팅을 관찰해 대상이 식별되고 예상한 아웃바운드에 매칭되는지 확인한 다음, 마지막으로 원격 연결, TLS 또는 프로토콜 핸드셰이크를 살펴봅니다. 데이터 흐름을 따라 로그를 읽으면 긴 메시지도 명확한 단계별로 분류할 수 있습니다.
일반적인 오류 문구는 문맥과 분리해서 해석해서는 안 됩니다. timeout은 DNS, TCP 연결 또는 핸드셰이크 단계에서 발생할 수 있고, connection refused는 로컬 포트, 원격 포트 또는 중간 전달에서 발생할 수 있습니다. failed to find an available destination은 아웃바운드 선택, 조회 결과 또는 정책과 관련될 수 있습니다. 판단할 때는 영어 문구 하나만 검색하지 말고 오류 전후의 모듈 이름, 대상 주소 및 태그를 함께 확인하세요.
실행 설정과 저장 설정
클라이언트 화면에 저장되는 것은 노드, 구독, 라우팅 모드 및 애플리케이션 설정이며, 실제로 코어에 전달되는 실행 설정은 시작 시 동적으로 합성될 수 있습니다. 문제를 해결할 때는 구독 링크의 노드 필드만 보지 말고 실행 설정을 확인해야 합니다. 클라이언트가 로컬 인바운드, API, 통계, DNS, 직접 연결 및 차단 아웃바운드를 추가할 수 있으며, 시스템 프록시 설정은 코어 설정 외부에 있습니다. 실행 설정은 올바른데 애플리케이션 트래픽이 들어오지 않는다면 JSON을 계속 수정하기보다 시스템 프록시 또는 애플리케이션 프록시를 점검해야 합니다.
테스트를 위해 실행 설정을 복사할 때는 임시 포트, 클라이언트 내부 태그 및 경로에 주의하세요. 코어를 독립적으로 실행하기 전에 환경 의존성을 현재 장치에서 사용할 수 있는 설정으로 바꿔야 합니다. 반대로 수동 작성 설정을 클라이언트로 가져와도 클라이언트가 다시 정리할 수 있습니다. 장기 유지 관리에서는 주된 출처를 하나로 정하세요. 클라이언트 설정을 기준으로 지원되는 사용자 지정 규칙을 확장하거나, 완전한 수동 설정을 기준으로 삼아 두 출처가 번갈아 덮어쓰지 않게 해야 합니다.
stats와 클라이언트 트래픽 표시
최상위 stats 객체는 통계 모듈을 활성화하는 데 사용되지만, 실제 지표는 policy의 스위치에도 좌우됩니다. 일부 클라이언트는 내부 API를 통해 인바운드, 아웃바운드 또는 사용자별 데이터를 읽어 화면에 표시합니다. API 객체나 내부 라우팅을 삭제하면 통계가 중단될 수 있지만 프록시 연결은 정상일 수 있습니다. “코어는 작동하지만 화면 데이터가 비어 있는” 상황은 노드가 작동하지 않는 경우와 분리해서 처리해야 합니다.
통계 값은 트래픽 방향과 특정 진입점을 연결이 통과했는지 확인하는 데 적합하지만, 회선 품질 점수로 사용하기에는 적합하지 않습니다. 처리량은 대상 서버, 네트워크 경로, 동시 연결 및 애플리케이션 동작의 영향을 함께 받습니다. 더 많은 숫자를 보기 위해 모든 통계 차원을 활성화하지 마세요. 먼저 “특정 인바운드가 업로드 트래픽을 받는지 확인한다”처럼 문제 해결 목표를 정한 뒤 해당 차원만 활성화하고, 확인이 끝나면 단순한 설정으로 되돌리세요.
최소 재현 환경 만들기
신뢰할 수 있는 문제 해결 기록에는 최소한 사용한 클라이언트 이름, 운영체제 플랫폼, 코어 계열, 재현 단계, 오류 발생 단계, 관련 태그 및 축약한 설정 구조가 포함되어야 합니다. 노드 인증 정보와 구독 내용은 공개해서는 안 됩니다. 프로토콜 유형, 필드 계층 및 예시 주소는 남겨 다른 사람이 구조 문제를 판단할 수 있게 하세요.
코어가 설정을 읽은 직후 종료된다면 로그로 config.json 설정 오류를 찾는 방법을 로그로 config.json 설정 오류 찾기에서 확인하세요. 오류가 certificate invalid, serverName 또는 핸드셰이크 단계에 집중된다면 TLS 인증서 오류 문제 해결 체크리스트로 이동해 시스템 시간, 서버 이름 및 인증서 체인을 순서대로 확인하세요.
08 / VALIDATION
전체 설정 조립, 검증 순서 및 장애 분기
읽기 쉬운 기본 설정 조립
전체 설정은 규칙 수보다 태그 관계를 명확히 하는 것이 먼저입니다. 아래 기본 구조에는 로컬 SOCKS 인바운드, 프록시 아웃바운드, 직접 연결 및 차단 출구, 간단한 DNS와 라우팅이 포함됩니다. 프록시 서버 정보는 여전히 예시이므로 실제 연결에 사용할 수 없습니다. 예제의 핵심은 각 모듈이 어떻게 서로 참조되는지 보여 주는 것입니다. 실제 사용에서는 그래픽 클라이언트가 구독을 바탕으로 프록시 아웃바운드를 자동으로 채우는 경우가 많으며, 수동 규칙은 클라이언트가 지원하는 설정 메뉴를 통해 병합하는 편이 적합합니다.
{
"log": {
"loglevel": "warning"
},
"dns": {
"servers": [
"localhost"
]
},
"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": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "server.example.com",
"port": 443,
"users": [
{
"id": "00000000-0000-4000-8000-000000000000",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"serverName": "server.example.com"
}
}
},
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "block",
"protocol": "blackhole"
}
],
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:category-ads-all"],
"outboundTag": "block"
}
]
},
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300
}
}
}
}
1단계: 문법 및 구조 검증
설정이 실행되지 않으면 먼저 JSON이 완전한지 확인하세요. 괄호가 쌍을 이루는지, 배열 멤버 사이에 쉼표가 있는지, 문자열에 큰따옴표를 사용했는지, 숫자와 불리언이 올바른 타입으로 작성되었는지 중점적으로 살펴봅니다. 편집기가 표시하는 오류 행은 파서가 더 이상 진행하지 못한 위치일 뿐이며, 실제로 빠진 쉼표는 앞 행에 있을 수 있습니다. 수정한 뒤 설정을 다시 읽어 JSON 파싱 오류가 더 이상 나타나지 않을 때까지 반복하세요.
문법 검사를 통과하면 필드 구조를 검증합니다. 필드 이름, 소속 계층 및 코어 지원 여부를 확인하세요. 다른 코어 계열, 오래된 튜토리얼 또는 다른 클라이언트에서 가져온 설정이라면 일부 필드를 사용할 수 없을 수 있습니다. Xray와 V2Fly는 공통 기반을 갖지만 프로토콜과 기능에서 차이가 있으므로 설정을 항상 그대로 서로 바꿔 쓸 수 있다고 가정해서는 안 됩니다. 두 코어 계열과 클라이언트의 조합을 알아보려면 Xray와 V2Fly 코어 관계 및 선택 가이드를 확인하세요.
2단계: 태그 및 수신 검증
모든 인바운드와 아웃바운드 태그를 전체 목록으로 만든 뒤 하나씩 참조를 확인하세요. 각 outboundTag에는 같은 이름의 아웃바운드가 있어야 하고, 각 inboundTag는 실제 진입점에 대응해야 합니다. 태그의 대소문자는 일치해야 하며 동일한 태그 이름을 여러 번 사용하면 설정 의미가 불명확해집니다. 그다음 각 인바운드가 정상적으로 수신을 시작했는지, 포트 충돌은 없는지, 애플리케이션 프록시 주소와 프로토콜 유형이 완전히 일치하는지 확인하세요.
애플리케이션에 접근할 수 없는데 코어에 해당 연결 로그가 전혀 없다면 시스템 프록시와 애플리케이션 설정에 집중해야 합니다. 데스크톱 환경에서는 시스템 프록시를 따르는 프로그램만 영향을 받을 수 있으며, 터미널 도구, 게임 또는 독립 브라우저는 자체 프록시 메뉴를 사용할 수 있습니다. Android 클라이언트는 보통 시스템 네트워크 인터페이스를 통해 트래픽을 가로채므로 애플리케이션 권한, 현재 설정 및 연결 상태를 중점적으로 확인해야 합니다. 플랫폼별 진입점은 설치 패키지 페이지에서 확인할 수 있습니다.
3단계: DNS, 라우팅 및 아웃바운드 검증
연결이 유입된 것을 확인한 뒤 로그의 대상 형식을 기록하세요. 도메인이라면 도메인 규칙을, 이미 IP라면 IP 규칙과 인바운드 식별을 확인합니다. 이어 실제로 매칭된 아웃바운드 태그를 확인하세요. 잘못 매칭되었다면 규칙 순서, 매칭 범위 또는 DNS 조회 결과를 조정해야 합니다. 올바르게 매칭되었지만 실패한다면 해당 아웃바운드의 서버 조회, 포트, 프로토콜 및 전송 계층을 확인하세요.
문제의 범위를 파악하기 위해 라우팅 규칙을 일시적으로 줄여 볼 수 있습니다. 먼저 내부 네트워크 직접 연결과 명확한 프록시 출구 하나만 남겨 기본 경로를 확인한 다음, 도메인 분류, 차단 규칙 및 전용 인바운드 규칙을 그룹별로 복원하세요. DNS도 같은 방식으로 단일 사용 가능 서버에서 시작해 도메인 그룹과 전용 출구를 복원합니다. 한 번에 한 그룹만 복원해야 장애를 유발한 변경을 정확히 찾을 수 있습니다.
일반적인 장애 분기
| 증상 | 우선 확인할 항목 | 다음 단계 |
|---|---|---|
| 코어가 시작된 직후 종료됨 | JSON 문법, 알 수 없는 필드, 포트 점유 | 최소 설정으로 줄인 뒤 단계별로 복원 |
| 애플리케이션은 연결되지만 액세스 로그가 없음 | 애플리케이션 프록시 유형, 주소, 포트, 시스템 프록시 | 요청이 올바른 인바운드로 들어오는지 확인 |
| 도메인 규칙이 매칭되지 않음 | 대상이 IP로 바뀌었는지, sniffing, 규칙 순서 | 도메인 및 IP 라우팅을 함께 관찰 |
| DNS를 수정한 뒤 모든 노드가 작동하지 않음 | 서버 도메인의 초기 조회 및 순환 의존성 | 기본 DNS를 복원한 뒤 규칙을 하나씩 추가 |
| TLS 또는 REALITY 핸드셰이크 실패 | 시스템 시간, serverName, 전송 매개변수 | 서버 설정과 대조해 필드 계층 확인 |
| 올바른 아웃바운드에 매칭되었지만 계속 시간 초과 | 서버 주소, 포트, 네트워크 경로, 주소 계열 | 조회 타임아웃, 연결 타임아웃 및 핸드셰이크 타임아웃 구분 |
변경 후 회귀 검사
설정을 복구해 사용할 수 있게 된 뒤 웹 페이지 하나만 확인하지 마세요. 최소한 도메인 대상, 직접 IP 대상, 로컬 네트워크 주소, 직접 연결이 필요한 사이트와 프록시가 필요한 사이트를 확인해 규칙 경계가 예상대로 작동하는지 점검하세요. UDP를 활성화했다면 실제로 UDP가 필요한 애플리케이션으로도 검증합니다. 그다음 클라이언트를 재시작해 설정이 안정적으로 다시 생성되고 로드되는지 확인해야 하며, 임시 실행 파일만 유효한 상태를 피해야 합니다.
구독을 업데이트한 뒤에는 사용자 지정 규칙이 유지되었는지, 현재 노드가 예상한 프록시 태그에 매핑되는지, 클라이언트가 코어를 변경했는지도 확인해야 합니다. v2rayN은 Windows, macOS 및 Linux 데스크톱 환경에 적합하고, v2rayNG는 Xray 코어를 사용하며, v2flyNG는 V2Fly 코어를 사용하는 Android 대안입니다. 세 클라이언트의 인터페이스는 다르지만 문제 해결 흐름은 같습니다. 진입, 식별, 라우팅, 조회, 출구 및 핸드셰이크를 단계별로 확인하세요.
마지막으로 변경 내용을 글로 기록해 변경 이유, 관련 모듈 및 검증 결과를 적어 두세요. 설정 파일은 복사할 수 있지만 네트워크 환경과 클라이언트 생성 로직은 바뀔 수 있습니다. 특정 규칙이 어떤 문제를 해결하는지 알아야 나중에 여전히 필요한지 판단할 수 있습니다. 빠른 작업은 사용 문서에서, 필드 이름과 프로토콜 개념은 용어집에서 확인하고, 구체적인 오류가 있을 때만 해당 블로그 글로 이동하세요. 모든 지식을 유지 관리하기 어려운 하나의 설정에 몰아넣지 않는 것이 좋습니다.
계속해서 확인하기
구조를 이해했다면 실제 작업에 따라 설치 패키지, 빠른 시작, 용어 설명 또는 로그 문제 해결 글로 이동하세요. 블로그 글은 구체적인 문제를 다루고, 이 페이지는 설정 구조에 대한 통합 참고 자료로 남겨 둡니다.