핵심 내용

설정 파일은 먼저 트래픽 흐름을 파악한 다음 세부 항목을 살펴보세요. 이 글에서는 로컬 직결 예시를 통해 인바운드, 아웃바운드, 라우팅, 로그를 함께 설명합니다. 노드를 가져온 뒤 포트 충돌이나 분기 오류를 확인하려는 사용자에게 적합합니다. 예시에는 원격 프록시 노드가 포함되지 않습니다. 읽고 나면 클라이언트에 저장된 노드 정보와 코어 실행 설정을 구분하고, 수정 결과를 순서대로 확인할 수 있습니다.

1. V2Ray 설정 구조: 클라이언트와 코어 구분하기

핵심부터 살펴보면 inbounds는 요청을 받을 위치를, outbounds는 다음 연결을 설정하는 방법을, routing은 요청을 전달할 아웃바운드를 결정합니다. 세 항목은 별개의 스위치가 아니라 하나의 처리 과정에서 이어지는 단계입니다.

앱 요청 로컬 인바운드 라우팅 규칙 확인 아웃바운드 연결 대상 서비스

v2rayN은 노드 저장, 구독 관리, 실행 설정 생성, 선택한 코어 실행을 담당하는 데스크톱 클라이언트입니다. Android용 v2rayNG는 Xray 코어를, v2flyNG는 V2Fly 코어를 사용합니다. 이름이 비슷한 클라이언트라도 지원하는 설정 항목이 완전히 같지는 않습니다. 문제를 확인하기 전에 로그나 정보 화면에서 실제로 실행 중인 코어와 버전을 확인하세요.

이 글에서는 일반적으로 쓰이는 기존 JSON 설정 구조를 다룹니다. V2Ray와 Xray는 이 구조의 일부를 공유하지만, 지원 기능은 각 버전에 따라 다릅니다. 예를 들어 Xray 예시에 REALITY나 xtls-rprx-vision이 있다고 해서 V2Fly 설정에 그대로 적용할 수는 없습니다. 공유 링크나 구독 정보도 완전한 실행 설정이 아닐 수 있으므로, 주소를 JSON 파일에 붙여 넣어 코어에서 실행하면 안 됩니다.

2. inbounds 인바운드: 주소·포트·프로토콜의 역할

인바운드는 코어가 트래픽을 받는 입구이지 원격 서버가 아닙니다. 브라우저가 로컬 SOCKS 포트에 연결하면 요청은 먼저 인바운드에 도착한 뒤 코어가 아웃바운드를 선택합니다. 아래 예시에서는 SOCKS 수신 포트를 10808, HTTP 수신 포트를 10809로 설정합니다. 이 값은 예시일 뿐 모든 클라이언트의 기본값은 아닙니다.

127.0.0.1
예시 루프백 주소
10808
예시 SOCKS 포트
10809
예시 HTTP 포트

SOCKS 인바운드

listen
127.0.0.1
port
10808
protocol
socks
tag
socks-in

앱에서 SOCKS5를 선택하고 동일한 주소와 포트를 입력하세요.

HTTP 인바운드

listen
127.0.0.1
port
10809
protocol
http
tag
http-in

HTTP 프록시는 CONNECT를 통해 HTTPS 연결도 전달할 수 있습니다. HTTP 웹사이트만 이용할 수 있는 것은 아닙니다.

listen은 수신 주소입니다. 127.0.0.1은 이 기기에서 오는 연결만 받습니다. 이를 0.0.0.0으로 바꾸면 모든 IPv4 네트워크 인터페이스에서 연결을 받으므로 같은 네트워크의 다른 기기도 프록시 입구에 접근할 수 있습니다. 이 기기에서만 사용할 설정이라면 문제 해결을 위해 수신 범위를 함부로 넓히지 마세요.

3. outbounds 아웃바운드: 노드 설정과 기본 출구

아웃바운드는 코어가 외부로 연결하는 방법을 지정합니다. 원격 프록시에 연결하려면 보통 서버 주소와 포트, 사용자 인증 정보, 전송 및 보안 설정이 필요합니다. 직결 아웃바운드는 대상 서비스에 직접 연결합니다. 이 글에서 다루는 기존 설정 구조에서는 규칙에 일치하는 항목이 없을 때 outbounds 배열의 첫 번째 항목을 기본으로 사용합니다. 따라서 배열 순서도 실제 트래픽 경로에 영향을 줍니다.

항목 또는 프로토콜기능확인할 점
tag라우팅 규칙에서 해당 아웃바운드를 참조outboundTag와 철자까지 일치
freedom대상 주소에 직접 연결직결을 의미하며 원격 프록시가 아님
blackhole전달된 트래픽을 폐기규칙이 의도치 않게 적용되는지 확인
settings해당 프로토콜의 설정 저장아웃바운드 프로토콜에 따라 구조가 달라짐
streamSettings전송 방식과 전송 보안 설정서버 설정과 일치해야 함

