구독을 가져왔지만 설정 파일을 읽기 어려운 분을 위한 안내입니다. 로컬 인바운드, 직접 연결, 차단만 포함한 전체 예제로 요청 흐름을 살펴본 뒤 포트, 아웃바운드 태그, 규칙 순서, DNS의 적용 범위를 설명합니다. 예제에는 원격 프록시 서버가 없으므로 구독을 대체하지 않습니다. 글을 읽고 클라이언트 설정을 바꿔야 할지, 코어 설정을 확인해야 할지 판단해 보세요.
1. config.json의 주요 섹션 다섯 가지
config.json은 코어가 읽는 설정 파일이지, 구독 링크나 클라이언트의 전체 설정이 아닙니다. v2rayN은 노드, 구독 그룹, 인터페이스 옵션을 관리하고 현재 선택 항목을 코어 실행에 필요한 설정으로 변환합니다. 파일명이 같더라도 V2Ray와 Xray의 모든 필드를 서로 바꿔 쓸 수 있는 것은 아닙니다.
파일을 위에서 아래로 읽을 필요는 없습니다. 먼저 inbounds에서 요청이 들어오는 곳을 확인하고, routing에서 연결 경로를 결정하는 방식을 살펴본 다음, outbounds에서 실제 출구를 찾으세요. log는 문제 해결에 도움을 주고, dns는 코어가 필요할 때 사용하는 도메인 해석 설정을 제공합니다.
| 최상위 필드 | 주요 역할 | 우선 확인할 항목 |
|---|---|---|
log | 로그 수준과 출력 위치 설정 | 현재 로그 수준에서 오류가 기록되는지 |
inbounds | 브라우저 등 앱의 연결 수신 | 수신 주소, 포트, 인바운드 프로토콜 |
outbounds | 직접 연결·차단·원격 프록시 아웃바운드 정의 | 프로토콜, 태그, 서버 매개변수 |
routing | 규칙에 따라 연결을 특정 아웃바운드로 전달 | 규칙 순서와 대상 태그 |
dns | 내장 DNS 리졸버 설정 | 리졸버 주소와 실제 호출 조건 |
2. 전체 예제: 로컬 인바운드, 직접 연결, 도메인 차단
아래 예제는 V2Ray와 Xray에서 흔히 볼 수 있는 기존 JSON 필드를 사용해 구조를 이해하기 쉽게 구성했습니다. 로컬에서만 접속할 수 있는 인바운드 두 개를 제공합니다. SOCKS 포트는 10808, HTTP 포트는 10809입니다. example.org와 하위 도메인으로 향하는 연결은 차단하고, 두 인바운드로 들어온 나머지 연결은 직접 연결합니다.
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "local-socks",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": false
}
},
{
"tag": "local-http",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": [
"domain:example.org"
],
"outboundTag": "block"
},
{
"type": "field",
"inboundTag": [
"local-socks",
"local-http"
],
"outboundTag": "direct"
}
]
},
"dns": {
"servers": [
"1.1.1.1"
]
}
}
포트는 이 예제에서 명시한 값이며 모든 클라이언트 버전의 기본값은 아닙니다. JSON에서 객체는 중괄호, 배열은 대괄호를 사용합니다. 키와 문자열은 영문 큰따옴표로 감싸고 마지막 항목 뒤에는 쉼표를 붙이지 않습니다. 여러 코어에서 읽기 쉽도록 이 예제에는 주석 문법을 사용하지 않았습니다.
3. inbounds: 수신 주소, 포트, 인바운드 프로토콜
inbounds는 배열이므로 하나의 코어에서 여러 로컬 인바운드를 제공할 수 있습니다. listen은 수신할 네트워크 인터페이스를, port는 앱이 연결할 포트를, protocol은 앱에서 사용할 프록시 프로토콜을 지정합니다. 세 항목을 함께 확인해야 하며 포트 번호만 기억해서는 안 됩니다.
로컬 SOCKS 인바운드
- tag
local-socks- listen
127.0.0.1- port
10808- protocol
socks- udp
false
앱에서 SOCKS 프록시를 선택해야 합니다. 이 예제는 SOCKS UDP 전달을 지원하지 않습니다.
로컬 HTTP 인바운드
- tag
local-http- listen
127.0.0.1- port
10809- protocol
http- settings
{}, 기본 설정 사용
앱에서 HTTP 프록시를 선택해야 합니다. HTTPS 대상은 일반적으로 CONNECT를 통해 터널을 설정합니다.
127.0.0.1은 이 기기에서만 접속할 수 있습니다. 이를 0.0.0.0으로 바꾸면 모든 IPv4 인터페이스에서 수신하므로 같은 네트워크의 다른 기기에서도 인바운드에 접속할 수 있습니다. 예제의 SOCKS 인바운드는 noauth를 사용하므로 문제 해결을 위해 수신 범위부터 넓히지 마세요.
- 앱이 인바운드에 연결되지 않음: 앱에서 선택한 프록시 유형과 포트를 확인하세요. HTTP 프록시에는 SOCKS 포트를 입력하면 안 됩니다.
- 코어에서 포트가 사용 중이라고 표시됨: 클라이언트가 두 개 실행 중인지, 이전 코어 프로세스가 종료되지 않았는지 확인하세요.
- 브라우저 트래픽이 프록시를 거치지 않음: 시스템 프록시 또는 브라우저 자체의 프록시 설정이 켜져 있는지 확인하세요. 코어를 실행해도 모든 앱의 네트워크 경로가 자동으로 바뀌지는 않습니다.
v2rayN에서는 「설정」→「매개변수 설정」에서 로컬 수신 포트 관련 옵션을 찾을 수 있습니다. 그런 다음 메인 창의 「시스템 프록시」 메뉴에서 「시스템 프록시 자동 설정」을 선택하세요. 버전에 따라 메뉴 위치가 다를 수 있으므로 현재 화면에 표시된 이름과 실제 포트를 기준으로 확인하세요.
4. outbounds: 아웃바운드 프로토콜과 tag의 관계
outbounds도 배열이지만, 코어에서 요청이 나가는 방식을 설명합니다. 예제에서 freedom은 대상에 직접 연결하고 blackhole은 연결을 차단합니다. direct와 block은 사용자가 지정한 태그일 뿐 프로토콜 이름이 아닙니다.
| 필드 또는 프로토콜 | 예제에서의 역할 | 수정 시 유의사항 |
|---|---|---|
tag | 라우팅 규칙에서 아웃바운드를 참조 | 이름을 바꾸면 모든 참조도 함께 수정하고 대소문자를 확인 |
freedom | 대상 주소에 직접 연결 | 원격 프록시가 아니며 프록시 서버를 제공하지 않음 |
blackhole | 일치하는 연결을 종료 | 대체 출구가 아니며 노드를 자동 전환하지 않음 |
settings | 현재 프로토콜에 필요한 매개변수 지정 | 프로토콜마다 설정 내용이 달라 그대로 옮겨 쓸 수 없음 |
실제 프록시 아웃바운드에는 서버 주소와 포트, 사용자 식별 정보, 서버와 일치하는 전송 및 보안 설정도 필요합니다. VMess와 VLESS의 사용자 매개변수는 서로 다르며, TLS·REALITY·WebSocket 등의 설정도 각각 위치와 적용 조건이 다릅니다. "protocol": "freedom"을 "vless"로 바꾸는 것만으로 설정이 완료되지는 않습니다.
정리: 먼저 태그를 확인한 다음 서버 매개변수를 점검하세요
라우팅이 proxy를 가리키면 먼저 아웃바운드 배열에 "tag": "proxy"가 실제로 있는지 확인하세요. 태그 참조가 맞는지 확인한 뒤 노드 매개변수를 살펴보세요. 그렇지 않으면 서버 정보가 완전해도 요청이 의도한 아웃바운드로 전달되지 않습니다.
규칙에 일치하지 않는 연결은 일반적으로 아웃바운드 배열의 첫 번째 항목을 사용합니다. 이것이 자동 장애 조치 기능을 뜻하지는 않습니다. 예제에서는 direct를 첫 번째에 두고 두 번째 규칙으로 두 로컬 인바운드의 연결을 명시적으로 처리해 매칭 결과를 쉽게 확인할 수 있게 했습니다.
5. routing: 규칙 순서와 도메인 매칭
일반적인 field 규칙은 배열 순서대로 확인합니다. 규칙이 일치하면 해당 출구를 선택하고, 이후 규칙 중 더 정확한 조건을 찾지 않습니다. 예제에서는 지정 도메인을 먼저 차단하고 두 인바운드의 나머지 연결은 직접 연결합니다. 두 규칙의 순서를 바꾸면 인바운드 규칙이 먼저 일치해 도메인 차단이 적용되지 않습니다.
- 대상 주소 수신: 앱이 도메인이나 IP 주소를 인바운드로 전달하면 코어가 이를 바탕으로 라우팅을 판단합니다.
- 첫 번째 규칙 확인:
domain:example.org는 해당 도메인과 하위 도메인에 일치하며, 일치하면block을 선택합니다. - 두 번째 규칙 확인: 첫 번째 규칙에 일치하지 않으면
local-socks또는local-http에서 들어온 연결은direct를 선택합니다. - 규칙에 일치하지 않은 연결 처리: 다른 인바운드가 있고 일치하는 규칙이 없다면 기본 아웃바운드 동작을 따릅니다.
하나의 규칙에 있는 서로 다른 조건은 일반적으로 모두 충족해야 합니다. 같은 조건 배열에 여러 값을 지정하면 대개 그중 하나와 일치하면 됩니다. 예를 들어 한 규칙에 inboundTag와 domain을 함께 쓰면 “이 인바운드에서 들어오고 대상 도메인도 일치”해야 한다는 뜻이지, 두 조건 중 하나만 맞으면 된다는 뜻이 아닙니다.
| 표기 | 매칭 의미 | 읽을 때 참고 |
|---|---|---|
domain:example.org | 도메인과 해당 하위 도메인 | 도메인 전체 범위를 기준으로 분류할 때 적합 |
full:example.org | 이 도메인 전체와 정확히 일치 | 모든 하위 도메인을 포함하지 않음 |
inboundTag | 연결이 들어올 때의 인바운드 태그와 일치 | 서버 이름이나 구독 그룹 이름이 아님 |
outboundTag | 일치한 연결에 적용할 아웃바운드 태그 지정 | 실제로 존재하는 아웃바운드와 일치해야 함 |
예제에는 트래픽 스니핑이 설정되어 있지 않습니다. 앱이 도메인을 IP로 변환한 다음 IP만 코어에 전달하면 도메인 규칙이 일치하지 않을 수 있습니다. 이 경우 차단 규칙을 무작정 확대하기보다 앱이 도메인을 프록시에 전달하는지 먼저 확인하세요. 도메인 라우팅은 URL 경로를 매칭하는 기능도 아닙니다. 예를 들어 /account는 여기서 사용하는 도메인 조건에 해당하지 않습니다.
6. dns: 리졸버 설정이 시스템 전체 DNS를 제어하는 것은 아닙니다
dns.servers는 내장 DNS에서 사용할 서버를 지정하며, 예제의 1.1.1.1은 명시된 리졸버 주소입니다. 이 주소를 설정해도 시스템 DNS가 변경되는 것은 아니며 브라우저 자체의 암호화 DNS가 이 리졸버를 통과한다는 뜻도 아닙니다. 내장 DNS를 호출하는지는 라우팅 정책과 아웃바운드 설정, 실제 요청 유형에 따라 달라집니다.
AsIs: 라우팅 단계에서 기존 대상 정보를 사용하며 IP 규칙을 위해 도메인을 먼저 해석하지 않습니다. 예제에서는 도메인 규칙을 쉽게 살펴보도록 이 값을 사용합니다.IPIfNonMatch: 도메인 규칙이 일치하지 않으면 대상 도메인을 해석한 뒤 IP 규칙을 추가로 확인할 수 있습니다.IPOnDemand: 매칭 중 IP가 필요한 규칙을 만나면 도메인 해석을 시작할 수 있습니다.
이 값들은 routing.domainStrategy에 해당합니다. 특정 아웃바운드의 domainStrategy와 혼동하지 마세요. 라우팅은 “어느 출구를 사용할지” 결정하고, 아웃바운드의 해석 전략은 “대상에 어떻게 연결할지”에 영향을 줍니다. 이름은 비슷하지만 적용 단계가 다릅니다.
설정에 geoip: 또는 geosite: 조건이 있으면 실행 환경에 해당 데이터 리소스가 있는지도 확인해야 합니다. 이 예제에서는 데이터 파일 누락과 JSON 구조 문제를 혼동하지 않도록 해당 조건을 사용하지 않았습니다.
7. log와 안전한 설정 변경: 한 번에 하나씩 수정
예제의 loglevel은 warning입니다. 경고와 오류를 확인하기에 적합하지만 연결별 라우팅 세부 정보까지 표시하지 않을 수 있습니다. 문제를 찾을 때는 일시적으로 info를 사용할 수 있으며, 더 자세한 진단에는 debug를 짧은 시간 동안 활용하세요. 로그에 대상 도메인과 주소가 포함될 수 있으므로 다른 사람에게 전달하기 전에 민감한 내용을 삭제하세요.
- 설정 출처 확인: 먼저 클라이언트가 생성한 실행 파일인지, 별도로 관리하는 사용자 지정 설정인지 확인하세요. 설치 폴더에서 이름이 비슷한 파일을 임의로 수정하지 마세요.
- 현재 상태 기록: 선택된 노드, 시스템 프록시 상태, 수신 포트를 기록하고 원본 설정 사본을 보관해 쉽게 되돌릴 수 있도록 하세요.
- 먼저 그래픽 설정에서 변경: 로컬 포트는 v2rayN의 「설정」→「매개변수 설정」에서 조정하고, 분할 라우팅 규칙은 「설정」→「라우팅 설정」에서 확인하세요. 항목 이름은 사용 중인 버전을 기준으로 확인하세요.
- 한 번에 한 항목씩 수정: 먼저 포트를 바꾸고 인바운드를 확인한 다음 규칙 순서를 조정하세요. DNS, 전송 매개변수, 아웃바운드 태그를 한꺼번에 바꾸지 마세요.
- 다시 불러온 뒤 첫 오류 확인: 네트워크 접속 여부를 판단하기 전에 JSON 구문, 포트 수신, 태그 참조 오류부터 해결하세요.
- 평소 로그 수준으로 복원: 문제 해결이 끝나면 적절한 로그 수준으로 되돌려 상세 연결 기록이 계속 쌓이지 않도록 하세요.
정리: 클라이언트가 생성한 파일은 설정 출처에서 수정하세요
직접 수정한 config.json이 노드를 전환한 뒤 원래대로 돌아온다면 해당 설정을 관리하는 클라이언트 메뉴에서 먼저 수정하세요. 사용자 지정 설정을 사용 중이고 로드 방식을 알고 있는 경우에만 전체 JSON 파일을 직접 관리하세요.
v2rayN은 데스크톱 클라이언트입니다. Android용 v2rayNG는 Xray 코어를, v2flyNG는 V2Fly 코어를 사용합니다. 가져오기 방식과 지원 필드는 클라이언트마다 다를 수 있습니다. 구독을 가져올 수 있다는 것은 클라이언트가 내용을 파싱했다는 뜻일 뿐, 모든 프로토콜 조합이 현재 실행 중인 코어에 적합하다는 뜻은 아닙니다.
8. 설정 오류와 웹 페이지 접속 불가 문제 해결 순서
문제를 “설정이 로드되는가”, “앱이 프록시를 사용하는가”, “라우팅이 올바른가”, “출구에 연결되는가”의 네 단계로 나누면 구독을 반복해서 가져오는 것보다 효과적으로 원인을 찾을 수 있습니다. 아래 증상은 범위를 좁히기 위한 참고 사항이며, 로그 한 줄만으로 서버 장애라고 단정해서는 안 됩니다.
| 증상 | 먼저 확인할 항목 | 다음 조치 |
|---|---|---|
| 코어가 시작하자마자 종료됨 | 괄호, 쉼표, 필드 유형, 처음 발생한 시작 오류 | 마지막 변경을 되돌리고 변경 전후 설정을 비교 |
| 주소가 이미 사용 중이라는 알림 | 10808, 10809 포트를 다른 프로세스가 사용 중인지 확인 | 중복 실행을 종료하거나 클라이언트에서 포트를 변경한 뒤 앱 설정도 함께 수정 |
| 대상 아웃바운드를 찾을 수 없음 | outboundTag와 아웃바운드의 tag가 완전히 일치하는지 확인 | 대소문자와 철자 차이를 확인해 참조를 수정 |
| 도메인 차단이 적용되지 않음 | 규칙 순서, 인바운드 태그, 대상이 여전히 도메인인지 확인 | 먼저 매칭 조건을 확인하고 전체 차단으로 바꾸지 않기 |
| 설정은 로드되지만 웹 페이지가 시간 초과됨 | 앱의 프록시 유형, 현재 아웃바운드, 대상 해석, 연결 오류 | 인바운드와 아웃바운드를 나눠 테스트해 직접 연결 실패와 원격 프록시 실패를 구분 |
마지막으로 세 가지 차이를 기억하세요. 인바운드 포트는 원격 서버 포트와 다르고, 아웃바운드 태그는 프로토콜 이름과 다르며, DNS 설정은 시스템 전체 트래픽을 제어하는 설정이 아닙니다. 이 세 가지를 구분한 뒤 실제 노드 설정을 살펴보면 복잡한 전송 매개변수도 올바른 위치에 놓기 쉬워집니다.