Xray API를 이용하면 GUI에서 노드를 하나씩 클릭하지 않고도 여러 아웃바운드의 상태를 수집하고, 지연 시간이나 연결 성공 여부를 기준으로 사용할 노드를 바꿀 수 있습니다. 다만 Xray 코어가 모든 환경에서 완성된 “최적 노드 자동 선택”을 대신해 주는 것은 아닙니다. API 서비스, 통계 수집, 라우팅 태그, 선택 정책과 실패 시 복구 절차를 함께 설계해야 안정적으로 운영할 수 있습니다.
VLESS 또는 VMess 노드를 여러 개 보유한 개발자와 네트워크 운영자를 위한 고급 설정 안내입니다. Xray 25.x 계열을 기준으로 API 인바운드와 gRPC 서비스 태그를 구성하고, 노드별 아웃바운드 태그를 분리한 뒤, 상태 확인·지연 시간 측정·선택 결과 반영까지 연결하는 방법을 설명합니다. 예시는 Linux에서 주기적으로 실행할 수 있는 구조를 사용하며, 기존 연결을 불필요하게 끊지 않는 운영 원칙도 함께 다룹니다.
Xray API 자동 선택의 전체 구조 이해하기
Xray에서 노드 자동 선택을 구현할 때 먼저 구분해야 할 것은 “노드의 연결 설정”과 “트래픽을 보낼 대상 태그”입니다. 각 서버를 node-hk-01, node-jp-01, node-sg-01처럼 별도의 아웃바운드로 정의하고, 실제 애플리케이션 요청은 하나의 라우팅 대상 또는 선택용 태그로 전달합니다. 스크립트는 API를 통해 통계를 조회하거나 외부 테스트를 수행한 뒤, 정해진 정책에 따라 다음 요청이 사용할 태그를 결정합니다.
Xray API는 일반적인 HTTP REST API가 아니라 gRPC 기반 서비스입니다. 따라서 API 포트에 브라우저로 접속해 JSON을 보내는 방식은 사용할 수 없습니다. 설정에는 API 서비스 목록과 API 인바운드가 필요하며, 보통 로컬 주소의 127.0.0.1:10085에만 바인딩해 외부 노출을 막습니다. API 포트를 모든 인터페이스에 열면 인증과 방화벽을 별도로 구성하지 않는 한 원격 사용자가 코어를 제어할 위험이 있습니다.
자동 선택 방식은 크게 두 가지로 나눌 수 있습니다. 첫 번째는 Xray의 라우팅과 관측 기능이 지원하는 내장 전략을 사용하는 방법입니다. 두 번째는 외부 스크립트가 각 노드를 실제로 검사하고 API 또는 설정 재생성 방식으로 결과를 반영하는 방법입니다. 내장 전략은 구성이 간결하지만 세부 조건을 자유롭게 넣기 어렵고, 외부 스크립트는 유연한 대신 동시 실행, 실패 복구, 변경 검증을 직접 처리해야 합니다.
API 인바운드와 노드별 아웃바운드 태그 설정
다음은 구조를 설명하기 위한 축약 JSON입니다. 실제 노드의 주소, UUID, 암호화 방식, 서버 인증서와 전송 옵션은 공급자가 제공한 값을 사용해야 합니다. 예시의 핵심은 API 서비스에 HandlerService, StatsService, RoutingService를 등록하고, 각 노드에 서로 다른 태그를 부여하는 것입니다.
{
"log": {
"loglevel": "warning"
},
"api": {
"tag": "api",
"services": [
"HandlerService",
"StatsService",
"RoutingService"
]
},
"inbounds": [
{
"tag": "api-in",
"listen": "127.0.0.1",
"port": 10085,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1"
}
}
],
"outbounds": [
{
"tag": "node-hk-01",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "hk.example.net",
"port": 443,
"users": [
{
"id": "00000000-0000-0000-0000-000000000000",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls"
}
},
{
"tag": "node-jp-01",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "jp.example.net",
"port": 443,
"users": [
{
"id": "00000000-0000-0000-0000-000000000000",
"encryption": "none"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls"
}
},
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "block",
"protocol": "blackhole"
}
],
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"inboundTag": ["api-in"],
"outboundTag": "api"
}
]
}
}
위 설정에서 API 인바운드의 요청을 api 아웃바운드로 보낸다는 의미와 API 서비스 자체가 열려 있다는 의미는 서로 다릅니다. API 인바운드가 외부 요청을 받는 일반 프록시 입구가 되지 않도록 주소를 루프백으로 제한하고, 일반 사용자의 SOCKS 또는 HTTP 인바운드와 분리하세요. 노드 아웃바운드에는 태그만 보고도 지역과 용도를 판단할 수 있는 이름을 사용하는 것이 좋습니다.
node-hk-01처럼 각 서버를 독립적인 아웃바운드로 정의합니다. 스크립트가 대상을 식별하기 쉽고, 특정 노드만 비활성화하거나 재검사하기 편합니다.
적합한 경우: 소수의 안정적인 노드, 세밀한 장애 관리
스크립트가 선택된 서버 정보를 포함한 새 JSON을 만든 뒤 코어를 재시작합니다. 구현은 단순하지만 재시작 순간에 기존 연결이 끊기고 설정 문법 오류의 영향이 큽니다.
적합한 경우: 재시작이 허용되는 개인 서버
여러 아웃바운드를 하나의 그룹으로 묶어 라우팅 계층에서 선택합니다. 지원되는 Xray 버전과 전략을 먼저 확인해야 하며, 외부 품질 기준을 그대로 반영하려면 별도 검사가 필요합니다.
적합한 경우: 코어 내부에서 분산 처리를 원하는 환경
상태 확인과 지연 시간 평가 정책 만들기
노드 자동 전환에서 가장 흔한 실수는 지연 시간이 가장 낮은 노드를 무조건 선택하는 것입니다. 측정 대상이 API 서버인지 실제 업무 사이트인지에 따라 결과가 달라지고, 한 번의 측정은 순간적인 캐시나 회선 상태를 반영할 뿐입니다. 최소 3회 측정 후 중앙값을 사용하고, 연결 성공률·연속 실패 횟수·최근 전환 시각을 함께 저장하는 편이 안전합니다.
Xray의 StatsService는 트래픽과 연결 관련 통계를 조회하는 데 유용하지만, 통계가 곧 인터넷 품질 측정값은 아닙니다. 후보 노드로 실제 요청을 보내는 별도 검사와 코어 통계를 조합해야 합니다. 또한 모든 노드를 몇 초마다 동시에 검사하면 서버와 회선에 불필요한 부하가 발생하므로 후보 수에 따라 30초에서 5분 사이의 주기를 선택하세요.
| 평가 항목 | 권장 기준 | 자동 전환 판단 |
|---|---|---|
| 연결 성공 | 3회 중 2회 이상 성공 | 2회 연속 실패하면 일시 제외 |
| 지연 시간 | 3회 측정 중앙값 | 현재 노드보다 20% 이상 낮을 때 후보 |
| 안정성 | 최근 5분 오류 수 | 오류가 많은 노드의 점수 감점 |
| 전환 횟수 | 최소 유지 시간 180초 | 임계값 미달이어도 즉시 재전환하지 않음 |
간단한 점수 모델은 다음처럼 만들 수 있습니다. 중앙 지연 시간이 80ms인 노드에는 낮은 지연 점수를, 2회 연속 실패한 노드에는 큰 감점을 주고, 최근 180초 안에 선택된 노드에는 전환 방지 페널티를 적용합니다. 이렇게 하면 2~3ms 차이 때문에 노드가 계속 바뀌는 현상을 줄일 수 있습니다. 업무가 웹 브라우징 중심이면 지연과 성공률에 높은 가중치를 주고, 장시간 전송 중심이면 처리량과 연결 유지 시간을 별도로 측정하세요.
결론: 최저 지연보다 안정적인 2순위가 더 나을 수 있습니다
중앙 지연이 55ms인 노드가 85ms인 노드보다 빠르더라도 최근 5분 동안 세 번 끊겼다면 자동 선택 대상에서 제외하는 편이 합리적입니다. 노드 선택기는 속도 순위표가 아니라 성공률·지연·전환 빈도를 함께 관리하는 정책 엔진으로 설계해야 합니다.
동작 구현: 스크립트에서 선택 결과를 반영하기
운영 스크립트는 “측정 → 검증 → 변경 → 확인”의 네 단계를 분리하세요. 측정 결과를 바로 코어에 보내지 말고, 노드 태그가 허용 목록에 있는지, 점수가 임계값을 넘는지, 마지막 변경 이후 최소 유지 시간이 지났는지 확인해야 합니다. 또한 스크립트가 동시에 두 번 실행되지 않도록 파일 잠금이나 systemd 단일 실행 정책을 사용해야 합니다.
-
허용 태그 정의
스크립트 내부에
node-hk-01,node-jp-01처럼 검사할 태그를 명시합니다. API 응답으로 받은 임의의 태그를 그대로 실행 대상으로 사용하지 마세요. -
후보 노드 검사
각 후보에 대해 동일한 HTTPS 요청을 수행하고 타임아웃, HTTP 상태, 왕복 시간을 기록합니다. 한 번의 성공보다 최근 3회 결과의 중앙값과 실패 횟수를 우선합니다.
-
전환 조건 확인
새 노드 점수가 현재 노드보다 충분히 높고 최소 유지 시간 180초가 지났는지 확인합니다. 차이가 작으면 현재 노드를 유지해 불필요한 전환을 막습니다.
-
API 변경 실행
사용 중인 Xray 버전의 HandlerService 메서드와 요청 메시지 형식을 확인한 뒤 변경을 보냅니다. 지원하지 않는 메서드를 임의로 호출하지 말고 먼저 서비스 목록과 오류 응답을 확인하세요.
-
변경 후 검증
선택 결과를 로컬 파일에 기록하고 5~10초 뒤 실제 프록시 요청을 다시 검사합니다. API 호출이 성공했어도 라우팅 태그가 잘못되면 사용자 트래픽은 이전 노드에 남을 수 있습니다.
여기서 중요한 기술적 주의점은 “활성 노드 선택”이 Xray의 모든 API 버전에서 동일한 단일 메서드로 제공된다고 가정하면 안 된다는 것입니다. Xray의 API 서비스와 protobuf 정의는 코어 버전에 따라 지원 범위가 달라질 수 있습니다. 먼저 설치된 코어에서 제공되는 서비스와 메서드를 확인하고, 해당 버전이 아웃바운드 변경을 지원하는지 검증하세요. 변경 API를 지원하지 않는 환경에서는 관리용 JSON을 안전한 임시 파일에 생성하고, 문법 검사를 통과한 뒤 짧은 재시작으로 반영하는 방식이 더 예측 가능합니다.
# 실행 중인 코어의 API 포트가 로컬에서 열려 있는지 확인
ss -lntp | grep 10085
# 설정 파일 문법 검사 예시
xray run -test -config /etc/xray/config.json
# 마지막 선택 결과 기록 예시
2026-08-29T12:30:00Z selected=node-jp-01 median=61ms failures=0
API 변경을 적용할 때는 현재 연결이 즉시 끊기는지 반드시 확인하세요. 기존 아웃바운드의 서버 주소를 직접 덮어쓰는 방식은 활성 연결과 새 연결의 동작이 달라질 수 있습니다. 가능하면 노드별 태그를 유지하고 라우팅 대상만 바꾸는 구조를 선택하세요. 전환 직후 오류가 증가하면 마지막으로 정상 확인된 태그로 되돌리는 롤백 값을 별도로 저장해야 합니다.
Linux 상시 운영과 문제 해결
Linux 서버에서는 자동 선택기를 사용자 셸에서 실행한 채 방치하기보다 systemd 서비스와 타이머로 관리하는 편이 좋습니다. 검사 스크립트의 실행 계정에는 Xray 설정 파일을 읽을 권한만 부여하고, API 포트는 로컬 소켓 또는 루프백에 한정하세요. 스크립트 로그에는 전체 구독 주소, UUID, API 인증 토큰 같은 민감한 값을 기록하지 말고 태그·지연 시간·결과 코드만 남겨야 합니다.
주기 실행 간격은 노드 수와 서비스 성격을 기준으로 정합니다. 후보가 3개이고 일반 웹 트래픽을 처리한다면 60초 주기가 시작점으로 적절하며, 짧은 순간의 장애를 빠르게 감지해야 하는 환경에서도 10초 이하로 줄이기 전에 검사 트래픽을 계산해야 합니다. systemd 타이머가 이전 실행이 끝나기 전에 다시 시작되지 않도록 잠금 파일을 사용하고, 실패한 실행은 즉시 무한 재시도하지 말고 지수형 대기 시간을 적용하세요.
권장 운영값
- API 바인딩
- 127.0.0.1:10085
- 측정 주기
- 60초
- 최소 유지
- 180초
- 실패 제외
- 2회 연속
개인 서버와 소규모 후보 노드에 적합한 보수적 시작값입니다.
변경 전 확인값
- 허용 태그
- 정적 목록
- 설정 검사
- xray run -test
- 롤백 태그
- 마지막 정상 노드
- 로그 보존
- 최근 7일
자동화 오류가 발생해도 원인을 추적하고 이전 상태로 복구할 수 있습니다.
API 포트에 연결되지만 메서드 호출이 실패합니다
포트가 열려 있다는 사실만으로 해당 서비스가 등록된 것은 아닙니다. api.services에 필요한 서비스를 등록했는지 확인하고, 설치된 Xray 코어의 API 정의와 호출하는 RPC 메서드가 일치하는지 점검하세요.
지연 시간이 낮은 노드가 계속 바뀝니다
최소 유지 시간을 180초 이상으로 설정하고 3회 측정 중앙값을 사용하세요. 현재 노드보다 20% 이상 개선될 때만 전환하도록 히스테리시스를 추가하면 작은 측정 차이로 인한 반복 전환을 줄일 수 있습니다.
전환 성공 로그가 있는데 접속은 계속 이전 노드로 됩니다
스크립트가 변경한 태그가 실제 라우팅 규칙의 outboundTag 또는 밸런서 대상과 연결되어 있는지 확인하세요. API 대상 태그와 사용자 트래픽의 라우팅 태그는 이름이 비슷해도 별개의 설정일 수 있습니다.
모든 후보가 실패하면 어떻게 해야 하나요?
현재 노드를 즉시 삭제하지 말고 마지막 정상 노드를 유지한 뒤, 새 연결만 보수적으로 재시도하세요. 일정 시간 동안 후보가 복구되지 않으면 direct나 block으로 임의 전환하지 말고 운영자 알림을 발생시키는 편이 안전합니다.
Xray API 기반 자동 선택의 핵심은 API 호출 자체가 아니라 안전한 상태 전이입니다. 노드 태그를 안정적으로 분리하고, 관측 결과를 여러 번 누적하며, 전환 조건과 롤백 값을 명시하면 GUI를 계속 확인하지 않아도 예측 가능한 운영이 가능합니다. 설정을 변경하기 전에는 현재 코어 버전에서 지원되는 API 서비스와 메서드를 확인하고, 테스트 환경에서 실제 트래픽이 새 아웃바운드로 흐르는지 검증한 뒤 Linux 상시 운영으로 확장하세요.