VMess, VLESS, Trojan, Shadowsocks는 동일한 settings 구조를 공유하지 않습니다. '포트'라고 불리는 항목도 로컬 수신 포트와 원격 서버 포트를 구분해야 합니다. 로컬 포트는 앱이 이 기기에 연결하는 방법을, 원격 포트는 코어가 서버에 연결하는 방법을 결정합니다. 하나를 바꿔도 다른 쪽 문제가 자동으로 해결되지는 않습니다.

VMess를 예로 들면 사용자 정보는 프로토콜에서 정한 사용자 배열에 있고, TLS는 전송 보안 설정에 해당합니다. WebSocket 경로, TLS 서버 이름, 원격 주소도 서로 다를 수 있습니다. 구독을 가져온 뒤 연결되지 않으면 모든 항목을 서버 주소로 바꾸지 말고 서비스 제공자가 안내한 값을 하나씩 대조하세요.

요약: 기본 아웃바운드를 먼저 확인한 뒤 분기 규칙을 살펴보세요

규칙에 일치하지 않은 요청이 모두 직결된다면 배열의 첫 항목이 freedom인지 확인하세요. 규칙에 지정된 프록시 태그만 바꾸고 기본 출구가 여전히 직결인 상황을 놓치지 마세요.

4. routing 라우팅: 규칙 순서와 도메인 확인 시점

라우팅은 '더 정확해 보이는' 규칙을 자동으로 선택하지 않습니다. 설정된 순서대로 확인하며, 처음 일치하는 규칙이 출구를 결정합니다. 범위가 넓은 규칙을 앞에 두면 뒤에 있는 세부 규칙이 적용될 기회가 없을 수 있습니다. 한 규칙에 인바운드, 도메인, 포트 등 여러 조건을 함께 지정하면 일반적으로 모든 조건이 충족되어야 합니다.

{
  "domainStrategy": "AsIs",
  "rules": [
    {
      "type": "field",
      "domain": ["full:example.invalid"],
      "outboundTag": "block"
    },
    {
      "type": "field",
      "inboundTag": ["socks-in", "http-in"],
      "outboundTag": "direct"
    }
  ]
}

이 규칙은 먼저 example.invalid과 정확히 일치하는 도메인을 block으로 전달한 다음, 두 로컬 입구에서 들어온 나머지 요청을 direct로 전달합니다. 이 도메인은 일치 규칙을 설명하기 위한 예시이며 실제 원격 서비스 주소가 아닙니다. full:은 도메인 전체가 정확히 일치해야 하며, domain:은 지정한 도메인과 하위 도메인까지 일치할 수 있습니다. 두 접두어의 의미를 혼동하지 마세요.

도메인 규칙의 적용 여부는 인바운드가 어떤 정보를 받았는지에 따라서도 달라집니다. 앱이 대상을 먼저 IP 주소로 변환한 다음 IP만 프록시에 전달하면 코어가 원래 도메인을 모를 수 있습니다. 스니핑은 일부 프로토콜 트래픽에서 도메인 정보를 추출할 수 있지만 모든 요청에 통하는 해결책은 아니며, DNS 분기 설정을 대신하지도 않습니다.

5. 전체 JSON 예시: 인바운드 2개, 직결, 차단

아래는 전체 구조를 보여 주는 기존 형식의 예시이며 원격 프록시 기능은 제공하지 않습니다. 로컬의 두 포트에서 수신하고 기본적으로 직결하며, 예시 도메인 하나를 차단합니다. 클라이언트가 이미 해당 포트를 사용 중이면 관련 프로세스를 먼저 중지하거나 비어 있는 포트로 바꾸세요. 그래야 포트 충돌을 설정 문법 오류로 오해하지 않습니다.

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "socks-in",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    },
    {
      "tag": "http-in",
      "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": ["full:example.invalid"],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "inboundTag": ["socks-in", "http-in"],
        "outboundTag": "direct"
      }
    ]
  }
}

설정 안의 참조 항목을 역으로 따라가며 살펴볼 수 있습니다. outboundTag: "block"을 발견하면 아웃바운드 배열에서 tag: "block"을 찾고, inboundTag를 발견하면 인바운드 배열로 돌아가 이름을 확인하세요. 태그를 설정 안의 연결선이라고 생각하면 각 항목을 외우는 것보다 문제를 찾기 쉽습니다.

  1. 일반 텍스트 편집기에서 config.json으로 저장하고, 서식 있는 텍스트로 저장되지 않았는지 확인하세요.
  2. 객체의 키와 문자열은 영문 큰따옴표로 묶고, 포트 번호는 단위가 포함된 문자열이 아닌 숫자로 입력하세요.
  3. 배열이나 객체의 마지막 항목 뒤에는 쉼표를 붙이지 마세요. 예시는 표준 JSON 형식에 맞춰 작성했으며 주석은 포함하지 않습니다.
  4. 먼저 코어 설정을 테스트한 뒤 수신을 시작하세요. 문법 검사를 통과했다는 것은 설정이 받아들여졌다는 의미일 뿐, 원격 서비스에 연결된다는 뜻은 아닙니다.

6. 로그와 클라이언트 화면: 증상으로 설정 문제 찾기

