이 글의 핵심

v2rayN, v2rayNG 또는 v2flyNG를 이미 사용할 수 있고, 직접 연결·프록시·차단 트래픽을 더 세밀하게 제어하려는 사용자에게 적합합니다. domain, full, regexp, geosite, CIDR, geoip의 정확한 의미와 다중 조건 규칙 조합, 예외 규칙부터 기본 규칙까지의 배치 방법을 다룹니다.

라우팅 규칙이 실제로 처리하는 것

V2Ray 라우팅은 여러 노드의 속도를 비교하는 기능이 아니라, 연결 대상 정보에 따라 하나의 아웃바운드를 선택하는 기능입니다. 애플리케이션이 연결을 시작하면 코어는 대상 도메인 또는 대상 IP, 대상 포트, 네트워크 유형, 인바운드 태그 등의 필드를 읽은 뒤 routing.rules의 첫 번째 규칙부터 확인합니다. 모든 조건을 처음으로 만족한 규칙이 outboundTag를 결정하며, 이후 규칙은 해당 연결에 적용되지 않습니다.

따라서 라우팅 설정을 작성하기 전에 사용할 아웃바운드 태그를 정의해야 합니다. 프록시 아웃바운드는 proxy, 직접 연결은 direct, 차단 아웃바운드는 block처럼 표시할 수 있습니다. 규칙의 태그는 해당 아웃바운드를 참조할 뿐이므로, outboundstag와 철자가 완전히 일치해야 하며 대소문자도 구분됩니다.

애플리케이션이 요청 시작대상 정보 읽기규칙을 순서대로 매칭아웃바운드 태그 선택연결 수립

하나의 type: field 규칙에는 여러 필드가 함께 들어갈 수 있습니다. 같은 필드 배열 안의 값은 ‘하나라도 일치’하는 방식으로 처리됩니다. 예를 들어 domain 배열에 도메인 세 개가 있으면 그중 하나만 일치해도 됩니다. 반면 서로 다른 필드는 ‘모두 충족’해야 합니다. domainport를 함께 지정했다면 대상이 도메인 조건과 지정된 포트 범위를 모두 만족해야 합니다.

규칙 필드 확인하는 정보 예시 조합 방식
domain 대상 도메인 full:api.example.com 배열 안에서 하나라도 일치
ip 대상 IP 또는 해석 결과 10.0.0.0/8 배열 안에서 하나라도 일치
port 대상 포트 5380-443 다른 필드와 함께 충족
network 전송 계층 네트워크 tcp,udp 다른 필드와 함께 충족
inboundTag 어떤 인바운드에서 들어온 연결인지 socks-in 다른 필드와 함께 충족

domain, full, regexp와 geosite

domain 필드는 도메인 조건을 담지만, 배열의 각 문자열에는 서로 다른 접두사를 사용할 수 있습니다. 접두사가 없는 일반 문자열은 가장 범위가 넓은 키워드 매칭으로 처리됩니다. domain:은 도메인과 하위 도메인에 매칭되고, full:은 완전한 도메인명에만 매칭됩니다. regexp:은 정규 표현식을 사용하며, geosite:은 로컬 규칙 데이터의 도메인 분류를 참조합니다.

정확한 도메인

작성법
full:api.example.com
일치
api.example.com
불일치
www.example.com

특정 API 도메인, 업데이트 도메인 또는 고정된 서비스 진입점만 별도로 제어할 때 적합합니다.

도메인과 하위 도메인

작성법
domain:example.com
일치
example.com
함께 일치
cdn.example.com

하나의 주 도메인과 모든 하위 도메인을 같은 아웃바운드로 보내는 데 주로 사용합니다.

정규 표현식 매칭

작성법
regexp:^img[0-9]+\.example\.com$
일치
img12.example.com
비용
매칭 처리 비용이 높음

접두사·접미사 또는 규칙 집합으로 대상을 표현할 수 없을 때만 사용하세요.

도메인 분류

작성법
geosite:cn
데이터 출처
로컬 geosite 데이터 파일
업데이트 방식
규칙 데이터와 함께 업데이트

많은 도메인을 한 번에 처리할 수 있지만, 분류 내용은 로컬 데이터 버전에 따라 달라집니다.

