JSON 구조와 설정 범위 한눈에 보기
설정 출처를 확인한 뒤 필드를 수정하세요
V2Ray 설정은 서버 목록이 아니라 트래픽이 어떻게 들어오고, 규칙에 따라 어떻게 분류되며, 프로세스 밖으로 어떻게 나가는지를 정의하는 실행 설정입니다. 최상위 객체에는 보통 log, inbounds, outbounds, routing, dns, policy가 포함됩니다. 모든 항목이 필수는 아니며, 생략했을 때의 동작은 커널 기본값에 따라 달라집니다. 필드를 살펴보기 전에 실행 중인 커널이 Xray인지 V2Fly인지, 클라이언트가 시작할 때 설정을 다시 생성하는지 확인하세요. 그렇지 않으면 실제로 불러오는 파일이 아닌 다른 파일을 수정할 수 있습니다.
데스크톱에서는 보통 v2rayN으로 시작합니다. 구독을 가져온 뒤 인터페이스에서 서버, 시스템 프록시, 라우팅 모드를 선택하면 클라이언트가 이를 커널 설정으로 변환합니다. 이때 구독에는 연결 정보가 저장되고, 인터페이스에는 사용자 설정이 저장되며, 실행 디렉터리의 JSON은 생성된 결과물일 수 있습니다. 각 항목의 역할은 서로 다릅니다. 문제를 확인할 때 생성된 설정을 살펴볼 수는 있지만, 지속적으로 수정하려면 인터페이스에서 지원하는 설정이나 사용자 지정 설정 기능을 이용하세요. 임시로 편집한 내용을 저장된 클라이언트 설정으로 간주하지 말고, 덮어쓰기 동작을 모르는 상태에서 같은 파일을 반복해서 수정하지 마세요.
실행 가능한 로컬 직결 기본 설정
다음은 기본 설정 전체 예제입니다. 로컬 루프백 주소에서 SOCKS 인바운드를 열고, 들어온 연결을 freedom 아웃바운드로 전달하며, 로그 수준은 경고로 설정합니다. 원격 프록시에는 연결하지 않으므로 커널이 실행되는지, 로컬 포트를 사용할 수 있는지, 테스트 프로그램이 해당 인바운드를 실제로 사용하는지 확인하기에 적합합니다. 포트 번호는 예시입니다. 클라이언트가 이미 사용 중이면 충돌하는 프로세스를 먼저 종료하거나 비어 있는 다른 포트를 선택하세요. 직결 기본 설정이 작동한다는 것은 로컬 경로가 정상이라는 뜻일 뿐, 원격 설정까지 올바르다는 뜻은 아닙니다.
{
"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": {}
}
]
}
표준 JSON에서는 속성명과 문자열을 큰따옴표로 감싸고, 객체나 배열의 마지막 항목 뒤에 쉼표를 붙이지 않습니다. 불리언 값은 true 또는 false로 쓰며 숫자로 된 포트 번호에는 따옴표가 필요하지 않습니다. 일부 커널 도구는 주석이 포함된 확장 형식을 읽을 수 있지만, 편집기나 클라이언트 가져오기 기능 등에서는 지원하지 않을 수 있습니다. 복사와 문제 추적을 쉽게 하도록 이 문서에서는 표준 JSON만 사용하고 코드 안에 주석을 넣지 않습니다. 설명은 코드 밖에 작성해 파서 간 차이를 줄이고 필요한 부분만 바꾸기 쉽게 합니다.
객체·배열·태그의 구성 방식
inbounds와 outbounds는 배열입니다. 하나의 프로세스가 여러 진입점을 리스닝하고 여러 출구를 유지할 수 있기 때문입니다. 배열의 각 항목은 객체입니다. tag는 설정 내부에서 참조하는 이름이지, 프로토콜 이름이 아니며 해당 기능을 자동으로 만들지도 않습니다. 아웃바운드의 이름을 proxy로 지정해도 원격 주소가 생기는 것은 아닙니다. 라우팅의 outboundTag는 실제 아웃바운드 항목과 일치해야 합니다. 대소문자와 철자를 정확히 맞추고, 짧고 의미가 분명한 태그를 일관되게 사용하세요.
설정을 관리할 때는 변경 사항을 검증 가능한 작은 단계로 나누세요. 먼저 실행되는 기본 설정을 저장하고, 아웃바운드 하나를 추가한 다음 라우팅 규칙을 하나 추가하고, 마지막으로 DNS나 정책을 조정합니다. 매번 영향을 받는 필드와 예상 결과, 되돌리는 방법을 기록하세요. 배열 항목의 순서는 기본 출구와 라우팅 매칭에 영향을 줄 수 있으므로 보기 좋게 정렬하려고 임의로 순서를 바꾸면 안 됩니다. 클라이언트를 정상적으로 사용하는 것이 목적이라면 인터페이스가 생성한 설정을 우선 사용하세요. 특별한 동작이 꼭 필요할 때만 수동 관리로 전환해 인터페이스 설정과 커널 파일을 동시에 관리하는 부담을 피하세요.
inbounds: 로컬 리스닝과 트래픽 진입점
listen, port, protocol의 역할
인바운드는 애플리케이션이 커널에 전달하는 연결을 받습니다. listen은 바인딩할 로컬 주소, port는 리스닝 포트, protocol은 해당 포트가 처리할 요청 형식을 정합니다. 세 항목은 모두 중요합니다. 올바른 포트에 연결해도 프로토콜이 맞지 않으면 유효한 요청을 만들 수 없습니다. SOCKS 인바운드를 일반 HTTP 프록시 주소로 지정할 수 없으며, 반대의 경우도 마찬가지입니다. 문제를 확인할 때는 포트 숫자만 비교하지 말고 클라이언트에 표시된 리스닝 프로토콜과 애플리케이션의 프록시 유형도 하나씩 대조하세요.
로컬 애플리케이션에서만 사용할 때는 보통 127.0.0.1에 리스닝합니다. 이 주소는 로컬 루프백 연결만 허용하며 LAN 주소와는 다르고, IPv6 루프백 주소까지 자동으로 포함하지 않습니다. 0.0.0.0에 리스닝하면 일반적으로 모든 IPv4 네트워크 인터페이스에 바인딩됩니다. 다른 기기의 접근 가능 여부는 방화벽과 네트워크 격리 설정에도 영향을 받습니다. 리스닝 범위를 넓히기 전에 필요한 기기와 인증 방식, 클라이언트 종료 후에도 리스닝 프로세스가 남는지 확인하세요. LAN 접근을 허용하는 것은 단순한 연결 최적화가 아니라 접근 범위를 바꾸는 일입니다.
SOCKS 및 HTTP 이중 인바운드 예제
다음 코드 조각은 서로 다른 포트에 바인딩되는 독립된 인바운드 두 개를 보여 줍니다. 각 인바운드는 태그를 통해 이후 라우팅에서 참조할 수 있습니다. SOCKS의 udp는 해당 인바운드가 SOCKS UDP 요청을 처리하도록 허용한다는 뜻입니다. 애플리케이션이 실제로 해당 방식을 사용해야 하며, 아웃바운드와 네트워크 경로도 UDP를 지원해야 합니다. HTTP 인바운드는 HTTP 프록시 방식을 사용하는 애플리케이션을 위한 것입니다. 인바운드 두 개를 설정했다고 모든 프로그램과 전송이 자동으로 처리되는 것은 아닙니다. 첫 번째 장의 기본 설정에 적용하려면 같은 이름의 최상위 필드를 추가하는 대신 inbounds 배열 전체를 바꾸세요.
{
"inbounds": [
{
"tag": "socks-local",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
},
{
"tag": "http-local",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
]
}
일반적으로 같은 주소와 포트를 두 개의 리스닝 인스턴스가 동시에 사용할 수 없습니다. 바인딩 오류가 발생하면 클라이언트가 중복 실행 중인지, 테스트용 커널이 계속 실행 중인지, 이전 프로세스가 정상 종료됐는지 먼저 확인하세요. 애플리케이션 포트만 바꾸고 인바운드는 그대로 두거나, 인바운드만 바꾸고 시스템에서 예전 프록시 포트를 계속 사용하는 일이 없도록 하세요. 데스크톱 v2rayN에서는 인터페이스의 로컬 리스닝 포트가 다른 인바운드 설정과 연동될 수 있습니다. 실제 동작은 실행 설정과 로그를 기준으로 확인하고, 예시 포트를 모든 설치 환경의 고정값으로 간주하지 마세요.
스니핑과 원래 대상의 관계
인바운드에는 일부 프로토콜의 초기 데이터에서 도메인 등의 정보를 식별해 도메인 기반 라우팅에 활용하는 sniffing을 설정할 수도 있습니다. 이는 복호화 도구가 아니며 모든 연결을 식별한다고 보장할 수 없고, 올바른 DNS 설정을 대신하지도 않습니다. 연결에 IP만 포함되거나 일부 프로토콜에서 대상 정보가 보이지 않는 경우에는 규칙에 전달되는 입력이 달라집니다. 식별한 정보를 라우팅에만 활용하고 실제 대상은 바꾸지 않으려면 관련 옵션을 현재 커널이 지원하는지와 그 의미를 확인하세요. 서로 다른 커널의 고급 스니핑 필드를 그대로 복사하면 안 됩니다.
인바운드가 작동하는지 확인하려면 먼저 수동 프록시 설정을 지원하는 애플리케이션 하나에서 주소와 프로토콜을 지정하고, 별도 요청을 보낸 뒤 로그에 해당 인바운드 태그가 표시되는지 확인하세요. 기록이 전혀 없다면 애플리케이션이 프록시를 우회하는지, 다른 네트워크 설정을 사용하는지, 로그 수준이 연결 정보를 표시하기에 충분한지 점검하세요. 시스템 프록시는 애플리케이션에 설정을 제공하는 방법일 뿐, 트래픽을 강제로 전달하지는 않습니다. 적용 범위를 확인하는 기본 방법은 사용 가이드를 참고하고, 연결할 수 없는 문제는 문제 해결에서 항목별로 확인하세요.
outbounds: 프로토콜 출구와 원격 설정
아웃바운드를 만든 뒤 규칙에서 참조하세요
아웃바운드는 커널이 받은 트래픽을 대상으로 어떻게 전송할지 정의합니다. freedom은 대상에 직접 연결하고, blackhole은 트래픽을 버리거나 차단하며, 원격 프록시 프로토콜에는 서버 및 계정 정보가 추가로 필요합니다. 배열에 아웃바운드가 있다고 해서 반드시 사용되는 것은 아닙니다. 라우팅 결과와 기본 동작에 따라 선택됩니다. 일반적인 실행 방식에서는 어떤 규칙에도 일치하지 않은 연결이 첫 번째 아웃바운드를 사용하므로 배열 순서를 바꾸면 전체 트래픽 경로가 달라질 수 있습니다. 관리할 때는 기본 출구를 명확히 기록하고 태그 이름만 보고 동작을 추측하지 마세요.
다음 예제에는 직결과 차단 아웃바운드만 있습니다. 기본 인바운드와 함께 사용해 라우팅 참조를 연습할 수 있습니다. 원격 서버가 없으므로 원격 연결 설정으로 소개해서는 안 됩니다. settings는 프로토콜별 객체이며, 프로토콜마다 허용하는 필드가 다릅니다. 최상위 필드가 비슷해 보여도 내부 매개변수를 서로 바꿔 쓸 수 있다는 뜻은 아닙니다. 원격 프로토콜 객체를 freedom으로 바꿀 때는 기존 프로토콜 매개변수도 함께 정리하세요. 남은 필드 때문에 설정을 읽거나 문제를 추적하기 어려워지고, 커널이 해당 계정 정보를 계속 사용하는 것으로 오해할 수 있습니다.
{
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
]
}
연결 정보·전송 방식·보안 계층을 구분하세요
원격 아웃바운드에는 보통 서버 주소와 포트, 프로토콜 인증 정보, 전송 및 보안 설정이라는 세 가지 정보가 포함됩니다. VMess, VLESS, Trojan의 인증 정보 구조는 서로 다릅니다. TCP나 WebSocket 같은 전송 방식도 이름 하나만 바꿔서 전환할 수 없습니다. TLS는 별도의 계층이며 서버 이름과 인증서 검증이 관련됩니다. 연결 링크를 가져오면 클라이언트가 일부 항목을 변환하지만, 수동 설정에서는 전체 조합을 확인해야 합니다. 필드 하나만 그럴듯해 보여도 원격 서버의 다른 설정과 호환된다는 뜻은 아닙니다.
| 설정 계층 | 주요 역할 | 확인할 사항 |
|---|---|---|
| 프로토콜 settings | 원격 주소, 계정, 프로토콜 옵션 | 동일한 서비스 설정을 기준으로 입력 |
| streamSettings | 전송 방식 및 보안 계층 | 전송 방식·경로·보안 매개변수 간 호환성 |
| 아웃바운드 tag | 라우팅 규칙에서 참조 | 참조 이름을 정확히 일치 |
| 배열 위치 | 기본 출구 선택에 영향 | 첫 번째 아웃바운드가 예상과 일치하는지 |
서버 주소는 도메인이나 IP를 사용할 수 있지만, 연결 주소와 TLS 검증에 사용하는 서버 이름이 반드시 같지는 않습니다. 도메인으로 연결하는 경우 해당 도메인의 DNS 확인 방식도 영향을 주므로 원격 연결 실패가 계정 오류가 아니라 DNS 문제일 수 있습니다. 인증서 또는 핸드셰이크 오류가 발생하면 시스템 시간, 서버 이름, 인증서 체인, 전송 설정을 확인하고 먼저 인증서 검증을 끄지 마세요. 검증을 건너뛰면 보안 범위가 달라지고 주소 입력 오류가 가려질 수 있습니다. 검증을 유지한 채 설정을 바로잡아야 실제 서비스 문제와 로컬 설정 오류를 구분하기 쉽습니다.
커널 지원 여부에 따라 설정을 이전할 수 있습니다
Xray와 V2Fly는 설정 방식 일부를 공유하지만 모든 프로토콜 기능, 전송 필드, 선택값을 서로 사용할 수 있는 것은 아닙니다. 특정 보안 기능이나 확장 기능을 사용하는 연결 정보는 가져오거나 사용자 지정하기 전에 실행 중인 커널의 지원 여부를 확인하세요. 클라이언트 이름만으로 매번 어떤 커널이 실행되는지 단정할 수도 없습니다. v2rayN에서 실제 선택 항목은 인터페이스와 로그로 확인해야 합니다. v2rayNG는 Xray 계열 설정을 주로 사용하며 v2flyNG는 V2Fly 계열 Android 대안입니다. 커널을 바꿀 때는 전체 라우팅과 고급 기능을 한꺼번에 옮기지 말고 아웃바운드 하나부터 검증하세요.
구독을 관리할 때는 설정의 수명 주기도 고려해야 합니다. 구독을 업데이트하면 서버 매개변수가 바뀔 수 있고, 수동으로 수정한 하위 객체가 유지되지 않을 수 있습니다. 클라이언트가 현재 선택에 따라 아웃바운드 태그를 다시 생성할 수도 있습니다. 태그를 장기간 고정해 참조해야 한다면 클라이언트가 명시적으로 지원하는 사용자 지정 설정 방식을 사용하고 업데이트할 때마다 실제 생성 결과를 확인하세요. 설치 방법은 다운로드 센터에서 확인하고, 세 클라이언트의 사용 사례 비교는 클라이언트 비교를 참고하세요. 이 페이지는 원격 서비스를 제공하지 않으며, 연결 가능 여부는 실제 서비스 정보와 네트워크 접근성에 따라 달라집니다.
routing: 매칭 순서와 라우팅 규칙
규칙은 구체성 순이 아니라 작성한 순서대로 확인합니다
라우팅은 연결에 사용할 아웃바운드를 선택합니다. 일반적인 필드 규칙은 routing.rules 배열에 작성하며, 커널은 규칙을 순서대로 확인하고 일치한 항목의 처리 결과를 적용합니다. 모든 규칙을 모은 뒤 가장 정밀한 항목을 고르는 방식이 아닙니다. 따라서 명확한 예외는 보통 범위가 넓은 규칙보다 앞에 둡니다. 앞선 규칙이 모든 TCP 및 UDP 트래픽에 이미 일치하면 뒤에 있는 도메인 규칙이 올바르게 작성되어도 출구를 결정할 기회가 없습니다. 라우팅 문제를 확인할 때는 먼저 순서, 다음으로 조건, 마지막으로 데이터 파일에 항목이 있는지 살펴보세요.
같은 필드에 여러 후보를 넣으면 보통 그중 하나가 일치하면 됩니다. 예를 들어 domain 배열에 있는 도메인 조건 중 하나라도 충족하면 규칙이 일치합니다. 반면 한 규칙에 서로 다른 유형의 조건을 함께 작성하면 대개 모두 만족해야 합니다. 인바운드 태그, 도메인, 포트를 함께 지정하면 어느 하나만 일치해도 적용되는 것이 아니라 세 조건을 충족해야 한다는 뜻입니다. 서로 다른 요구사항을 한 규칙에 몰아넣으면 매칭 범위가 예상보다 좁아지기 쉽습니다. 독립적인 예외가 여러 개라면 규칙을 나누는 편이 검증하기 쉽고 어떤 규칙이 작동하는지도 확인하기 편합니다.
지역 데이터 없이 연습하는 규칙 예제
다음 규칙은 앞의 두 장에서 만든 직결 및 차단 아웃바운드와 함께 사용할 수 있습니다. 먼저 예시용 예약 도메인과 하위 도메인을 차단한 다음 SOCKS 인바운드에서 들어온 연결을 직결합니다. 나머지 트래픽은 기본 출구를 사용합니다. domain:은 도메인과 하위 도메인 매칭을, inboundTag는 인바운드 조건을 지정합니다. 이 예제는 실제 라우팅 목록을 권장하는 것이 아니라 규칙 참조와 순서를 설명하기 위한 것입니다. 테스트 대상을 명확히 지정하고 로그에서 라우팅 결과를 확인하세요. 웹페이지가 열리는지만 보고 어떤 규칙이 일치했는지 판단할 수는 없습니다.
{
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": [
"domain:example.org"
],
"outboundTag": "block"
},
{
"type": "field",
"inboundTag": [
"socks-local"
],
"outboundTag": "direct"
}
]
}
}
full:은 도메인 전체와 정확히 일치시킬 때, domain:은 지정 도메인과 하위 도메인에 매칭할 때 사용합니다. 정규식은 복잡한 조건이 꼭 필요할 때 적합합니다. 일반 텍스트는 생각보다 넓은 범위와 일치할 수 있으므로 의미가 명확한 형식을 우선 사용하세요. IP 규칙에는 주소나 CIDR 대역을 사용할 수 있지만 사설망, 루프백 주소, 링크 로컬 주소는 각각 의미가 다릅니다. 이를 모두 같은 ‘로컬 주소’로 취급하면 안 됩니다. 규칙의 대상 IP가 최초 DNS 확인에서 나온 하나의 주소와 반드시 같지도 않습니다. 도메인 연결은 DNS 확인 단계에 따라 매칭에 사용할 수 있는 정보가 달라집니다.
domainStrategy와 지리 데이터의 범위
AsIs는 라우팅을 위해 도메인을 IP로 변환하지 않고 현재 대상 형식을 기준으로 판단합니다. IPIfNonMatch는 도메인 규칙에 일치하지 않았을 때 IP로 변환해 추가 판단을 시도합니다. IPOnDemand는 라우팅 판단에 IP 정보가 필요할 때 확인을 시도합니다. 이 값들은 라우팅 단계의 이름 확인 방식을 제어합니다. 전역 DNS 스위치가 아니며, 각 아웃바운드에서 최종적으로 어떤 주소 계열을 사용할지도 정하지 않습니다. 값을 선택하기 전에 규칙이 도메인과 IP 중 무엇을 기준으로 하는지, IP 매칭을 위해 추가 DNS 확인을 허용할지 확인하세요.
geosite와 geoip는 데이터 파일을 참조하는 규칙이며, 커널이 분류를 자동으로 만들어 내는 것은 아닙니다. 파일이 없거나 디렉터리가 잘못됐거나 분류 이름이 존재하지 않으면 로딩에 실패하거나 예상과 다른 결과가 나올 수 있습니다. 데이터 내용도 바뀔 수 있으므로 분류를 영구적으로 정확한 서비스 경계로 간주해서는 안 됩니다. 중요한 대상은 설명하기 쉬운 명시적 규칙으로 지정하고, 해당 규칙을 분류 규칙보다 앞에 둘지 뒤에 둘지 분명히 하세요. 로컬 서비스는 시스템 라우팅과 방화벽도 고려해야 합니다. 커널의 도메인 규칙만으로 모든 네트워크 접근 문제를 해결하려 하지 마세요.
‘대상 하나, 예상 출구 하나, 로그 한 구간’을 기준으로 라우팅을 검증하세요. 먼저 관련 없는 규칙을 잠시 제거하고 대상이 도메인인지 IP인지 확인한 다음 데이터 분류와 복잡한 조건을 복원합니다. 전체 라우팅 사례는 V2Ray 라우팅 규칙 실전 가이드에서 확인할 수 있습니다. 기존 규칙을 가져오기 전에 태그 참조, 규칙 순서, 데이터 의존성이 현재 설정에 맞는지 확인하세요. 규칙 전체를 그대로 복사하면 원래 찾기 쉬웠던 문제를 더 많은 조건 속에 숨길 수 있습니다.
dns: DNS 확인 경로와 도메인 정보
누가 DNS 확인을 요청하는지 먼저 파악하세요
DNS 문제는 흔히 ‘도메인이 열리지 않는다’고 뭉뚱그려 설명하지만, 연결 하나에 애플리케이션 자체 DNS, 운영체제 DNS, 커널 내장 DNS, 원격 서버 측 DNS 확인이 관여할 수 있습니다. 이들이 같은 설정을 읽는다고 보장할 수 없습니다. 애플리케이션이 먼저 도메인을 IP로 변환한 뒤 IP를 SOCKS 인바운드에 전달하면 커널이 받는 입력은 도메인을 직접 받았을 때와 달라집니다. 최상위에 dns를 추가해도 시스템과 모든 애플리케이션이 해당 리졸버를 사용하지는 않습니다. 외부 DNS 서버로 향하는 요청을 모두 자동으로 가로채지도 않습니다.
내장 DNS는 일부 라우팅 판단이나 직결 아웃바운드의 주소 확인처럼 커널에서 DNS가 필요한 기능에 결과를 제공할 수 있습니다. 실제로 이를 호출하는지는 해당 모듈의 정책과 커널 구현에 따라 달라집니다. 문제를 추적할 때는 도메인을 처음 확인한 위치, 요청이 나가는 아웃바운드, 확인 결과를 전달받는 주체를 기록하세요. 호출 경로를 파악하지 않고 DNS 서버만 바꾸면 웹페이지가 간헐적으로 열릴 수는 있어도 다른 애플리케이션에서 계속 실패하는 이유를 알기 어렵고, 이후 변경으로 같은 문제가 다시 발생할 수도 있습니다.
기본 서버·정적 매핑·주소 계열
다음은 표준 JSON 조각입니다. 예시용 예약 도메인에 정적 매핑을 설정하고 DNS 서버 목록을 지정하며, 조회에는 IPv4 전략을 사용합니다. 이는 필드 구조를 보여 주는 예시이지 모든 네트워크에 권장하는 서버 목록이 아닙니다. 실제 네트워크에서 특정 DNS 전송 방식이 제한될 수 있고, 서버에 현재 경로로 접근하지 못할 수도 있습니다. 정적 매핑은 대상 주소를 확실히 알고 있는 경우에만 사용하세요. 서비스 주소가 자주 바뀌면 장기간 고정한 매핑으로 인해 오래된 주소에 연결하거나 인증서 오류가 발생하고 지역별 연결 조정이 무효화될 수 있습니다.
{
"dns": {
"hosts": {
"example.org": "93.184.215.14"
},
"servers": [
"1.1.1.1",
"8.8.8.8"
],
"queryStrategy": "UseIPv4"
}
}
queryStrategy는 조회 결과에 사용할 주소 계열을 지정합니다. 일반적인 값으로 UseIP, UseIPv4, UseIPv6가 있으며, 실제 지원 여부는 실행 중인 커널을 기준으로 확인해야 합니다. IPv4를 선택하면 일부 IPv6 경로 문제를 분리해 확인하는 데 도움이 될 수 있지만, 모든 시간 초과 문제를 해결하는 만능 방법은 아닙니다. 서비스에 특정 주소 유형의 레코드만 있으면 다른 주소 계열로 제한했을 때 사용할 결과를 얻지 못할 수 있습니다. 반대로 IPv6 주소를 받았다고 해서 로컬 IPv6 라우팅이나 해당 아웃바운드가 작동한다는 뜻도 아닙니다. DNS 조회 성공과 연결 성공은 별개의 단계입니다.
도메인별 DNS 지정과 순환 의존성
servers 배열에는 도메인 조건과 예상 IP 범위에 따라 조회 방식을 세분화하는 서버 객체를 넣을 수 있습니다. 여기서 도메인 조건은 DNS 서버를 선택하기 위한 것으로, routing.rules의 출구 선택과는 다릅니다. DNS 서버에 요청한 네트워크 연결이 어떻게 나가는지는 사용 전송 방식과 커널 구현에도 영향을 받습니다. 일부 로컬 모드와 일반 모드는 라우팅 동작이 다를 수 있습니다. 암호화 DNS 서비스를 설정하기 전에 현재 필드가 실제로 어떻게 동작하는지 확인하고 모든 DNS 요청이 프록시 출구를 자동으로 따른다고 가정하지 마세요.
특히 DNS 부트스트랩 과정에 순환 의존성이 생기지 않도록 주의하세요. 원격 서버 주소를 먼저 확인해야 하는데 DNS 서버에 접근하려면 아직 연결되지 않은 원격 서버가 필요한 상황이 생길 수 있습니다. 도메인으로 지정한 암호화 DNS 주소에서도 비슷한 문제가 발생할 수 있습니다. 부트스트랩 단계가 독립적으로 완료되는지 확인하고 원격 서버 도메인에서 주소를 얻는 방법을 명확히 한 뒤 복잡한 DNS 경로를 단계별로 추가하세요. 보안 확인을 끄거나 서버 주소를 임의로 고정해 순환 문제를 숨기지 마세요. 의존 경로를 분리하고 시스템 DNS, 커널 DNS, 아웃바운드 연결의 역할을 각각 점검하세요.
FakeDNS는 가상 주소와 도메인 매핑을 통해 이후 단계에서 도메인을 복원하는 방식이며, 일반적으로 인바운드의 트래픽 가로채기, DNS 처리 과정, 커널 기능이 함께 작동해야 합니다. 이름 하나를 추가하거나 예제 조각을 그대로 복사한다고 해서 일반 시스템 프록시가 모든 트래픽을 가로채는 것은 아닙니다. 관련 모드를 종료할 때는 애플리케이션이나 시스템 캐시에 가상 주소가 남아 있는지도 확인하세요. 자세한 적용 범위는 FakeDNS 원리와 사용 사례에서 살펴볼 수 있습니다. 일반적인 문제 해결은 단순한 DNS 경로부터 시작하고, 안정성을 확인한 뒤 이 기능이 필요한지 판단하세요.
policy, log, stats: 실행 정책
policy는 연결 동작을 제어하며 출구를 선택하지 않습니다
policy는 연결 핸드셰이크, 유휴 시간 제한, 반쪽 닫기 처리, 트래픽 통계 옵션 등을 설정할 때 사용합니다. 라우팅을 대신하지 않으며, 숫자 몇 개를 추가한다고 연결 품질이 자동으로 좋아지는 것도 아닙니다. levels의 키는 사용자 수준을 나타내며 프로토콜 사용자 객체의 수준 정보와 연결됩니다. 별도로 지정하지 않은 일반적인 경우에는 기본 수준을 사용합니다. 프로토콜마다 제공할 수 있는 사용자 정보가 다르므로 모든 인바운드에서 같은 방식으로 통계를 수집할 수 있다고 가정하면 안 됩니다. 값을 설정하기 전에 현재 연결이 어떤 수준에 해당하는지 확인하세요. 그렇지 않으면 실제로 사용되지 않는 정책만 수정할 수 있습니다.
다음 예제는 기본 수준에 일반적인 시간 제한을 명시적으로 설정합니다. handshake는 핸드셰이크 단계에 허용되는 시간이고, connIdle은 연결 유휴 시간에 적용됩니다. uplinkOnly와 downlinkOnly는 한쪽 방향이 종료된 뒤 다른 방향을 얼마나 더 열어 둘지 제어합니다. 단위는 초입니다. 이 예제는 구조를 설명하기 위한 것으로 기존 클라이언트 기본값을 모두 바꿔야 한다는 뜻은 아닙니다. 현재 정상 작동한다면 클라이언트에 맞게 조정된 기본 정책을 유지하는 편이 시간 제한을 무작정 줄이는 것보다 관리하기 쉽습니다.
{
"policy": {
"levels": {
"0": {
"handshake": 4,
"connIdle": 300,
"uplinkOnly": 2,
"downlinkOnly": 5
}
},
"system": {
"statsInboundUplink": false,
"statsInboundDownlink": false
}
},
"log": {
"loglevel": "warning"
}
}
핸드셰이크 시간을 너무 짧게 설정하면 네트워크 지연이나 여러 전송 계층의 연결 과정이 끝나기 전에 연결이 종료될 수 있습니다. 유휴 시간 제한이 너무 짧으면 장시간 연결, 푸시 대기, 간헐적인 전송에 영향을 줄 수 있고, 너무 길면 더 이상 필요하지 않은 연결이 오래 유지됩니다. 애플리케이션 자체의 하트비트나 재시도 동작도 실제 결과에 영향을 줍니다. 재현 가능한 문제를 기준으로 정책을 조정하고 변경 전후의 로그와 연결 단계를 기록하세요. 한 번 우연히 성공한 것을 설정 변경의 효과로 판단하지 말고, 시간 제한 값을 서비스 응답 속도의 측정값으로 간주하지 마세요.
로그 수준과 출력 위치
일반적인 loglevel 값에는 debug, info, warning, error, none이 있습니다. 디버그 수준은 더 많은 정보를 기록하지만 로그 용량과 개인정보 노출도 늘어납니다. 일상적인 실행에서 가장 상세한 로그를 계속 유지할 필요는 없습니다. 파일 경로를 지정하지 않으면 콘솔이나 클라이언트가 로그를 받을 수 있습니다. 접속 로그와 오류 로그 경로를 지정할 때는 실행 사용자에게 쓰기 권한이 있는지, 상대 경로가 어떤 작업 디렉터리를 기준으로 하는지 확인하세요. 파일에 새 내용이 없다고 연결이 없었다고 단정할 수는 없습니다. 이전 경로를 확인 중이거나 다른 로그 파일을 보고 있을 수도 있습니다.
접속 기록과 오류 기록은 용도가 다릅니다. 접속 기록은 요청 대상과 출구를 확인하는 데, 오류 기록은 DNS 확인·연결·핸드셰이크 중 어느 단계에서 실패했는지 파악하는 데 도움이 됩니다. 로그를 읽을 때는 먼저 같은 테스트의 시간 범위를 맞춘 뒤 인바운드 태그, 대상 주소, 오류 흐름을 확인하세요. 마지막에 시간 초과가 기록되어도 앞 단계의 DNS 확인 실패가 원인일 수 있으므로 마지막 한 줄만 떼어 보면 안 됩니다. 로그에는 도메인, 주소, 사용자 식별 정보, 로컬 경로가 포함될 수 있습니다. 다른 사람과 공유하기 전에 민감한 정보를 가리고 흐름을 판단하는 데 필요한 내용만 남기세요. 실행 로그 전체를 그대로 공개하지 마세요.
통계 옵션과 관리 인터페이스의 관계
최상위 stats와 policy의 통계 옵션은 서로 다른 단계를 담당합니다. 전자는 통계 모듈을 활성화하고, 후자는 어떤 항목의 데이터를 수집할지 결정합니다. 빈 stats 객체를 추가해도 접속 가능한 그래픽 대시보드가 자동으로 만들어지지 않습니다. 통계를 조회하려면 보통 관리 인터페이스, 서비스 선언, 인바운드 격리도 설정해야 합니다. 한 번 문제를 추적하려고 관리 인터페이스를 외부에 공개하는 방법은 권장하지 않으며, 통계 수치를 네트워크 성능의 확정적인 결론으로 보아서도 안 됩니다. 클라이언트에 트래픽 표시 기능이 있다면 경계를 확인하기 어려운 인터페이스를 새로 설정하기보다 기존 연동을 우선 사용하세요.
‘연결은 되지만 시간이 지나면 끊긴다’면 policy를 조정하기 전에 애플리케이션이 연결을 닫았는지, 원격에서 종료했는지, 유휴 정책이 작동했는지, 네트워크가 전환됐는지부터 구분하세요. 매번 핸드셰이크 단계에서 실패한다면 유휴 시간 매개변수를 바꿔도 근본 원인은 해결되지 않습니다. 자세한 로그 읽는 방법은 V2Ray 실행 로그 확인 방법을 참고하세요. 원인을 찾은 뒤에는 일상적으로 적절한 로그 수준으로 되돌리고 더 이상 필요하지 않은 디버그 파일을 정리하세요. 필요한 정책 변경 사항은 설정 백업 안내에 기록하세요.
클라이언트 설정과 커널 JSON의 범위
v2rayN: 인터페이스 설정과 파일 상태는 다를 수 있습니다
데스크톱에서는 v2rayN을 우선 사용하지만, 그래픽 클라이언트의 모든 설정이 하나의 JSON 파일에 저장되는 것은 아닙니다. 서버 목록, 구독 주소, 창 설정, 라우팅 템플릿, 커널 실행 설정이 각각 다른 곳에 저장될 수 있습니다. 시작을 누르면 클라이언트가 현재 선택 항목을 조합해 커널이 읽을 설정을 만듭니다. 중지 후 다시 시작하거나 서버를 바꾸거나 구독을 업데이트하면 결과가 다시 생성될 수 있습니다. 파일을 읽을 때는 장기간 유지되는 원본인지 임시로 생성된 결과물인지 먼저 확인하세요. 출처가 불분명한 파일을 유일한 백업으로 사용하거나 커널 실행 중에 편집하면서 적용 여부를 추측하지 마세요.
시스템 프록시는 운영체제와 애플리케이션 사이의 설정 약속이고, 커널 JSON은 프로세스의 리스닝과 전달 방식을 정의합니다. 일반적인 데스크톱 사용 흐름을 완성하려면 두 설정이 함께 작동해야 합니다. 시스템 프록시를 해제해도 커널이 반드시 중지되는 것은 아니며, 커널을 중지해도 시스템에 남은 프록시 설정이 바로 해제된다고 보장할 수 없습니다. 애플리케이션이 계속 꺼진 로컬 포트에 요청하면 전체 네트워크가 작동하지 않는 것처럼 보일 수 있습니다. 종료 전후에 시스템 프록시 상태와 프로세스 상태를 각각 확인하세요. 모든 연결 거부를 원격 서비스 문제로 돌리거나 클라이언트를 여러 개 겹쳐 실행해 남은 설정을 고치려 하지 마세요.
플랫폼 및 커널별 설정 차이
Windows, macOS, Linux에서 모두 v2rayN을 사용할 수 있지만 권한, 실행 디렉터리, 시스템 프록시 연동, 네트워크 가로채기 방식은 서로 다를 수 있습니다. 파일 경로 표기, 설정 디렉터리의 쓰기 권한, 서비스 실행 계정이 실제 설정 로딩에 영향을 줍니다. Android에서는 보통 v2rayNG를 사용하고 V2Fly 계열 설정에는 v2flyNG를 고려할 수 있습니다. 운영체제의 네트워크 가로채기 권한은 데스크톱 시스템 프록시와 같은 방식이 아닙니다. 플랫폼을 바꿀 때는 연결 정보를 보존한 뒤 대상 플랫폼에서 트래픽 가로채기 설정을 다시 확인하세요. 작업 디렉터리 전체를 복사해 모든 경로와 권한이 그대로 작동할 것이라고 기대하면 안 됩니다.
| 클라이언트 | 지원 플랫폼 | 설정 확인 시 중점 사항 |
|---|---|---|
| v2rayN | Windows / macOS / Linux | 실행 커널, 생성된 설정, 시스템 프록시 상태 |
| v2rayNG | Android | Xray 필드 지원, 시스템 권한, 애플리케이션 트래픽 가로채기 범위 |
| v2flyNG | Android | V2Fly 필드 지원 및 가져오기 형식 |
JSON이라도 설정 모델은 완전히 다를 수 있습니다. v2rayN은 여러 커널을 사용할 수 있지만, 이 문서의 inbounds, outbounds, routing 예제는 V2Fly / Xray의 일반적인 구조를 기준으로 작성했으며 sing-box 설정에 그대로 적용할 수 없습니다. 파일 확장자만 보고 호환성을 판단하지 마세요. 필드를 인식하지 못한다면 현재 실행 중인 커널부터 확인한 뒤 설정 입력 기능에서 전체 설정, 서버 객체, 클라이언트 전용 가져오기 형식 중 무엇을 요구하는지 살펴보세요. 잘못된 형식에 필드를 계속 덧붙이지 마세요.
TUN과 시스템 프록시는 불리언 하나로 같은 기능이 되지 않습니다
TUN은 보통 가상 네트워크 인터페이스, 라우팅 설정, 관련 권한이 필요하며 별도의 트래픽 가로채기 구성 요소나 다른 커널이 필요할 수 있습니다. 클라이언트에서 ‘TUN 사용’을 켠다고 이 문서의 기본 JSON 최상위에 같은 이름의 필드를 추가해 동일하게 작동하는 것은 아닙니다. 시스템 프록시는 적용 범위가 비교적 명확하지만 애플리케이션이 이를 사용해야 합니다. TUN은 더 넓은 트래픽을 가로챌 수 있지만 로컬 네트워크, DNS, 아웃바운드 루프백 문제도 처리해야 합니다. 모드를 전환할 때는 명확한 트래픽 가로채기 경로 하나만 활성화하고 원격 연결이 다시 인바운드로 되돌아가지 않는지 확인하세요.
사용자 지정 전체 설정과 일반 구독 사용도 별도로 관리해야 합니다. 전체 설정을 사용자 지정하면 인바운드, 아웃바운드, 규칙, 데이터 의존성을 직접 관리해야 하는 경우가 많습니다. 반면 구독은 클라이언트가 구독 정보와 인터페이스 설정을 바탕으로 설정을 생성합니다. 가져오기에 성공했다고 모든 필드가 적용된 것은 아닙니다. 클라이언트에서 설정 미리보기나 실행 로그를 제공한다면 실제로 불러온 결과를 기준으로 판단하세요. 병합 방식이 명시되지 않았다면 사용자 지정 조각이 올바른 위치를 자동으로 덮어쓴다고 가정하지 마세요. 서로 덮어쓰는 임시 파일을 여러 개 관리하기보다 복구 가능한 기본 설정을 보관하는 편이 안전합니다.
데스크톱 인터페이스를 선택할 때는 v2rayN 데스크톱 버전과 WPF 버전의 차이를 참고해 운영체제와 인터페이스 사용 습관에 따라 선택하세요. 인터페이스 프레임워크 차이를 프로토콜 기능 차이와 혼동하지 마세요. 설치 파일은 플랫폼에 맞게 다운로드 센터에서 선택하고 첫 설정은 사용 가이드를 따르세요. 인터페이스에서 실제 요구사항을 구현할 수 없다는 점을 확인한 뒤 사용자 지정 커널 파일을 도입하고, 구독 업데이트와 모드 전환, 재시작 후에도 설정이 유지되는지 확인하세요.
설정 검증·로그 추적·복구 절차
문법 검증과 실행 검증을 따로 진행하세요
설정 문제는 가장 간단한 확인부터 시작하세요. 첫째, 괄호와 쉼표, 문자열 이스케이프가 올바른 표준 JSON인지 확인합니다. 둘째, 현재 커널이 해당 필드를 지원하는지 확인합니다. 셋째, 태그 참조, 데이터 파일, 리스닝 포트, 경로 권한을 살펴봅니다. 마지막으로 실제 연결을 테스트합니다. 문법 검증을 통과했다는 것은 파일을 파싱할 수 있다는 뜻이지 원격에 접근할 수 있거나 라우팅 결과가 예상과 같다는 뜻은 아닙니다. 원격 출구가 없는 직결 설정도 문법적으로 유효할 수 있습니다. 따라서 ‘커널 실행 가능’과 ‘지정한 대상이 지정한 출구를 통해 접근 가능’을 별도의 검증 목표로 다뤄야 합니다.
커널을 수동으로 실행할 때는 장시간 리스닝을 시작하기 전에 설정 테스트 모드를 사용할 수 있습니다. 다음 명령은 로컬에 설치된 Xray 및 V2Ray 실행 파일을 대상으로 합니다. config.json은 실제로 확인할 설정 파일이어야 합니다. 적절한 작업 디렉터리에서 명령을 실행하거나 실행 파일 경로를 올바르게 지정하세요. 배포 방식에 따라 명령 옵션이 다를 수 있으므로 알 수 없는 옵션이 나오면 프로그램 자체 도움말을 확인하세요. 그래픽 클라이언트 사용자는 로그와 설정 검사 기능을 우선 활용하면 됩니다. 이 문서를 읽기 위해 별도의 백그라운드 프로세스를 설치할 필요는 없습니다.
xray run -test -config config.json
v2ray test -c config.json
설정 테스트를 통과한 뒤에는 충돌하는 리스닝 인스턴스를 먼저 종료하고 대상 설정을 실행하세요. 프록시 설정을 지원하는 애플리케이션 하나를 선택해 이번 확인에 필요한 인바운드만 지정하고 요청 한 번을 보낸 뒤 시간을 기록합니다. 첫 장의 직결 기본 설정을 사용한다면 검증 대상은 로컬 인바운드이지 원격 프록시가 아닙니다. 다음으로 매개변수를 확인한 원격 아웃바운드를 추가하고 마지막으로 라우팅과 DNS를 복원하세요. 단계마다 주요 변수를 하나씩만 늘리면 실패해도 방금 추가한 부분을 집중적으로 확인할 수 있어 인바운드, DNS, 원격 연결을 동시에 추측하지 않아도 됩니다.
증상에 맞는 설정 계층부터 확인하세요
커널이 시작되지 않으면 파싱 오류, 지원하지 않는 필드, 포트 충돌, 데이터 파일 로딩을 먼저 확인하세요. 프로그램이 로컬 연결을 거부하면 리스닝 주소와 포트, 프로세스 상태를 확인합니다. 커널이 요청을 받았지만 도메인 확인 오류가 발생하면 DNS 호출 경로를 살펴보세요. 원격 핸드셰이크에 실패하면 주소, 시스템 시간, 프로토콜 인증 정보, 전송 및 보안 설정을 점검합니다. 시간 초과가 발생했다고 바로 특정 계층의 오류로 단정하지 말고 로그를 거슬러 올라가 마지막으로 성공한 단계와 처음으로 명확하게 실패한 지점을 찾으세요.
| 증상 | 먼저 확인 | 다음으로 확인할 증거 |
|---|---|---|
| 프로세스가 시작 직후 종료됨 | JSON 문법, 필드 지원 여부, 파일 경로 | 시작 오류에 표시된 구체적인 필드 또는 파일명 |
| 로컬 연결이 거부됨 | 프로세스, 리스닝 주소, 포트 | 해당 인바운드가 실제로 리스닝 중인지 |
| DNS 확인 오류 발생 | DNS 서버와 부트스트랩 의존성 | 도메인이 어느 계층에서 확인되는지 |
| 라우팅 결과가 예상과 다름 | 규칙 순서, 대상 형식, 태그 | 요청에서 선택된 아웃바운드 기록 |
테스트할 때는 애플리케이션 캐시가 결과를 왜곡하지 않도록 주의하세요. 기존 연결이 이전 채널을 재사용하거나 도메인 캐시에 이전 결과가 남을 수 있으며, 실행 중인 애플리케이션은 시스템 프록시 변경을 바로 적용하지 않을 수 있습니다. 필요하면 관련 연결을 닫거나 테스트 애플리케이션을 재시작한 뒤 같은 요청을 다시 보내세요. 단, 모든 설정을 동시에 초기화하면 원래 문제와 비교할 수 없게 됩니다. 네트워크를 전환하면 접근 가능 여부와 DNS 경로도 달라질 수 있으므로 테스트에 사용한 네트워크 환경을 기록하세요. 같은 조건에서 반복되는 결과만 설정 변경의 실제 효과를 판단하는 근거로 삼을 수 있습니다.
패치를 쌓지 말고 복구 지점을 남기세요
각 단계가 정상 작동하는 것을 확인할 때마다 설정과 간단한 설명을 함께 저장하세요. 실행 커널, 인바운드 포트, 기본 아웃바운드, 의존 파일을 기록합니다. 백업에 구독 주소나 계정 정보가 포함되어 있다면 민감 정보로 관리하고 공개 페이지나 공유 기록에 올리지 마세요. 새 문제가 생기면 가장 최근 복구 지점으로 돌아간 뒤 변경 사항을 하나씩 다시 적용하세요. 실패한 설정에 예외 규칙과 시간 제한을 계속 덧붙이지 마세요. 정상 상태로 복구한 뒤에는 효과가 없다고 확인된 패치를 제거해 임시 시도가 필수 설정으로 오해되지 않도록 하세요.
마지막으로 설정이 유지되는지 확인하세요. 클라이언트를 중지한 뒤 다시 시작하고, 구독 업데이트나 모드 전환으로 필요한 설정이 덮어쓰이지 않았는지 확인한 다음 같은 대상으로 다시 테스트합니다. 디버깅이 끝나면 적절한 로그 수준으로 되돌리고 임시로 넓힌 리스닝 범위를 원래대로 복구하며 사용하지 않는 시스템 프록시 설정을 정리하세요. 문제가 계속되면 민감한 정보를 제거한 오류 내용과 최소 재현 절차를 준비해 문제 해결을 참고하세요. 기본 절차를 다시 진행하려는 경우에는 사용 가이드로 돌아가면 됩니다. 시스템 설정 참고 자료의 선택 항목을 모두 필수 단계로 취급하지 마세요.