log는 로그 출력을 설정합니다. 일반적인 loglevel 값에는 debug, info, warning, error, none이 있습니다. 평소에는 warning을 사용하고, 문제를 확인할 때는 잠시 info나 debug로 높이세요. 확인을 마친 뒤 원래대로 되돌려 접속 정보가 계속 쌓이지 않게 하세요.

설정 항목화면에서 확인할 위치확인할 내용
inboundsv2rayN의 '설정' → '매개변수 설정'에서 로컬 수신과 관련된 항목포트, 수신 범위, 인바운드 프로토콜
outbounds노드 목록에서 현재 노드 편집원격 주소, 포트, 사용자 정보, 전송 및 보안 설정
routing현재 라우팅 구성과 규칙 편집 화면규칙 순서, 대상 출구, 구성 활성화 여부
log로그 수준 설정과 실행 로그 영역시작 실패 메시지와 발생 시간

클라이언트 버전에 따라 메뉴 이름이 달라질 수 있습니다. 표는 개념을 대응해 보여 주며 모든 버전에서 메뉴 단계가 동일하다는 뜻은 아닙니다. Android에서는 VPN 연결과 로컬 프록시 수신도 구분해야 합니다. v2rayNG와 v2flyNG는 시스템 VPN 기능으로 트래픽을 받을 수 있으므로 데스크톱의 시스템 프록시 설정을 기준으로 그대로 판단하면 안 됩니다.

데스크톱에서 시스템 프록시를 켜면 시스템 프록시 설정을 따르는 앱에 지정된 입구를 사용하도록 알릴 뿐, 모든 앱의 트래픽이 코어를 통과한다고 보장하지는 않습니다. 로그에 해당 앱의 연결 기록이 전혀 없다면 원격 노드를 바꾸지 말고 트래픽이 인바운드로 들어오는지 먼저 확인하세요. 트래픽 연결 방식은 사용 안내를, 연결 오류는 연결 문제 안내를 참고하세요.

시작하자마자 종료됨
JSON 파싱 오류, 지원하지 않는 항목, 포트 바인딩 실패, 데이터 리소스 누락부터 확인하세요.
로컬 포트에는 연결되지만 접속이 안 됨
라우팅 선택, 원격 연결, 인증, TLS 핸드셰이크, DNS 조회를 확인하세요. 포트가 열려 있다는 사실만으로 프록시가 작동한다고 판단하지 마세요.
일부 웹사이트에서만 오류가 발생함
문제가 생긴 도메인과 시간을 기록하고, 차단 또는 직결 규칙에 일치하는지 확인한 뒤 같은 노드에서 결과를 비교하세요.

7. 설정 검증 순서: 한 번에 변수 하나만 변경하기

명령줄 테스트를 사용하면 코어가 설정을 받아들이는지 확인할 수 있습니다. 다음은 V2Ray 5.x와 Xray에서 일반적으로 사용하는 명령 형식입니다. 실제 코어에 맞는 명령 하나만 실행하고, 실행 파일 경로와 현재 작업 디렉터리를 확인하세요. 버전이 다르면 먼저 해당 프로그램의 도움말을 확인하세요.

v2ray test -c config.json

xray run -test -config config.json

이런 테스트만으로 실제 요청을 대체하거나 계정, 서버, 네트워크 경로가 정상이라고 증명할 수는 없습니다. 테스트를 통과한 뒤 코어 시작, 수신 상태 확인, 요청 전송, 출구 확인 순으로 진행하세요. 같은 대상과 접속 방식을 유지해야 어떤 수정이 효과를 냈는지 쉽게 판단할 수 있습니다.

  1. 실제 설정 파일 확인: 시작 매개변수가 어떤 설정 파일을 가리키는지 확인하세요. 백업 파일을 수정하고 다른 파일을 실행하는 실수를 막을 수 있습니다.
  2. 문법과 항목 확인: 현재 코어에서 설정을 테스트하세요. 실패하면 가장 먼저 나온 명확한 오류부터 해결하세요. 뒤따르는 메시지는 앞선 오류로 인해 발생했을 수 있습니다.
  3. 입구 확인: 앱의 프록시 유형과 포트를 확인해 요청이 예상한 인바운드로 들어오는지 확인하세요.
  4. 규칙 확인: 태그 참조와 규칙 순서를 점검하고, 필요하면 출구 하나만 사용하도록 임시로 단순화해 결과를 비교하세요.
  5. 원격 연결 확인: 실제 프록시 설정을 복원한 뒤 서버 주소, 인증 정보, 전송 보안 설정을 확인하세요.
  6. 평소 설정으로 복원: 임시로 넓힌 수신 범위를 원래대로 되돌리고 로그 수준을 복원한 다음, 재현에 필요한 변경 내용을 기록해 두세요.

요약: 요청이 인바운드에 도달했는지 먼저 확인한 뒤 원격 연결을 살펴보세요

인바운드 기록이 없다면 앱 연결 방식과 수신 설정부터 해결하세요. 인바운드에 들어온 요청이 잘못된 출구로 향한다면 라우팅을 먼저 확인하세요. 처리 단계에 따라 문제를 나누면 포트와 프로토콜, 노드를 한꺼번에 바꾸는 것보다 원인을 명확히 찾기 쉽습니다.