일반 키워드 방식은 매칭 범위를 쉽게 넓힐 수 있습니다. 배열 항목을 example로 작성하면 도메인에 이 문자열이 포함되기만 해도 매칭될 수 있어 example.netcdn-example.org이 모두 포함될 수 있습니다. 완전한 도메인명을 알고 있다면 full:을 우선 사용하세요. 주 도메인과 하위 도메인까지 포함해야 한다면 domain:을 사용하면 넓은 키워드보다 점검하기 쉽습니다.

regexp:의 표현식은 JSON 문자열 이스케이프도 거쳐야 합니다. 정규 표현식에서 사용하는 \.은 JSON에서 \\.으로 작성해야 합니다. 백슬래시를 한 단계 덜 입력하면 설정을 해석하지 못하거나 표현식의 의미가 예상과 달라질 수 있습니다. 다음 규칙은 지정한 API 도메인과 이미지 하위 도메인 그룹만 프록시로 보냅니다.

{
  "type": "field",
  "domain": [
    "full:api.example.com",
    "regexp:^img[0-9]+\\.example\\.com$"
  ],
  "outboundTag": "proxy"
}

geosite은 온라인 조회 서비스가 아니라 로컬 데이터 파일에서 분류를 읽습니다. 일반적인 작성 예로 geosite:cn, geosite:private, geosite:category-ads-all이 있습니다. 특정 분류의 존재 여부와 포함 도메인은 클라이언트가 현재 사용하는 데이터 파일에 따라 달라집니다. 규칙을 복사한 뒤 로그에 분류가 없다고 표시되면 아웃바운드 노드를 계속 수정하지 말고, 먼저 Geo 데이터를 업데이트한 다음 분류명을 확인하세요.

ip, CIDR, geoip와 domainStrategy

ip 필드에는 단일 주소, CIDR 네트워크 또는 geoip: 분류를 지정할 수 있습니다. 단일 IPv4 주소는 192.0.2.10처럼 작성하고, 네트워크는 192.168.0.0/16처럼 작성합니다. IPv6도 fd00::/8과 같은 CIDR을 사용합니다. 사설 네트워크는 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16을 일일이 적는 대신 보통 geoip:private로 묶어 처리합니다.

IP 규칙이 도메인 요청에 매칭될 수 있는지는 routing.domainStrategy와 직접 관련이 있습니다. 브라우저가 도메인에 접속할 때 코어가 처음 받는 대상은 여전히 도메인명일 수 있습니다. 전략이 AsIs이면 라우팅 단계에서 IP 규칙을 적용하기 위해 도메인을 능동적으로 해석하지 않으므로, geoip:cn을 도메인 분류의 대체 수단으로 보면 안 됩니다.

domainStrategy 처리 방식 주요 적용 대상
AsIs 원래 대상 기준으로 매칭하며 라우팅을 위해 도메인을 능동적으로 해석하지 않음 domain·geosite 규칙 중심
IPIfNonMatch 도메인 규칙이 일치하지 않은 뒤 IP를 해석하고 IP 규칙을 시도 도메인 규칙 우선, geoip는 보완용
IPOnDemand 매칭 중 IP 정보가 필요한 규칙을 만나면 대상을 해석 IP 조건에 크게 의존하는 규칙 구조

대부분의 ‘도메인 분류는 직접 연결, IP 분류는 보완’ 설정은 IPIfNonMatch부터 시작할 수 있습니다. 먼저 geosite:cn을 확인하고, 일치하지 않으면 해석 결과를 바탕으로 geoip:cn을 검사하는 방식입니다. DNS가 여러 주소를 반환하면 실제 연결과 라우팅 해석 결과가 DNS 설정, 캐시, 주소 선택의 영향을 받을 수 있으므로 한 번의 해석 결과만으로 전체 규칙이 작동하지 않는다고 판단하지 마세요.

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": [
          "geosite:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:cn"
        ],
        "outboundTag": "direct"
      }
    ]
  }
}

결론: 도메인 분류와 IP 분류는 서로 바꿔 쓸 수 없습니다

