v2rayN에서 코어 시작 오류가 표시되거나, v2rayNG가 실행 직후 종료되거나, 사용자 설정을 수정한 뒤 불러오지 못하는 경우에 적용할 수 있습니다. 먼저 설정 로드 실패와 실행 중 연결 실패를 구분한 다음, 로그의 구체적인 원인을 바탕으로 JSON, 수신 대기 포트, 프로토콜, 라우팅 필드를 확인하세요. 한 번에 한 가지 문제만 수정하고, 마지막으로 설정 테스트와 실제 요청을 각각 확인합니다.
먼저 오류가 발생한 단계 확인하기
“웹페이지가 열리지 않는다”는 것이 곧 “코어가 시작되지 않았다”는 뜻은 아닙니다. 클라이언트 화면이 열려도 백그라운드 코어가 정상적으로 실행 중이라는 보장은 없습니다. 시작 단계에서는 설정을 읽고 인바운드와 아웃바운드를 구성한 뒤 로컬 포트에서 수신 대기를 시작해야 합니다. 이 과정이 완료되어야 앱 요청이 라우팅 규칙에 도달할 수 있습니다.
- 시작 직후 종료됨: 먼저
Failed to start,failed to load,failed to listen등의 문구를 찾아 로컬 설정과 수신 대기 조건을 확인하세요. - 시작 후 요청 로그가 표시됨: 일반적으로 실행 단계에 들어간 상태입니다. 이때 원격 연결 시간 초과, 인증서 오류, 연결 거부가 발생한다면 노드 주소, 전송 매개변수, 네트워크 연결 상태를 확인하세요.
- 로그가 전혀 표시되지 않음: 구독 업데이트 로그만 보고 있는 것은 아닌지 확인하고 코어 로그가 활성화되어 있는지 점검하세요. 클라이언트가 실제로 코어 프로그램을 실행했는지, 로그를 쓸 수 있는 위치인지도 확인해야 합니다.
v2rayN은 데스크톱 클라이언트이며, 사용할 수 있는 필드는 현재 선택한 코어에 따라 달라집니다. v2rayNG는 Xray를, v2flyNG는 V2Fly를 사용합니다. 두 코어의 설정은 일부 겹치지만 모든 확장 필드를 서로 바꿔 쓸 수 있는 것은 아닙니다. 문제를 기록할 때는 클라이언트 버전과 코어 버전을 함께 적고, “최신 버전”이라고만 쓰지 마세요.
전체 시작 로그 보관하기
연결 버튼을 반복해서 누르지 말고 현재 설정을 백업한 다음 로그 표시 영역을 지우거나 시간을 기록하세요. 한 번만 시작하고 코어 버전이 표시된 줄부터 종료 정보까지 보관합니다. v2rayNG에서는 사이드 메뉴의 「로그」를 열 수 있습니다. v2rayN에서는 기본 창의 정보 출력 영역을 확인하세요. 메뉴 위치와 화면 구성은 버전에 따라 달라질 수 있으므로 코어 시작 정보를 기준으로 확인하면 됩니다.
| loglevel | 주요 용도 | 확인할 내용 |
|---|---|---|
error | 오류 수집 | 로드 또는 연결 실패의 원인 보관 |
warning | 경고 및 오류 확인 | 경고가 이번 종료와 직접 관련 있는지 확인 |
info | 실행 정보 보충 | 시작 과정 및 요청 처리 상황 |
debug | 임시로 상세 분석 | 내부 처리에 관한 상세 단서 |
none | 이 로그 수준 끄기 | 문제 해결 중에는 사용하지 않는 것이 좋음 |
사용자 JSON 설정에서는 log.loglevel을 임시로 debug로 설정할 수 있습니다. 로그가 더 상세해질 뿐 오류가 해결되는 것은 아닙니다. JSON 자체를 파싱할 수 없다면 이 설정도 적용되지 않았을 수 있으므로 프로세스 출력이나 클라이언트가 캡처한 표준 오류를 확인해야 합니다.
{
"log": {
"loglevel": "debug"
}
}
로그의 타임스탬프와 연결 번호는 동일한 작업의 기록을 연결하는 데 사용됩니다. >가 여러 개 포함된 오류는 대개 여러 단계로 감싼 오류 체인입니다. 먼저 이번 시작과 관련된 첫 실패를 찾고, 오류 체인 끝까지 읽어 구체적인 원인을 확인하세요. 가장 바깥의 Failed to start만 잘라내거나 이전 요청의 시간 초과를 섞어서는 안 됩니다.
JSON 구문 오류: 구조부터 바로잡고 필드 확인하기
JSON 파싱에 실패하면 프로토콜, DNS, 라우팅은 아직 정상적으로 구성되지 않은 경우가 많습니다. 흔한 원인은 마지막 항목 뒤에 쉼표를 붙이거나, 큰따옴표를 빠뜨리거나, 복사 과정에서 따옴표가 바뀌거나, 숫자 필드를 문자열로 작성하는 것입니다. 오류 위치가 실제 문제 지점보다 뒤에 표시될 수도 있습니다. 파서가 다음 문자를 읽을 때 앞부분의 구조가 잘못되었음을 알아차리기 때문입니다.
오류: invalid character '}' looking for beginning of object key string
원인: 객체가 끝나기 전에 필드 이름이 와야 하는 상황입니다. 마지막 필드 뒤에 쉼표를 잘못 붙인 경우가 흔합니다.
해결 방법: 닫는 중괄호 앞의 줄을 확인해 불필요한 쉼표를 지우고, 객체의 키 이름을 영문 큰따옴표로 감쌌는지 확인하세요.
오류: unexpected EOF
원인: 입력이 너무 일찍 끝났습니다. 닫는 괄호나 따옴표가 빠졌거나 저장 중 파일이 잘렸을 수 있습니다.
해결 방법: 마지막으로 수정한 위치부터 괄호와 따옴표의 짝이 맞는지 확인하세요. 파일이 눈에 띄게 불완전하다면 먼저 백업을 복원한 뒤 수정 내용을 나눠 다시 적용하세요.
오류: cannot unmarshal string into Go struct field
원인: 필드의 데이터 형식이 코어에서 기대하는 형식과 다릅니다. 이후 로그에 필드 경로와 필요한 형식이 표시되는 경우가 많습니다.
해결 방법: 전체 경로를 기준으로 형식을 확인하세요. 예를 들어 로컬 인바운드 포트는 "port": 10808처럼 작성해야 하며, 숫자를 따옴표로 감싼 문자열로 입력하면 안 됩니다.
여기에 나온 내용은 흔한 오류 문구의 예시입니다. 전체 접두어, 대소문자, 필드 경로는 코어 버전에 따라 달라질 수 있습니다. 수정할 때 전체 바꾸기를 무작정 사용하지 마세요. 포트 필드에 숫자가 필요하다고 해서 숫자를 포함한 모든 값에서 따옴표를 제거해야 하는 것은 아닙니다. UUID, 주소, 태그는 문자열입니다.
- JSON 검사를 지원하는 로컬 편집기로 실제 읽히는 파일을 여세요.
- 편집기가 표시하는 첫 번째 구문 오류부터 수정하고, 다시 검사한 뒤 다음 오류를 처리하세요.
- 표준 JSON에서는 끝에 쉼표를 붙이거나 주석을 작성할 수 없습니다. 일부 로더가 확장 문법을 허용하더라도 문제 해결 중에는 표준 JSON을 우선 사용하세요.
- 클라이언트 양식으로 설정을 생성했다면 해당 설정 항목으로 돌아가 수정하세요. 임시 생성 파일을 직접 편집하면 다음 시작 때 덮어써질 수 있습니다.
포트 충돌: 무작정 관리자 권한을 쓰지 말고 프로세스 확인하기
인바운드 생성 실패는 두 클라이언트가 같은 주소와 포트에서 동시에 수신 대기하거나, 이전 실행의 프로세스가 아직 종료되지 않았을 때 자주 발생합니다. 아래 포트는 이 글의 예시이며 모든 클라이언트의 기본값을 의미하지 않습니다. 로그나 현재 설정에서 실제 포트를 확인한 뒤 명령어의 숫자를 바꾸세요.
오류: address already in use
원인: 지정한 수신 대기 주소와 포트가 이미 사용 중이거나 기존 수신 대기 범위와 충돌합니다.
해결 방법: 수신 대기 중인 프로세스를 확인하고 중복 실행된 인스턴스를 정상 종료하세요. 여러 인스턴스를 함께 실행해야 한다면 인바운드마다 다른 포트를 지정하고 앱의 프록시 설정도 함께 변경하세요.
오류: Only one usage of each socket address
원인: Windows 소켓 바인딩 충돌입니다. 전체 오류에는 로컬 주소와 포트도 표시되는 경우가 많습니다.
해결 방법: 로그에 표시된 포트로 수신 대기 PID를 찾으세요. 관리자 권한으로 실행하는 것은 포트 충돌의 일반적인 해결책이 아닙니다.
Windows: 수신 대기 PID 확인하기
Get-NetTCPConnection -LocalPort 10808 -State Listen |
Select-Object LocalAddress, LocalPort, OwningProcess
PowerShell에서 명령을 실행한 다음 작업 관리자의 「세부 정보」 탭에서 PID와 프로세스를 대조하세요. 어떤 프로그램인지 확인한 뒤 종료하고, 포트만 기준으로 출처를 알 수 없는 시스템 프로세스를 일괄 종료하지 마세요. 수신 대기 결과가 없다면 전체 로그에 권한 또는 사용할 수 없는 주소 오류가 표시되는지 확인하세요.
Linux 및 macOS: 수신 대기 프로세스 확인하기
# Linux
ss -ltnp 'sport = :10808'
# macOS
lsof -nP -iTCP:10808 -sTCP:LISTEN
일반 사용자 권한으로는 다른 사용자의 프로세스 정보가 모두 표시되지 않을 수 있습니다. 필요한 경우 조회 명령에만 권한을 높이고, 클라이언트 전체를 계속 높은 권한으로 실행하지 마세요. 로컬 포트를 10808에서 10810으로 변경했다면 브라우저, 시스템 프록시, 직접 설정한 다른 앱에서도 포트를 변경해야 합니다.
프로토콜 및 필드 오류: 실제 사용 중인 코어 확인하기
JSON 형식이 올바르다는 것은 파일을 파싱할 수 있다는 뜻일 뿐, 코어가 해당 프로토콜을 이해한다는 뜻은 아닙니다. protocol 값은 vmess, vless, socks, freedom처럼 정확하게 입력해야 합니다. 인바운드와 아웃바운드의 settings 구조는 서로 다릅니다. 서버에서 사용자를 받는 필드를 클라이언트 아웃바운드에 그대로 붙여 넣지 마세요.
- 먼저 버전 확인: 시작 로그에 표시된 Xray 또는 V2Fly 이름과 버전을 기록하세요. 클라이언트 화면에 표시되는 버전과 코어 버전은 별개의 정보입니다.
- 다음으로 방향 확인: 아웃바운드는 원격 서버를, 인바운드는 로컬 수신 대기를 설정합니다. 프로토콜 이름이 같아도 양쪽에서 사용하는 필드는 다를 수 있습니다.
- 마지막으로 확장 기능 확인: 전송 계층, 보안 계층, 프로토콜 확장 기능마다 지원 범위가 다릅니다. 다른 코어에 설정을 적용하기 전에 프로그램 이름만 바꾸지 말고 항목별로 확인하세요.
“알 수 없는 프로토콜” 오류가 항상 한 줄로 표시되는 것은 아니며 인바운드 또는 아웃바운드 로드 실패에 포함될 수 있습니다. 오류 체인을 따라가 구체적인 protocol 값을 찾은 뒤 실제 설정과 비교하세요. 알 수 없는 필드에서 오류가 발생하지 않았다고 해서 적용된 것은 아닙니다. 일부 알 수 없는 JSON 필드는 무시될 수 있으므로 현재 코어의 문서와 실제 동작을 확인해야 합니다.
라우팅 오류: 조건과 아웃바운드 태그 확인하기
라우팅 규칙은 코어에 들어온 연결을 특정 아웃바운드로 보내는 역할을 합니다. routing.rules는 순서대로 매칭됩니다. 범위가 넓은 규칙을 앞에 두면 뒤의 더 구체적인 규칙이 적용되지 않을 수 있습니다. 이런 설정은 시작에는 성공해도 “모든 트래픽이 직접 연결됨” 또는 “특정 도메인이 잘못된 경로로 연결됨” 같은 문제를 일으킬 수 있습니다. 시작 실패를 일으키는 구조 오류와는 구분해서 살펴보세요.
오류: this rule has no effective fields
원인: 규칙에 유효한 매칭 조건이 없습니다. 예를 들어 type과 outboundTag만 남아 있는 경우입니다.
해결 방법: domain, ip, port, network 등 명확한 조건을 추가하거나 필요 없는 빈 규칙을 삭제하세요.
아래는 문제를 분리해 테스트하기 위한 간단한 전체 설정입니다. 로컬 127.0.0.1:10808에서만 SOCKS 인바운드를 제공하고, example.com과 하위 도메인은 차단 아웃바운드로 보내며 나머지 트래픽은 첫 번째 직접 연결 아웃바운드를 사용합니다. 원격 프록시 노드는 포함되어 있지 않으므로 실제 노드 설정을 대체할 수 없습니다.
{
"log": {
"loglevel": "info"
},
"inbounds": [
{
"tag": "local-socks",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": false
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {}
},
{
"tag": "blocked",
"protocol": "blackhole",
"settings": {}
}
],
"routing": {
"rules": [
{
"type": "field",
"domain": ["domain:example.com"],
"outboundTag": "blocked"
}
]
}
}
outboundTag와outbounds[].tag를 대소문자까지 정확히 비교하세요. 태그가 없을 때의 동작은 버전과 처리 경로에 따라 달라질 수 있으므로 시작에 성공했다는 이유만으로 설정이 올바르다고 판단해서는 안 됩니다.- 도메인 및 IP 매칭 조건에는 배열을 사용합니다. 한 규칙에 여러 조건을 지정하면 일반적으로 모두 충족해야 합니다. 조건 추가를 선택 사항 추가로 착각하지 마세요.
- 오류가
geosite.dat또는geoip.dat를 직접 가리킨다면 현재 코어의 리소스 디렉터리, 파일 읽기 권한, 규칙에서 참조하는 분류가 실제로 있는지 확인하세요. - 리소스 문제를 분리하려면 위의 명확한 도메인 규칙을 리소스 분류 대신 임시로 사용할 수 있습니다. 검증을 마친 뒤 기존 규칙을 하나씩 복원하세요.
수정 후 두 단계로 확인하기
첫 번째 단계에서는 코어가 설정을 받아들이는지 확인합니다. Xray 명령줄을 사용하는 경우 설정 파일이 있는 디렉터리에서 아래 테스트 명령을 실행하세요. 실행 파일은 클라이언트가 실제로 사용하는 것과 같은 버전이어야 합니다. Windows에서는 명령어 앞부분의 xray를 .\xray.exe로 바꾸면 됩니다.
xray run -test -config ./config.json
설정 테스트에 성공해도 포트 바인딩이나 원격 서버 연결까지 보장되는 것은 아닙니다. 두 번째 단계에서는 클라이언트를 실제로 시작해 새로운 수신 대기 오류가 없는지 확인한 다음, 올바른 로컬 프록시 포트를 통해 앱에서 요청을 보내세요. 예시 설정에서는 example.com을 의도적으로 차단하므로 해당 도메인이 열리는지 확인해서는 안 됩니다.
JSON 검사는 통과했는데 왜 시작에 실패하나요?
JSON 검사는 구문만 확인합니다. 코어 출력을 계속 읽으며 프로토콜 구성 실패, 리소스 파일 읽기 실패, 포트 바인딩 실패를 구분하세요. 먼저 설정 테스트를 실행한 뒤 실제로 시작하고, 두 단계의 결과를 각각 기록하세요.
파일을 고쳐도 다시 연결하면 원래대로 돌아가나요?
클라이언트가 자동 생성한 실행 설정을 수정했을 수 있습니다. 백업한 다음 노드 편집, 라우팅 설정 또는 사용자 설정 메뉴에서 원본 데이터를 변경하세요. 다시 시작한 뒤 새로 생성된 파일과 로그에 표시된 파일 경로를 확인합니다.
코어는 시작됐는데 로그에 시간 초과가 계속 표시되면 어떻게 하나요?
먼저 앱 요청이 로컬 인바운드에 실제로 도달하는지 확인한 뒤 원격 주소, 포트, TLS 서버 이름, 전송 경로를 점검하세요. 실행 중 발생하는 원격 시간 초과는 JSON 구문 오류가 아니므로 설정 전체를 반복해서 삭제할 필요가 없습니다.
클라이언트를 다시 설치하면 포트 충돌이 해결되나요?
재설치해도 다른 프로그램의 수신 대기가 자동으로 해제되지는 않습니다. 먼저 실제 충돌 포트(예: 10808)에 해당하는 PID를 조회하고 중복 인스턴스를 종료하거나 포트를 변경한 뒤 앱의 프록시 설정도 함께 바꾸세요.
재현 가능한 문제 해결 기록에는 작업 시간, 클라이언트 및 코어 버전, 읽어 온 설정 경로, 첫 번째 오류 로그, 이번에 수정한 필드, 재검사 결과가 포함되어야 합니다. 한 번에 변수 하나만 바꾸면 포트를 해결하는 동시에 라우팅 오류를 새로 만드는 일을 방지할 수 있습니다. 필드 구조를 더 자세히 확인하려면 설정 참조를 보며 항목별로 점검하세요.