사이트별로 분류할 때는 먼저 geosite을 작성하고, 해석된 네트워크 위치를 기준으로 보완할 때 geoip을 사용하세요. 또한 domainStrategy를 이 순서와 일치하는 전략으로 설정해야 합니다.

매칭 우선순위와 규칙 배치 방법

V2Ray은 full:, geosite:, geoip:에 전역 우선순위를 자동으로 부여하지 않습니다. ‘정확한 규칙 우선’은 설정자가 정확한 규칙을 앞에 배치해야 실현됩니다. 앞선 규칙이 이미 일치해 아웃바운드를 선택하면 뒤에 있는 더 정확한 조건도 결과를 덮어쓸 수 없습니다.

가장 안정적인 배치 방식은 ‘예외를 앞에, 분류를 가운데에, 기본 규칙을 뒤에’ 두는 것입니다. 반드시 차단하거나 직접 연결해야 하는 정확한 대상을 먼저 배치하고, 그다음 사설 네트워크와 지역 분류, 프록시가 필요한 분류를 둔 뒤 network: tcp,udp만 포함한 규칙으로 나머지 연결을 처리합니다. 기본 규칙을 중간에 두면 같은 네트워크 유형에 해당하는 뒤의 규칙은 실행될 기회를 잃습니다.

  1. 첫 번째 계층: 특정 도메인, 특정 IP, 특정 포트 등 명확한 예외.
  2. 두 번째 계층: 광고 분류 또는 차단해야 하는 대상.
  3. 세 번째 계층: 로컬 네트워크, 사설 주소, 직접 연결이 필요한 사이트.
  4. 네 번째 계층: 지역 도메인 및 지역 IP 분류.
  5. 다섯 번째 계층: 프록시를 사용할 특정 도메인 또는 분류.
  6. 마지막 계층: tcp,udp를 포괄하는 기본 아웃바운드.

다음은 계속 확장하기 쉬운 구성 예시입니다. 먼저 광고 분류를 차단하고, 사설 주소와 지정 사이트를 직접 연결한 다음 지역 분류를 처리하고, 마지막으로 나머지 TCP·UDP 연결을 프록시로 보냅니다. 예시에 사용한 proxy, direct, block은 전체 설정에 실제로 존재하는 아웃바운드 태그로 바꿔야 합니다.

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": [
          "full:telemetry.example.com",
          "geosite:category-ads-all"
        ],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": [
          "full:intranet.example.com",
          "domain:office.example.net"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": [
          "geosite:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}

하나의 규칙에 domainip를 함께 작성하면 대부분 ‘둘 중 하나’가 아니라 두 필드를 모두 충족해야 한다는 뜻입니다. ‘특정 도메인 또는 특정 IP를 모두 직접 연결’하려는 경우에는 같은 outboundTag를 사용하는 두 개의 규칙으로 나누세요. 이는 사용자 지정 라우팅에서 가장 흔한 논리적 실수 중 하나입니다.

결론: 먼저 규칙을 나누고 순서를 조정하세요

한 규칙에 여러 필드가 들어갔는데 계속 매칭되지 않는다면 먼저 domain, ip, port를 독립 규칙으로 나누어 테스트하세요. 각 조건이 단독으로 작동하는지 확인한 뒤 ‘모두 충족’ 방식으로 합칠 필요가 있는지 결정하면 됩니다.

클라이언트에 적용하고 검증하기

데스크톱 v2rayN 7.x에서는 먼저 「설정」→「라우팅 설정」을 열고 기존 라우팅 프로필을 복사한 뒤 수정하세요. 현재 사용 중인 프로필을 바로 덮어쓰는 일을 피할 수 있습니다. 편집을 마치면 저장하고 해당 프로필을 선택한 다음 코어를 재시작합니다. 최종 생성 내용을 확인하려면 「설정」→「설정 파일 보기」에서 코어에 실제로 전달되는 JSON을 확인하고, routing, rules, outboundTag를 중점적으로 검색하세요.

안드로이드 v2rayNG와 v2flyNG의 메뉴 위치는 버전에 따라 달라질 수 있지만 검증 원칙은 같습니다. 먼저 현재 설정에서 사용자 지정 라우팅이 활성화되어 있는지 확인한 다음, 사전 정의 규칙·도메인 전략·애플리케이션 프록시 설정이 서로 덮어쓰고 있지 않은지 점검하세요. 구독 업데이트는 일반적으로 서버 설정만 갱신하므로, 클라이언트의 사용자 지정 라우팅 프로필이 모두 유지된다고 가정해서는 안 됩니다. 수정 전에 규칙 텍스트를 저장해 두면 이전이 더 쉽습니다.

포트 조건을 테스트할 때는 로컬 프록시 수신 포트와 대상 포트를 구분해야 합니다. v2rayN에서 흔히 사용하는 로컬 SOCKS 수신 포트 10808은 인바운드 포트입니다. 반면 라우팅 규칙의 port: 443은 원격 대상 포트를 의미합니다. 10808을 대상 포트 규칙에 넣어도 일반적으로 ‘모든 브라우저 트래픽’을 처리할 수 없습니다.

수정 후 모든 웹 페이지에 연결할 수 없다면 먼저 기본 규칙 하나만 있는 최소 설정으로 되돌린 뒤 규칙을 하나씩 복원하세요. 코어 로그에 failed to parse가 표시되면 JSON의 쉼표·따옴표·정규 표현식 이스케이프를 확인합니다. geosite 또는 geoip 분류를 찾을 수 없다는 메시지가 나오면 해당 데이터 파일을 업데이트하세요. 연결은 수립되지만 아웃바운드가 예상과 다르면 규칙 순서와 태그 철자를 우선 점검합니다.

full 규칙을 작성했는데 왜 여전히 기본 프록시로 연결되나요?

먼저 로그의 대상이 도메인명인지, 애플리케이션이 미리 해석한 IP인지 확인하세요. 그다음 완전한 도메인명, 포트 조건, 아웃바운드 태그를 점검합니다. 애플리케이션이 IP에 직접 연결하면 별도의 full: 규칙은 매칭되지 않습니다.

geosite:cn과 geoip:cn 중 하나만 남겨야 하나요?

두 규칙은 서로 다른 정보를 처리합니다. 먼저 geosite:cn으로 도메인을 매칭하고, IPIfNonMatch에서 geoip:cn을 사용해 해석된 주소를 기준으로 연결을 보완할 수 있습니다.

direct를 첫 번째 규칙에 두면 왜 프록시 규칙이 작동하지 않나요?

첫 번째 규칙에 모든 연결을 포괄하는 network: tcp,udp가 작성되어 있는지 확인하세요. 이 규칙은 기본 규칙이므로 목록의 마지막으로 옮겨야 합니다. 그렇지 않으면 같은 네트워크 유형을 대상으로 하는 뒤의 규칙이 매칭되지 않습니다.

같은 규칙에 domain과 port를 함께 쓰면 어떤 관계인가요?

두 필드는 모두 충족되어야 합니다. 예를 들어 domain:example.comport:443을 함께 지정하면 해당 주 도메인과 하위 도메인이 대상 포트 443으로 연결할 때만 처리하며, 대상 포트 80은 포함하지 않습니다.

관리하기 쉬운 규칙을 위한 최종 점검

관리하기 쉬운 라우팅 설정에는 반복 항목을 많이 쌓을 필요가 없습니다. 예외는 명확한 full:domain:으로 표현하고, 분류는 geositegeoip에 맡긴 뒤 읽기 쉬운 기본 규칙 하나만 남기세요. 수정할 때마다 한 가지 조건만 추가하고 로그로 실제 매칭 규칙과 아웃바운드를 확인하는 것이 좋습니다.

규칙 수가 늘어나면 ‘차단, 사설 네트워크, 강제 직접 연결, 분류별 직접 연결, 강제 프록시, 기본 프록시’ 순서로 그룹을 나눌 수 있습니다. 클라이언트 화면에서 드래그할 수 있더라도 참고용으로 포맷을 정리한 JSON을 보관하고, domainStrategy·아웃바운드 태그·사용하는 Geo 분류를 기록하세요. 이렇게 하면 v2rayN, v2rayNG, v2flyNG 사이에서 설정 방식을 옮길 때 화면 옵션을 코어 문법으로 잘못 이해하는 일을 줄일 수 있습니다.