๐ OmniRoute Proxy Guide (ํ๊ตญ์ด)
- ํ๋ก์๋ฅผ ์ฌ์ฉํ๋ ์ด์
- ์ํคํ ์ฒ ๊ฐ์
- 4๋จ๊ณ ํ๋ก์ ์์คํ
- ํ๋ก์ ๋ ์ง์คํธ๋ฆฌ(CRUD)
- 1proxy ๋ฌด๋ฃ ๋ง์ผํ๋ ์ด์ค
- ํ๋ก์ ์ํ
- ํ์ง ๋ฐฉ์ง ๋ฐ ์คํ ์ค
- ์ ์คํธ๋ฆผ ํ๋ก์ ๋ชจ๋
- ๋์๋ณด๋ UI
- API ์ฐธ์กฐ
- ํ๊ฒฝ ๋ณ์
- ๋ฌธ์ ํด๊ฒฐ
ํ๋ก์๋ฅผ ์ฌ์ฉํ๋ ์ด์
์น์ ์ ๋ชฉ: โํ๋ก์๋ฅผ ์ฌ์ฉํ๋ ์ด์ โ๋ง์ AI ์ ๊ณต์ ์ฒด๋ ์ง๋ฆฌ์ ์ง์ญ์ ๋ฐ๋ผ ์ก์ธ์ค๋ฅผ ์ ํํฉ๋๋ค. ๋ฌ์์, ์ค๊ตญ, ์ด๋, ์ฟ ๋ฐ, ํ๋ฅดํค์ ๋ฐ ๊ธฐํ ๊ตญ๊ฐ์ ๊ฐ๋ฐ์๋ ๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๋ฅผ ๊ฒช์ต๋๋ค.
unsupported_country_region_territory์ฐจ๋จ๋ ์ง์ญ์ด ์๋๋๋ผ๋ ํ๋ก์๋ ๋ค์๊ณผ ๊ฐ์ ์ฉ๋๋ก ์ ์ฉํฉ๋๋ค.
| ์ฌ์ฉ ์ฌ๋ก | ์ค๋ช |
|---|---|
| ์ง๋ฆฌ์ ์ฐจ๋จ ์ฐํ | ์ฐจ๋จ๋ ๊ตญ๊ฐ์์ OpenAI, Anthropic, Codex, Copilot์ ์ก์ธ์ค |
| IP ์ํ | ์๋ ์ ํ์ ๋ฐฉ์งํ๋๋ก ์ฌ๋ฌ IP์ ์์ฒญ์ ๋ถ์ฐ |
| ๊ฐ์ธ์ ๋ณด ๋ณดํธ | ์ ์คํธ๋ฆผ ์ ๊ณต์ ์ฒด๋ก๋ถํฐ ์ค์ IP๋ฅผ ์จ๊น |
| ๊ท์ ์ค์ | ํน์ ๊ดํ ๊ถ์ ํตํด ํธ๋ํฝ์ ๋ผ์ฐํ |
| ํ ์คํธ | ์๋ก ๋ค๋ฅธ ์ง์ญ์์ ๋ฐ์ํ ์์ฒญ์ ์๋ฎฌ๋ ์ด์ |
์ํคํ ์ฒ ๊ฐ์
์น์ ์ ๋ชฉ: โ์ํคํ ์ฒ ๊ฐ์โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ OmniRoute ์๋ฒ โโ โโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโ โ ํ๋ก์ โ โ ํ๋ก์ โ โ ํ๋ก์ โ โโ โ ๋ ์ง์คํธ๋ฆฌ โโโโโถโ ๋์คํจ์ฒ โโโโโถโ Fetch (undici) โ โโ โ (SQLite) โ โ (์บ์๋จ) โ โ โ โโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโโ โโ โฒ โ โโ โ โผ โโ โโโโโโโโดโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโ โ 1proxy ๋๊ธฐํโ โ ์
์คํธ๋ฆผ โ โโ โ (๋ฌด๋ฃ ํ) โ โ ์ ๊ณต์
์ฒด API โ โโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ์ฃผ์ ๊ตฌ์ฑ ์์
์น์ ์ ๋ชฉ: โ์ฃผ์ ๊ตฌ์ฑ ์์โ| ๊ตฌ์ฑ ์์ | ํ์ผ | ์ญํ |
|---|---|---|
| ํ๋ก์ ๋ ์ง์คํธ๋ฆฌ | src/lib/db/proxies.ts |
ํ๋ก์ ํญ๋ชฉ ๋ฐ ๋ฒ์ ํ ๋น์ ์ํ CRUD |
| ํ๋ก์ ๋์คํจ์ฒ | open-sse/utils/proxyDispatcher.ts |
์บ์ฑ์ ์ฌ์ฉํ์ฌ undici ProxyAgent/SOCKS ๋์คํจ์ฒ ์์ฑ |
| ํ๋ก์ Fetch | open-sse/utils/proxyFetch.ts |
ํ๋ก์ ๋์คํจ์ฒ๋ฅผ ์ฃผ์
ํ์ฌ fetch() ๋ํ |
| ์ค์ ๋ผ์ฐํธ | src/app/api/settings/proxy/route.ts |
๋ ๊ฑฐ์ ํ๋ก์ ๊ตฌ์ฑ API(GET/PUT/DELETE) |
| ๊ด๋ฆฌ ๋ผ์ฐํธ | src/app/api/v1/management/proxies/route.ts |
๋ ์ง์คํธ๋ฆฌ CRUD API(GET/POST/PATCH/DELETE) |
| 1proxy DB | src/lib/db/oneproxy.ts |
๋ฌด๋ฃ ํ๋ก์ ๋ง์ผํ๋ ์ด์ค ์์์ฑ |
4๋จ๊ณ ํ๋ก์ ์์คํ
์น์ ์ ๋ชฉ: โ4๋จ๊ณ ํ๋ก์ ์์คํ โOmniRoute๋ ์๋ก ๋ ๋ฆฝ์ ์ธ ๋ค ๊ฐ์ง ๋ฒ์์์ ํ๋ก์ ๊ตฌ์ฑ์ ์ง์ํ๋ฉฐ, ์ฐ์ ์์์ ๋ฐ๋ผ ๊ฒฐ์ ๋ฉ๋๋ค.
์ฐ์ ์์ ๊ฒฐ์ ์์(๋์ โ ๋ฎ์):
1. ๐ต ๊ณ์ /์ฐ๊ฒฐ ํ๋ก์ โ API ํค/OAuth ์ฐ๊ฒฐ๋ณ 2. ๐ก ์ ๊ณต์ ํ๋ก์ โ ์ ๊ณต์๋ณ(์: ๋ชจ๋ OpenAI ํธ๋ํฝ) 3. ๐ ์ฝค๋ณด ํ๋ก์ โ ์ฝค๋ณด/๋ผ์ฐํ
๊ตฌ์ฑ๋ณ 4. ๐ข ์ ์ญ ํ๋ก์ โ ๋ชจ๋ ํธ๋ํฝ, ๋ชจ๋ ์ ๊ณต์๊ฒฐ์ ๋ฐฉ์
์น์ ์ ๋ชฉ: โ๊ฒฐ์ ๋ฐฉ์โOmniRoute๊ฐ ์
์คํธ๋ฆผ ์ ๊ณต์์ ์์ฒญ์ ๋ณด๋ผ ๋ resolveProxyForConnectionFromRegistry()๋ฅผ ํธ์ถํ์ฌ ๊ฐ ๋จ๊ณ๋ฅผ ์์๋๋ก ํ์ธํฉ๋๋ค.
- ๊ณ์ ์์ค โ ์ด ํน์ ์ฐ๊ฒฐ ID์ ํ ๋น๋ ํ๋ก์๊ฐ ์๋๊ฐ?
- ์ ๊ณต์ ์์ค โ ์ด ์ ๊ณต์(์:
openai)์ ํ ๋น๋ ํ๋ก์๊ฐ ์๋๊ฐ? - ์ ์ญ ์์ค โ ๊ตฌ์ฑ๋ ์ ์ญ ํ๋ก์๊ฐ ์๋๊ฐ?
- ํ๋ก์ ์์ โ ์ ๊ณต์์ ์ง์ ์ฐ๊ฒฐํฉ๋๋ค.
๊ฐ์ฅ ๋จผ์ ์ผ์นํ๋ ํญ๋ชฉ์ด ์ฌ์ฉ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์ ์ญ ํ๋ก์๋ฅผ ๋์ฒด ์๋จ์ผ๋ก ์ค์ ํ๋ฉด์ ํน์ ์ ๊ณต์๋ ์ฐ๊ฒฐ์ ๋ํด ์ฌ์ ์ํ ์ ์์ต๋๋ค.
ํ๋ก์๋ฅผ ๊ฑฐ์น๋ ํญ๋ชฉ
์น์ ์ ๋ชฉ: โํ๋ก์๋ฅผ ๊ฑฐ์น๋ ํญ๋ชฉโ| ํธ๋ํฝ ์ ํ | ํ๋ก์ ์ฌ์ฉ ์ฌ๋ถ | ์ฐธ๊ณ |
|---|---|---|
| ์ฑํ ์์ฑ | โ | ๋ชจ๋ /v1/chat/completions ์์ฒญ |
| ์๋ฒ ๋ฉ | โ | /v1/embeddings |
| ์ด๋ฏธ์ง ์์ฑ | โ | /v1/images/generations |
| ์ค๋์ค(TTS/STT) | โ | /v1/audio/* |
| OAuth ํ ํฐ ๊ตํ | โ | unsupported_country_region_territory ํด๊ฒฐ |
| ์ฐ๊ฒฐ ํ ์คํธ | โ | โ์ฐ๊ฒฐ ํ ์คํธโ ๋ฒํผ์์ ํ๋ก์ ์ฌ์ฉ |
| ํ ํฐ ๊ฐฑ์ | โ | ๋ฐฑ๊ทธ๋ผ์ด๋ OAuth ๊ฐฑ์ |
| ๋ชจ๋ธ ๋๊ธฐํ | โ | ๋ชจ๋ธ ๋ชฉ๋ก ์กฐํ ๋ฐ ๊ฒ์ |
ํ๋ก์ ๋ ์ง์คํธ๋ฆฌ(CRUD)
์น์ ์ ๋ชฉ: โํ๋ก์ ๋ ์ง์คํธ๋ฆฌ(CRUD)โํ๋ก์ ๋ ์ง์คํธ๋ฆฌ๋ ๋ชจ๋ ํ๋ก์๋ฅผ ์ ์ฅํ๋ SQLite ํ
์ด๋ธ(proxy_registry)์
๋๋ค. ๊ฐ ํ๋ก์์๋ ๋ค์ ํ๋๊ฐ ์์ต๋๋ค.
| ํ๋ | ์ ํ | ์ค๋ช |
|---|---|---|
id |
UUID | ๊ณ ์ ์๋ณ์ |
name |
๋ฌธ์์ด | ์ฌ๋์ด ์ฝ์ ์ ์๋ ๋ ์ด๋ธ |
type |
๋ฌธ์์ด | ํ๋กํ ์ฝ: http, https, socks5 |
host |
๋ฌธ์์ด | ํ๋ก์ ํธ์คํธ ์ด๋ฆ ๋๋ IP |
port |
์ ์ | ํฌํธ ๋ฒํธ |
username |
๋ฌธ์์ด | ์ธ์ฆ ์ฌ์ฉ์ ์ด๋ฆ(์ ์ฅ ์ ์ํธํ) |
password |
๋ฌธ์์ด | ์ธ์ฆ ๋น๋ฐ๋ฒํธ(์ ์ฅ ์ ์ํธํ) |
region |
๋ฌธ์์ด | ์ง๋ฆฌ์ ์ง์ญ ๋ ์ด๋ธ |
notes |
๋ฌธ์์ด | ์์ ํ์ ๋ฉ๋ชจ |
status |
๋ฌธ์์ด | active ๋๋ inactive |
source |
๋ฌธ์์ด | manual ๋๋ oneproxy |
ํ๋ก์ ์์ฑ
์น์ ์ ๋ชฉ: โํ๋ก์ ์์ฑโ๋์๋ณด๋์์:
- ์ค์ โ ํ๋ก์๋ก ์ด๋ํฉ๋๋ค.
- ํ๋ก์ ์ถ๊ฐ๋ฅผ ํด๋ฆญํฉ๋๋ค.
- ์ ํ, ํธ์คํธ, ํฌํธ ๋ฐ ์ ํ์ ์ธ์ฆ ์๊ฒฉ ์ฆ๋ช ์ ์ ๋ ฅํฉ๋๋ค.
- ์ ์ฅํฉ๋๋ค.
API์์:
curl -X POST http://localhost:20128/api/v1/management/proxies \ -H "Content-Type: application/json" \ -d '{ "name": "US Proxy", "type": "http", "host": "proxy.example.com", "port": 8080, "username": "user", "password": "pass", "region": "US" }'ํ๋ก์ ์ ๋ฐ์ดํธ
์น์ ์ ๋ชฉ: โํ๋ก์ ์ ๋ฐ์ดํธโcurl -X PATCH http://localhost:20128/api/v1/management/proxies \ -H "Content-Type: application/json" \ -d '{ "id": "proxy-uuid-here", "host": "new-proxy.example.com", "port": 9090 }'์ฐธ๊ณ : ๋น์ด ์์ง ์์ ๋์ฒด ๊ฐ์ ๋ช ์์ ์ผ๋ก ๋ณด๋ด์ง ์๋ ํ ์๊ฒฉ ์ฆ๋ช ์ ์ ์ง๋ฉ๋๋ค.
username/password์ ๋น ๋ฌธ์์ด์ ๋ณด๋ด๋ฉด ์ ์ฅ๋ ๊ฐ์ด ์ ์ง๋ฉ๋๋ค.
ํ๋ก์ ์ญ์
์น์ ์ ๋ชฉ: โํ๋ก์ ์ญ์ โ# ํ๋ก์๊ฐ ์ด๋ค ๋ฒ์์๋ ํ ๋น๋์ด ์์ผ๋ฉด ์คํจcurl -X DELETE "http://localhost:20128/api/v1/management/proxies?id=proxy-uuid"
# ๊ฐ์ ์ญ์ (ํ ๋น๋ ํจ๊ป ์ ๊ฑฐ)curl -X DELETE "http://localhost:20128/api/v1/management/proxies?id=proxy-uuid&force=1"ํ๋ก์ ๋ชฉ๋ก ์กฐํ
์น์ ์ ๋ชฉ: โํ๋ก์ ๋ชฉ๋ก ์กฐํโcurl "http://localhost:20128/api/v1/management/proxies?limit=50&offset=0"๋ฒ์์ ํ๋ก์ ํ ๋น
์น์ ์ ๋ชฉ: โ๋ฒ์์ ํ๋ก์ ํ ๋นโ# ์ ์ญ ๋ฒ์์ ํ ๋นcurl -X PUT http://localhost:20128/api/settings/proxy \ -H "Content-Type: application/json" \ -d '{"level": "global", "proxy": {"type":"http","host":"proxy.example.com","port":8080}}'
# ํน์ ์ ๊ณต์์ ํ ๋นcurl -X PUT http://localhost:20128/api/settings/proxy \ -H "Content-Type: application/json" \ -d '{"level": "provider", "id": "openai", "proxy": {"type":"socks5","host":"socks.example.com","port":1080}}'
# ํน์ ์ฐ๊ฒฐ/ํค์ ํ ๋นcurl -X PUT http://localhost:20128/api/settings/proxy \ -H "Content-Type: application/json" \ -d '{"level": "key", "id": "connection-uuid", "proxy": {"type":"http","host":"key-proxy.com","port":3128}}'์ ํจ ํ๋ก์ ๊ฒฐ์
์น์ ์ ๋ชฉ: โ์ ํจ ํ๋ก์ ๊ฒฐ์ โ์ฃผ์ด์ง ์ฐ๊ฒฐ์ ์ด๋ค ํ๋ก์๊ฐ ์ฌ์ฉ๋๋์ง ํ์ธํฉ๋๋ค.
curl "http://localhost:20128/api/settings/proxy?resolve=connection-uuid"๊ฒฐ์ ๋ ํ๋ก์๋ฅผ ํด๋น ์์ค(account, provider ๋๋ global) ๋ฐ ์์ค์ ํจ๊ป ๋ฐํํฉ๋๋ค.
์ผ๊ด ํ ๋น
์น์ ์ ๋ชฉ: โ์ผ๊ด ํ ๋นโํ๋์ ํ๋ก์๋ฅผ ์ฌ๋ฌ ์ ๊ณต์ ๋๋ ์ฐ๊ฒฐ์ ํ ๋ฒ์ ํ ๋นํฉ๋๋ค.
curl -X POST http://localhost:20128/api/v1/management/proxies/bulk-assign \ -H "Content-Type: application/json" \ -d '{ "scope": "provider", "scopeIds": ["openai", "anthropic", "codex"], "proxyId": "proxy-uuid" }'๊ฐ์ ธ์ค๊ธฐ/๋ด๋ณด๋ด๊ธฐ
์น์ ์ ๋ชฉ: โ๊ฐ์ ธ์ค๊ธฐ/๋ด๋ณด๋ด๊ธฐโํ๋ก์๋ ๋ฐฑ์ /๋ณต์ ์์คํ ์ ํฌํจ๋ฉ๋๋ค. OmniRoute ๊ตฌ์ฑ์ ๋ด๋ณด๋ผ ๋๋ ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ฆ ๋๋ค.
- ๋์๋ณด๋ โ ์ค์ โ ๋ฐฑ์ ์ผ๋ก ์ด๋ํฉ๋๋ค.
- ๋ด๋ณด๋ด๊ธฐ๋ฅผ ํด๋ฆญํฉ๋๋ค. ํ๋ก์ ๋ ์ง์คํธ๋ฆฌ์ ํ ๋น์ด ํฌํจ๋ฉ๋๋ค.
- ๋ณต์ํ๋ ค๋ฉด ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ํด๋ฆญํ๊ณ ๋ฐฑ์ ํ์ผ์ ์ ๋ก๋ํฉ๋๋ค.
ํ๋ก์ ๋ ์ง์คํธ๋ฆฌ๋ host+port ๊ธฐ์ค upsert๋ ์ง์ํฉ๋๋ค. ์ด๋ฏธ ์กด์ฌํ๋ ํ๋ก์(ํธ์คํธ์ ํฌํธ๊ฐ ๋์ผํจ)๋ฅผ ๊ฐ์ ธ์ค๋ฉด ์ค๋ณต ํญ๋ชฉ์ ์์ฑํ๋ ๋์ ๊ธฐ์กด ํญ๋ชฉ์ ์ ๋ฐ์ดํธํฉ๋๋ค.
๋ ๊ฑฐ์ ๋ง์ด๊ทธ๋ ์ด์
์น์ ์ ๋ชฉ: โ๋ ๊ฑฐ์ ๋ง์ด๊ทธ๋ ์ด์ โ์ด์ ๋ฒ์ (๋ ์ง์คํธ๋ฆฌ ๋์ ์ )์์ ํ๋ก์๋ฅผ ๊ตฌ์ฑํ ๊ฒฝ์ฐ OmniRoute๊ฐ ํด๋น ํ๋ก์๋ฅผ ์๋์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์ ํฉ๋๋ค.
๋ ๊ฑฐ์ key_value ์ ์ฅ์ โ proxy_registry + proxy_assignments์
๊ทธ๋ ์ด๋ ํ ์ฒ์ ์์ํ ๋ ํ ๋ฒ ์คํ๋ฉ๋๋ค. ๋ค์ ์คํํ๋ ค๋ฉด migrateLegacyProxyConfigToRegistry({ force: true })๋ฅผ ์ฌ์ฉํ์ธ์.
1proxy ๋ฌด๋ฃ ํ๋ก์ ๋ง์ผํ๋ ์ด์ค
์น์ ์ ๋ชฉ: โ1proxy ๋ฌด๋ฃ ํ๋ก์ ๋ง์ผํ๋ ์ด์คโOmniRoute๋ 1proxy ์ปค๋ฎค๋ํฐ ํ๋ซํผ๊ณผ ํตํฉ๋์ด ์ ์ธ๊ณ์ ๊ฒ์ฆ๋ ๋ฌด๋ฃ ํ๋ก์ ์๋ฐฑ ๊ฐ์ ๋ํ ์ก์ธ์ค๋ฅผ ์ ๊ณตํฉ๋๋ค. ์์ฒด ํ๋ก์ ์ธํ๋ผ๊ฐ ์๋ ์ฌ์ฉ์์๊ฒ ์ ํฉํฉ๋๋ค.
์๋ ๋ฐฉ์
์น์ ์ ๋ชฉ: โ์๋ ๋ฐฉ์โโโโโโโโโโโโโโโโ ๋๊ธฐํ โโโโโโโโโโโโโโโโโโโ ์ํ โโโโโโโโโโโโโ 1proxy API โ โโโโโโโโโโโโโถ โ proxy_registry โ โโโโโโโโโโโโโถ โ ์ ๊ณต์ โโ (์ธ๋ถ) โ ์ต๋ 500๊ฐ โ source=oneproxy โ ํ์ง ๊ธฐ์ค โ API โโโโโโโโโโโโโโโโ ํ๋ก์ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโ- ๋๊ธฐํ โ OmniRoute๊ฐ 1proxy API์์ ๊ฒ์ฆ๋ ํ๋ก์๋ฅผ ๊ฐ์ ธ์ต๋๋ค
- ์ ์ฅ โ ํ๋ก์๋ ๋์ผํ
proxy_registryํ ์ด๋ธ์source = 'oneproxy'๋ก ์ ์ฅ๋ฉ๋๋ค - ํํฐ๋ง โ ํ๋กํ ์ฝ, ๊ตญ๊ฐ, ํ์ง ์ ์๋ณ๋ก ํํฐ๋งํฉ๋๋ค
- ์ํ โ ํ์ง, ๋ฌด์์ ๋๋ ์์ฐจ ์ ๋ต์ ์ฌ์ฉํ์ฌ ์ต์ ์ ํ๋ก์๋ฅผ ์ ํํฉ๋๋ค
- ์๋ ์ฑ๋ฅ ์ ํ ์ฒ๋ฆฌ โ ์คํจํ ํ๋ก์๋ ํ์ง ์ ์๊ฐ ๊ฐ์ํ๋ฉฐ, ์๊ณ๊ฐ ๋ฏธ๋ง์ด ๋๋ฉด โ ๋นํ์ฑ ์ํ๋ก ํ์๋ฉ๋๋ค
ํ๋ก์ ๋๊ธฐํ
์น์ ์ ๋ชฉ: โํ๋ก์ ๋๊ธฐํโ๋์๋ณด๋์์:
- Settings โ 1proxy ํญ์ผ๋ก ์ด๋ํฉ๋๋ค
- **โSync Nowโ**๋ฅผ ํด๋ฆญํฉ๋๋ค
- ์ ์ฒด ํ๋ก์ ์, ํ์ฑ ํ๋ก์ ์, ํ๊ท ํ์ง, ๊ตญ๊ฐ๋ณ ๋ถ์ ๋ฑ ํต๊ณ๋ฅผ ํ์ธํฉ๋๋ค
API๋ฅผ ํตํด:
# ๋๊ธฐํ ์คํcurl -X POST http://localhost:20128/api/settings/oneproxy \ -H "Content-Type: application/json" \ -d '{}'
# ์๋ต:# { "success": true, "added": 127, "updated": 45, "failed": 2, "total": 172 }ํ๋ก์ ํํฐ๋ง
์น์ ์ ๋ชฉ: โํ๋ก์ ํํฐ๋งโ# ํ๋กํ ์ฝ๋ณ ํํฐ๋งcurl "http://localhost:20128/api/settings/oneproxy?protocol=socks5"
# ๊ตญ๊ฐ๋ณ ํํฐ๋งcurl "http://localhost:20128/api/settings/oneproxy?countryCode=US"
# ์ต์ ํ์ง ์ ์๋ณ ํํฐ๋งcurl "http://localhost:20128/api/settings/oneproxy?minQuality=80"
# ํํฐ ์กฐํฉcurl "http://localhost:20128/api/settings/oneproxy?protocol=http&countryCode=DE&minQuality=70"ํ๋ก์ ํ์ง ์ ์
์น์ ์ ๋ชฉ: โํ๋ก์ ํ์ง ์ ์โ๊ฐ 1proxy ํ๋ก์์๋ ๋ค์๊ณผ ๊ฐ์ ๋ฉํ๋ฐ์ดํฐ๊ฐ ํฌํจ๋ฉ๋๋ค:
| ํ๋ | ์ค๋ช |
|---|---|
qualityScore |
1proxy ๊ฒ์ฆ์์ ๋ถ์ฌ๋ 0-100์ ํ์ |
latencyMs |
์ธก์ ๋ ๋คํธ์ํฌ ์ง์ฐ ์๊ฐ |
anonymity |
transparent, anonymous ๋๋ elite |
googleAccess |
ํ๋ก์์ Google ์๋น์ค ์ก์ธ์ค ๊ฐ๋ฅ ์ฌ๋ถ |
countryCode |
๋ ๊ธ์๋ก ๋ ISO ๊ตญ๊ฐ ์ฝ๋ |
lastValidated |
๋ง์ง๋ง ๊ฒ์ฆ ํ์์คํฌํ |
ํ์ง ์ ์๋ ๋์ ์ผ๋ก ์กฐ์ ๋ฉ๋๋ค:
- ์คํจํ ์์ฒญ์ ์ ์๋ฅผ 10์ ๊ฐ์์ํต๋๋ค
- ์ ์๊ฐ โค10์ผ๋ก ๊ฐ์ โ ํ๋ก์๊ฐ
inactive๋ก ํ์๋ฉ๋๋ค - ๋นํ์ฑ ํ๋ก์๋ ์ํ ๋์์์ ์ ์ธ๋ฉ๋๋ค
์ํ ์ ๋ต
์น์ ์ ๋ชฉ: โ์ํ ์ ๋ตโ# ํ์ง๋ณ ์ํ(์ต์์ ํ๋ก์ ์ฐ์ ) โ ๊ธฐ๋ณธ๊ฐcurl -X POST http://localhost:20128/api/settings/oneproxy/rotate \ -H "Content-Type: application/json" \ -d '{"strategy": "quality"}'
# ๋ฌด์์ ์ํcurl -X POST http://localhost:20128/api/settings/oneproxy/rotate \ -d '{"strategy": "random"}'
# ์์ฐจ ์ํ(๊ฐ์ฅ ์ค๋์ ์ ๊ฒ์ฆ๋ ํ๋ก์ ์ฐ์ )curl -X POST http://localhost:20128/api/settings/oneproxy/rotate \ -d '{"strategy": "sequential"}'์ํท ๋ธ๋ ์ด์ปค
์น์ ์ ๋ชฉ: โ์ํท ๋ธ๋ ์ด์ปคโ1proxy ๋๊ธฐํ์๋ ์ํท ๋ธ๋ ์ด์ปค๊ฐ ๋ด์ฅ๋์ด ์์ต๋๋ค:
- ๋๊ธฐํ๊ฐ 5ํ ์ฐ์ ์คํจํ๋ฉด ์ดํ์ ๋๊ธฐํ ์๋๊ฐ ์ฐจ๋จ๋ฉ๋๋ค
resetOneproxyCircuitBreaker()๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์๋ฒ๋ฅผ ์ฌ์์ํ์ฌ ์ด๊ธฐํํฉ๋๋ค- ๋๊ธฐํ ์ํ๋
GET /api/settings/oneproxy?action=status์์ ํ์ธํ ์ ์์ต๋๋ค
1proxy ํ๋ก์ ์ญ์
์น์ ์ ๋ชฉ: โ1proxy ํ๋ก์ ์ญ์ โ# ๋จ์ผ 1proxy ํ๋ก์ ์ญ์ curl -X DELETE "http://localhost:20128/api/settings/oneproxy?id=proxy-uuid"
# ๋ชจ๋ 1proxy ํ๋ก์ ์ญ์ (์๋ ํ๋ก์๋ ๊ทธ๋๋ก ์ ์ง๋จ)curl -X DELETE "http://localhost:20128/api/settings/oneproxy?clearAll=1"ํ์ง ๋ฐฉ์ง ๋ฐ ์คํ ์ค
์น์ ์ ๋ชฉ: โํ์ง ๋ฐฉ์ง ๋ฐ ์คํ ์คโOmniRoute๋ ๋จ์ํ ํ๋ก์๋ฅผ ํตํด ํธ๋ํฝ์ ๋ผ์ฐํ ํ๋ ๋ฐ ๊ทธ์น์ง ์๊ณ , ํธ๋ํฝ์ด ์ ์์ ์ธ ์์ฒญ์ฒ๋ผ ๋ณด์ด๋๋ก ๋ง๋ญ๋๋ค.
TLS ํ๊ฑฐํ๋ฆฐํธ ์คํธํ
์น์ ์ ๋ชฉ: โTLS ํ๊ฑฐํ๋ฆฐํธ ์คํธํโwreq-js๋ฅผ ์ฌ์ฉํ์ฌ ๋ธ๋ผ์ฐ์ ์ ์ ์ฌํ TLS ํ๊ฑฐํ๋ฆฐํธ๋ฅผ ์์ฑํจ์ผ๋ก์จ, ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ TLS ํธ๋์
ฐ์ดํฌ๋ฅผ ํ์งํ๋ ๋ด ๊ฐ์ง ์์คํ
์ ์ฐํํฉ๋๋ค.
CLI ํ๊ฑฐํ๋ฆฐํธ ์ผ์น
์น์ ์ ๋ชฉ: โCLI ํ๊ฑฐํ๋ฆฐํธ ์ผ์นโCLI ํ๊ฑฐํ๋ฆฐํธ ํ ๊ธ(์ค์ โ ๋ณด์)์ ๋ค์ดํฐ๋ธ CLI ๋ฐ์ด๋๋ฆฌ(Claude Code, Codex ๋ฑ)์ ์ ํํ ์๊ทธ๋์ฒ์ ์ผ์นํ๋๋ก HTTP ํค๋์ JSON ๋ณธ๋ฌธ ํ๋์ ์์๋ฅผ ์ฌ์ ๋ ฌํฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ํ๋ก์์ ํจ๊ป ์๋ํฉ๋๋ค.
์ฌ์ฉ์ IP(์ฐจ๋จ๋จ) โ ํ๋ก์ IP(๋ฏธ๊ตญ) โ ์ ๊ณต์ API + TLS ์คํธํ + CLI ํ๊ฑฐํ๋ฆฐํธ๋ฐ๋ผ์ IP ๋ง์คํน๊ณผ ์์ฒญ ์ ๋ขฐ์ฑ์ ๋์์ ํ๋ณดํ ์ ์์ต๋๋ค.
ํ๋ก์ IP ์ ์ง
์น์ ์ ๋ชฉ: โํ๋ก์ IP ์ ์งโ๋์๋ณด๋์ ์์ ๊ตฌ๋ถ ๋ฐฐ์ง๋ ํ์ฌ ํ์ฑํ๋ ํ๋ก์ ์์ค์ ๋ณด์ฌ์ค๋๋ค.
| ๋ฐฐ์ง | ์์ค | ์๋ฏธ |
|---|---|---|
| ๐ข | ์ ์ญ | ๋ชจ๋ ํธ๋ํฝ์ด ์ด ํ๋ก์๋ฅผ ํต๊ณผํจ |
| ๐ก | ์ ๊ณต์ | ์ด ์ ๊ณต์์ ํธ๋ํฝ๋ง ํ๋ก์๋ฅผ ํต๊ณผํจ |
| ๐ต | ์ฐ๊ฒฐ | ์ด ํน์ ํค/๊ณ์ ์ด ์ด ํ๋ก์๋ฅผ ์ฌ์ฉํจ |
๋ฐฐ์ง์๋ ๊ฒ์ฆ์ ์ํด ํ์ธ๋ ํ๋ก์ IP๋ ํ์๋ฉ๋๋ค.
์ ์คํธ๋ฆผ ํ๋ก์ ๋ชจ๋
์น์ ์ ๋ชฉ: โ์ ์คํธ๋ฆผ ํ๋ก์ ๋ชจ๋โCLIProxyAPI ํจํด์ ์ฌ์ฉํ๋ ์ ๊ณต์์ ๋ํด OmniRoute๋ ์ธ ๊ฐ์ง ์ ์คํธ๋ฆผ ํ๋ก์ ๋ชจ๋๋ฅผ ์ง์ํฉ๋๋ค.
| ๋ชจ๋ | ์ค๋ช |
|---|---|
native |
OmniRoute๊ฐ ํ๋ก์ ๋ผ์ฐํ ์ ์ง์ ์ฒ๋ฆฌํจ(๊ธฐ๋ณธ๊ฐ) |
cliproxyapi |
์ธ๋ถ CLIProxyAPI ์ธ์คํด์ค์ ์ฒ๋ฆฌ๋ฅผ ์์ํจ |
fallback |
๋จผ์ ๋ค์ดํฐ๋ธ ๋ฐฉ์์ ์๋ํ ํ CLIProxyAPI๋ก ๋์ฒดํจ |
์ ๊ณต์๋ณ๋ก ๊ตฌ์ฑํฉ๋๋ค.
curl -X PUT "http://localhost:20128/api/upstream-proxy/openai" \ -H "Content-Type: application/json" \ -d '{"mode": "native", "enabled": true}'๋์๋ณด๋ UI
์น์ ์ ๋ชฉ: โ๋์๋ณด๋ UIโ์ค์ โ ํ๋ก์ ํญ
์น์ ์ ๋ชฉ: โ์ค์ โ ํ๋ก์ ํญโ- ์ ์ญ ํ๋ก์ ๊ตฌ์ฑ(๋ชจ๋ ํธ๋ํฝ์ ๋ํด ํ ๋ฒ๋ง ์ค์ )
- ์ ๊ณต์๋ณ ํ๋ก์ ์ฌ์ ์
- ์ฐ๊ฒฐ๋ณ ํ๋ก์ ํ ๋น
- ๊ตฌ์ฑ๋ ํ๋ก์๋ฅผ ํตํ ์ฐ๊ฒฐ ํ ์คํธ
- ํ์ฑ ํ๋ก์ ์์ค์ ๋ณด์ฌ์ฃผ๋ ์์ ๊ตฌ๋ถ ๋ฐฐ์ง
์ค์ โ 1proxy ํญ
์น์ ์ ๋ชฉ: โ์ค์ โ 1proxy ํญโ- ๋ฌด๋ฃ ํ๋ก์๋ฅผ ๊ฐ์ ธ์ค๋ ์ง๊ธ ๋๊ธฐํ ๋ฒํผ
- ํต๊ณ ์นด๋: ์ ์ฒด, ํ์ฑ, ํ๊ท ํ์ง, ๋ง์ง๋ง ๋๊ธฐํ
- ํํฐ: ํ๋กํ ์ฝ, ๊ตญ๊ฐ ์ฝ๋, ์ต์ ํ์ง
- ํธ์คํธ, ํ๋กํ ์ฝ, ๊ตญ๊ฐ, ํ์ง ์ ์, ์ง์ฐ ์๊ฐ, ์ต๋ช ์ฑ, Google ์ ๊ทผ ๊ฐ๋ฅ ์ฌ๋ถ๋ฅผ ํ์ํ๋ ํ๋ก์ ํ ์ด๋ธ
- ์ฑ๊ณต/์คํจ ์ถ์ ๋ฐ ์ฐ์ ์คํจ ํ์๋ฅผ ํ์ํ๋ ๋๊ธฐํ ์ํ ํจ๋
- ๋ชจ๋ 1proxy ํญ๋ชฉ์ ์ ๊ฑฐํ๋ ๋ชจ๋ ์ง์ฐ๊ธฐ
API ์ฐธ์กฐ
์น์ ์ ๋ชฉ: โAPI ์ฐธ์กฐโํ๋ก์ ์ค์ API
์น์ ์ ๋ชฉ: โํ๋ก์ ์ค์ APIโ| ๋ฉ์๋ | ์๋ํฌ์ธํธ | ์ค๋ช |
|---|---|---|
GET |
/api/settings/proxy |
์ ์ฒด ํ๋ก์ ๊ตฌ์ฑ ๊ฐ์ ธ์ค๊ธฐ |
GET |
/api/settings/proxy?level=global |
์ ์ญ ํ๋ก์ ๊ฐ์ ธ์ค๊ธฐ |
GET |
/api/settings/proxy?level=provider&id=openai |
์ ๊ณต์ ํ๋ก์ ๊ฐ์ ธ์ค๊ธฐ |
GET |
/api/settings/proxy?resolve=connectionId |
์ ํจ ํ๋ก์ ํ์ธํ๊ธฐ |
PUT |
/api/settings/proxy |
ํ๋ก์ ๊ตฌ์ฑ ์ ๋ฐ์ดํธํ๊ธฐ |
DELETE |
/api/settings/proxy?level=provider&id=openai |
ํด๋น ์์ค์ ํ๋ก์ ์ ๊ฑฐํ๊ธฐ |
ํ๋ก์ ๋ ์ง์คํธ๋ฆฌ API
์น์ ์ ๋ชฉ: โํ๋ก์ ๋ ์ง์คํธ๋ฆฌ APIโ| ๋ฉ์๋ | ์๋ํฌ์ธํธ | ์ค๋ช |
|---|---|---|
GET |
/api/v1/management/proxies |
๋ชจ๋ ํ๋ก์ ๋์ดํ๊ธฐ |
GET |
/api/v1/management/proxies?id=uuid |
ID๋ก ํ๋ก์ ๊ฐ์ ธ์ค๊ธฐ |
GET |
/api/v1/management/proxies?id=uuid&where_used=1 |
ํ๋ก์ ํ ๋น ๊ฐ์ ธ์ค๊ธฐ |
POST |
/api/v1/management/proxies |
ํ๋ก์ ์์ฑํ๊ธฐ |
PATCH |
/api/v1/management/proxies |
ํ๋ก์ ์ ๋ฐ์ดํธํ๊ธฐ |
DELETE |
/api/v1/management/proxies?id=uuid |
ํ๋ก์ ์ญ์ ํ๊ธฐ |
DELETE |
/api/v1/management/proxies?id=uuid&force=1 |
๊ฐ์ ๋ก ์ญ์ ํ๊ธฐ |
POST |
/api/v1/management/proxies/bulk-assign |
์ผ๊ด ํ ๋นํ๊ธฐ |
GET |
/api/v1/management/proxies/assignments |
ํ ๋น ๋ชฉ๋ก ๊ฐ์ ธ์ค๊ธฐ |
GET |
/api/v1/management/proxies/health |
ํ๋ก์ ์ํ ํต๊ณ ๊ฐ์ ธ์ค๊ธฐ |
ํฐ๋ API
์น์ ์ ๋ชฉ: โํฐ๋ APIโํ๋ก์๋ฅผ ํตํด ์์๋ฐ์ด๋ ํธ๋ํฝ์ ๋ผ์ฐํ
ํ๋ ๋์ OmniRoute ์ธ์คํด์ค๋ฅผ ๊ณต์ฉ ์ธํฐ๋ท์ ๋
ธ์ถํ๋ ค๋ฉด(Cloudflare/ngrok/Tailscale) TUNNELS_GUIDE.md๋ฅผ ์ฐธ์กฐํ์ธ์. ํฐ๋ REST API๋ /api/tunnels/{cloudflared,ngrok,tailscale}/* ์๋์ ์์ผ๋ฉฐ, ์์์ ์ค๋ช
ํ ์์๋ฐ์ด๋ ํ๋ก์ ์ฒด์ธ๊ณผ๋ ๋ณ๊ฐ์
๋๋ค.
1proxy API
์น์ ์ ๋ชฉ: โ1proxy APIโ| ๋ฉ์๋ | ์๋ํฌ์ธํธ | ์ค๋ช |
|---|---|---|
GET |
/api/settings/oneproxy |
1proxy ํ๋ก์ ๋์ดํ๊ธฐ |
GET |
/api/settings/oneproxy?action=stats |
ํต๊ณ ๋ฐ ๋๊ธฐํ ์ํ ๊ฐ์ ธ์ค๊ธฐ |
GET |
/api/settings/oneproxy?action=status |
๋๊ธฐํ ์ํ๋ง ๊ฐ์ ธ์ค๊ธฐ |
POST |
/api/settings/oneproxy |
๋๊ธฐํ ์คํํ๊ธฐ |
POST |
/api/settings/oneproxy/rotate |
๋ค์ ํ๋ก์๋ก ์ ํํ๊ธฐ |
DELETE |
/api/settings/oneproxy?id=uuid |
ํ๋ ์ญ์ ํ๊ธฐ |
DELETE |
/api/settings/oneproxy?clearAll=1 |
๋ชจ๋ ์ง์ฐ๊ธฐ |
์ ์คํธ๋ฆผ ํ๋ก์ API
์น์ ์ ๋ชฉ: โ์ ์คํธ๋ฆผ ํ๋ก์ APIโ| ๋ฉ์๋ | ์๋ํฌ์ธํธ | ์ค๋ช |
|---|---|---|
GET |
/api/upstream-proxy/:providerId |
์ ์คํธ๋ฆผ ํ๋ก์ ๊ตฌ์ฑ ๊ฐ์ ธ์ค๊ธฐ |
PUT |
/api/upstream-proxy/:providerId |
์ ์คํธ๋ฆผ ํ๋ก์ ๋ชจ๋ ์ค์ ํ๊ธฐ |
DELETE |
/api/upstream-proxy/:providerId |
์ ์คํธ๋ฆผ ํ๋ก์ ๊ตฌ์ฑ ์ ๊ฑฐํ๊ธฐ |
ํ๊ฒฝ ๋ณ์
์น์ ์ ๋ชฉ: โํ๊ฒฝ ๋ณ์โ| ๋ณ์ | ๊ธฐ๋ณธ๊ฐ | ์ค๋ช |
|---|---|---|
ENABLE_SOCKS5_PROXY |
true |
SOCKS5 ํ๋ก์ ์ง์ ํ์ฑํ(.env.example์ ๊ธฐ๋ณธ๊ฐ์ true) |
๋ฌธ์ ํด๊ฒฐ
์น์ ์ ๋ชฉ: โ๋ฌธ์ ํด๊ฒฐโโSOCKS5 proxy is disabledโ
์น์ ์ ๋ชฉ: โโSOCKS5 proxy is disabledโโ.env ํ์ผ์์ ENABLE_SOCKS5_PROXY=true๋ก ์ค์ ํ๊ณ ๋ค์ ์์ํ์ธ์.
ํ๋ก์๋ฅผ ํตํ โsocket hang upโ ์ค๋ฅ
์น์ ์ ๋ชฉ: โํ๋ก์๋ฅผ ํตํ โsocket hang upโ ์ค๋ฅโ์ ํด ์ฐ๊ฒฐ์ ๋๋ ์ ๊ฐํ ํ๋ก์์์๋ ์ ์์ ์ผ๋ก ๋ฐ์ํ ์ ์์ต๋๋ค. OmniRoute๋ ์ด๋ฏธ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ด๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
- ํ๋ก์ ์ฐ๊ฒฐ์์ keep-alive ๋นํ์ฑํ(
keepAliveTimeout: 1) - ํ์ดํ๋ผ์ด๋ ๋นํ์ฑํ(
pipelining: 0) - ๋ฐ๋ณต์ ์ธ ํธ๋์ ฐ์ดํฌ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๋์คํจ์ฒ ์บ์ฑ
๋ฌธ์ ๊ฐ ๊ณ์๋๋ฉด ๋ค๋ฅธ ํ๋ก์๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ 1proxy ๋กํ ์ด์ ๊ธฐ๋ฅ์ ์ฌ์ฉํด ๋ณด์ธ์.
OAuth ์ค โunsupported_country_region_territoryโ
์น์ ์ ๋ชฉ: โOAuth ์ค โunsupported_country_region_territoryโโOAuth ํ๋ฆ์ ์์ํ๊ธฐ ์ ์ ํ๋ก์๊ฐ ๊ตฌ์ฑ๋์ด ์๋์ง ํ์ธํ์ธ์. OmniRoute๋ ๊ตฌ์ฑ๋ ํ๋ก์๋ฅผ ํตํด OAuth ํ ํฐ ๊ตํ์ ๋ผ์ฐํ ํฉ๋๋ค. ๋จผ์ ์ ์ญ ๋๋ ๊ณต๊ธ์ ์์ค ํ๋ก์๋ฅผ ์ค์ ํ ๋ค์ ์ฐ๊ฒฐํ์ธ์.
ํ๋ก์๊ฐ ์ฌ์ฉ๋์ง ์์
์น์ ์ ๋ชฉ: โํ๋ก์๊ฐ ์ฌ์ฉ๋์ง ์์โํ์ธ ์์๋ฅผ ์ ๊ฒํ์ธ์.
GET /api/settings/proxy?resolve=your-connection-id๋ก ํ์ธ- ํ๋ก์
status๊ฐactive์ธ์ง ํ์ธ(inactive๊ฐ ์๋์ด์ผ ํจ) - ํ๋ก์ ํ ๋น ๋ฒ์๊ฐ ์ฐ๊ฒฐ๊ณผ ์ผ์นํ๋์ง ํ์ธ
1proxy ๋๊ธฐํ ์คํจ
์น์ ์ ๋ชฉ: โ1proxy ๋๊ธฐํ ์คํจโ๋๊ธฐํ ์ํ๋ฅผ ํ์ธํ์ธ์.
curl "http://localhost:20128/api/settings/oneproxy?action=status"consecutiveFailures >= 5์ด๋ฉด ํ๋ก ์ฐจ๋จ๊ธฐ๊ฐ ์๋ํ ๊ฒ์
๋๋ค. ์๋ฒ๋ฅผ ๋ค์ ์์ํ์ฌ ์ด๊ธฐํํ๊ฑฐ๋ ์๋์ผ๋ก ์ด๊ธฐํ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ธ์.
๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง
์น์ ์ ๋ชฉ: โ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋งโproxy_registry ํ
์ด๋ธ
์น์
์ ๋ชฉ: โproxy_registry ํ
์ด๋ธโCREATE TABLE proxy_registry ( id TEXT PRIMARY KEY, name TEXT NOT NULL, type TEXT NOT NULL DEFAULT 'http', host TEXT NOT NULL, port INTEGER NOT NULL, username TEXT DEFAULT '', password TEXT DEFAULT '', region TEXT, notes TEXT, status TEXT DEFAULT 'active', source TEXT NOT NULL DEFAULT 'manual', -- 'manual' ๋๋ 'oneproxy' quality_score INTEGER, -- 0-100(1proxy ์ ์ฉ) latency_ms INTEGER, -- ๋ฐ๋ฆฌ์ด(1proxy ์ ์ฉ) anonymity TEXT, -- ํฌ๋ช
/์ต๋ช
/์๋ฆฌํธ google_access INTEGER DEFAULT 0, -- Google์ ์ก์ธ์คํ ์ ์๋๊ฐ? (1proxy) last_validated TEXT, -- ISO ํ์์คํฌํ(1proxy) country_code TEXT, -- ISO 2์๋ฆฌ ์ฝ๋(1proxy) created_at TEXT NOT NULL, updated_at TEXT NOT NULL);proxy_assignments ํ
์ด๋ธ
์น์
์ ๋ชฉ: โproxy_assignments ํ
์ด๋ธโCREATE TABLE proxy_assignments ( id INTEGER PRIMARY KEY AUTOINCREMENT, proxy_id TEXT NOT NULL REFERENCES proxy_registry(id), scope TEXT NOT NULL, -- 'global', 'provider', 'account', 'combo' scope_id TEXT, -- ๊ณต๊ธ์ ID, ์ฐ๊ฒฐ ID ๋๋ ์กฐํฉ ID created_at TEXT NOT NULL, updated_at TEXT NOT NULL, UNIQUE(scope, scope_id));ํ๋ก์ ์ํ ํ์ธ(v3.8.16+)
์น์ ์ ๋ชฉ: โํ๋ก์ ์ํ ํ์ธ(v3.8.16+)โOmniRoute์ ํ๋ก์ ๋น ๋ฅธ ์คํจ ๋ฉ์ปค๋์ฆ(src/lib/proxyHealth.ts)์ ๋น ๋ฅธ TCP ์ฐ๊ฒฐ ๊ฒ์ฌ๋ฅผ ํตํด 2์ด ์ด๋ด์ ์๋ํ์ง ์๋ ํ๋ก์๋ฅผ ๊ฐ์งํ ๋ค์, ์์ฒญ๋ณ ์ค๋ฒํค๋๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๊ฒฐ๊ณผ๋ฅผ ์บ์ฑํฉ๋๋ค.
์๋ ๋ฐฉ์
์น์ ์ ๋ชฉ: โ์๋ ๋ฐฉ์โ์์ฒญ โโโถ ProxyHealthCache.get(url) โ โโ ์บ์ ์ ์ค + ์ต์ ์ํ? โโโถ ์บ์๋ ์ํ ๋ฐํ โ โโ ์บ์ ๋๋ฝ / ์ค๋๋ ์ํ? โโโถ host:port์ TCP ์ฐ๊ฒฐ (์ ํ ์๊ฐ: FAST_FAIL_TIMEOUT_MS) โโโถ HEALTH_CACHE_TTL_MS ๋์ ์บ์ฑ โโโถ ๊ฒฐ๊ณผ ๋ฐํ์ด ๊ธฐ๋ฅ์ด ์์ผ๋ฉด ์๋ํ์ง ์๋ ํ๋ก์๋ก ์ธํด ๋ชจ๋ ์์ฒญ์ด ์คํจํ๊ธฐ ์ ๊น์ง ์ ์ฒด PROXY_TIMEOUT_MS(๊ธฐ๋ณธ๊ฐ 30์ด) ๋์ ์ฐจ๋จ๋ฉ๋๋ค.
์กฐ์ ๊ฐ๋ฅํ ํ๊ฒฝ ๋ณ์
์น์ ์ ๋ชฉ: โ์กฐ์ ๊ฐ๋ฅํ ํ๊ฒฝ ๋ณ์โ| ๋ณ์ | ๊ธฐ๋ณธ๊ฐ | ์ฉ๋ |
|---|---|---|
PROXY_FAST_FAIL_TIMEOUT_MS |
2000 |
์ํ ํ์ธ๋น TCP ์ฐ๊ฒฐ ์ ํ ์๊ฐ |
PROXY_HEALTH_CACHE_TTL_MS |
30000 |
์ํ ๊ฒฐ๊ณผ๊ฐ ์บ์ฑ๋๋ ๊ธฐ๊ฐ |
๊ถ์ฅ ๊ฐ:
| ์๋๋ฆฌ์ค | ๋น ๋ฅธ ์คํจ ์ ํ ์๊ฐ | ์บ์ TTL | ๊ทผ๊ฑฐ |
|---|---|---|---|
| ์ฒ๋ฆฌ๋์ด ๋์ API ๊ฒ์ดํธ์จ์ด | 1500ms | 60000ms | ์ ๊ทน์ ์ธ ๋น ๋ฅธ ์คํจ, ๊ฒ์ฌ ํ์๋ฅผ ์ค์ด๊ธฐ ์ํ ๋ ๊ธด ์บ์ |
| ์ง๋ฆฌ์ ์ผ๋ก ๋ถ์ฐ๋ ๋ ธ๋ | 3000ms | 15000ms | ๋๋ฆฐ ๋คํธ์ํฌ์๋ ๋ ๋ง์ ์๊ฐ์ด ํ์ํ๋ฉฐ, ๋น ๋ฅธ ์ฅ์ ์กฐ์น๋ฅผ ์ํด ๋ ์งง์ ์บ์ ์ฌ์ฉ |
| ๊ฐ๋ฐ / ํ ์คํธ | 1000ms | 10000ms | ๋ก์ปฌ ํ๋ก์์์ ๋น ๋ฅด๊ฒ ๋ฐ๋ณต ์์ |
| ์คํ ์ค / ํ์ง ๋ฐฉ์ง | 2500ms | 45000ms | ์๋ ์ ํ์ ์ ๋ฐํ ์ ์๋ ๋น ๋ฅธ ํ์ ๋ฐฉ์ง |
ํ๋ก์ ์ํ ๊ฒ์ฌ
์น์ ์ ๋ชฉ: โํ๋ก์ ์ํ ๊ฒ์ฌโimport { getAllProxyHealthStatuses, invalidateProxyHealth } from "omniroute/proxyHealth";
const statuses = getAllProxyHealthStatuses();for (const s of statuses) { console.log(`${s.proxyUrl} โ healthy=${s.healthy}, stale=${s.stale}`);}
// ํน์ ํ๋ก์ ๊ฐ์ ์ฌ๊ฒ์ฌinvalidateProxyHealth("http://user:pass@203.0.113.7:8080");์บ์ ํญ๋ชฉ์ด HEALTH_CACHE_TTL_MS๋ฅผ ์ด๊ณผํ์ฌ ๋ค์ ์์ฒญ์์ ์๋ก์ด ๊ฒ์ฌ๊ฐ ์คํ๋ ๊ฒฝ์ฐ stale ํ๋๊ทธ๋ true์
๋๋ค.
ํ๋ก์ ์ ํ๋ณ ๊ธฐ๋ณธ๊ฐ
์น์ ์ ๋ชฉ: โํ๋ก์ ์ ํ๋ณ ๊ธฐ๋ณธ๊ฐโ์ํ ํ์ธ์ URL ์คํด์ ๋ฐ๋ผ ์ ์ ํ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํฉ๋๋ค.
| ์คํด | ๊ธฐ๋ณธ ํฌํธ |
|---|---|
http:// |
8080 |
https:// |
443 |
socks5:// / socks5h:// |
1080 |
URL์ ์ฌ์ฉ์ ์ง์ ํฌํธ(http://host:9999)๋ ํญ์ ์คํด ๊ธฐ๋ณธ๊ฐ๋ณด๋ค ์ฐ์ ํฉ๋๋ค.
ํ๋ก์ ๋ถ์ ๋ฐ ๊ด์ธก์ฑ
์น์ ์ ๋ชฉ: โํ๋ก์ ๋ถ์ ๋ฐ ๊ด์ธก์ฑโOmniRoute๋ ์ด์์๊ฐ ๋ผ์ฐํ ํจํด, ์ง์ฐ ์๊ฐ ๊ธ์ฆ ๋ฐ ๋ฐ๋ณต๋๋ ์ฅ์ ๋ฅผ ์ง๋จํ ์ ์๋๋ก ํ๋ก์๋ณ ์ฌ์ฉ๋์ ์ถ์ ํฉ๋๋ค.
์ถ์ ๋๋ ํญ๋ชฉ
์น์ ์ ๋ชฉ: โ์ถ์ ๋๋ ํญ๋ชฉโ์ค์ ๋ ํ๋ก์๋ฅผ ํต๊ณผํ๋ ๋ชจ๋ ์์ฒญ์ ๋ํด OmniRoute๋ ๋ค์์ ๊ธฐ๋กํฉ๋๋ค.
| ๋ฉํธ๋ฆญ | ์ค๋ช |
|---|---|
proxy_url |
์ ์ฒด ํ๋ก์ URL(์ธ์ฆ ์๊ฒฉ ์ฆ๋ช ์ ๋ง์คํน๋จ) |
provider |
์ ์คํธ๋ฆผ ์ ๊ณต์ ID(openai, anthropic ๋ฑ) |
latency_ms |
ํ๋ก์ ํธ๋์ ฐ์ดํฌ๋ฅผ ํฌํจํ ์ ์ฒด ์๋ณต ์๊ฐ |
connect_ms |
TCP ์ฐ๊ฒฐ ์๊ฐ๋ง |
status |
์ ์คํธ๋ฆผ์์ ๋ฐํ๋ HTTP ์ํ ์ฝ๋ |
error |
์์ฒญ์ด ์คํจํ ๊ฒฝ์ฐ ์ค๋ฅ ํด๋์ค |
timestamp |
ISO 8601 UTC |
๋ฐ์ดํฐ ์ก์ธ์ค
์น์ ์ ๋ชฉ: โ๋ฐ์ดํฐ ์ก์ธ์คโ# ์ต๊ทผ ํ๋ก์ ์ด๋ฒคํธcurl -H "Authorization: Bearer $OMNIROUTE_KEY" \ "http://localhost:20128/api/usage/proxy-logs?limit=100"์ค์ ์๋ํฌ์ธํธ๋ /api/usage/proxy-logs์
๋๋ค(src/app/api/usage/proxy-logs/route.ts ์ฐธ์กฐ). ์ด ์๋ํฌ์ธํธ๋ ๋ค์์ ์ง์ํฉ๋๋ค.
GET /api/usage/proxy-logsโ ํ๋ก์ ๋ก๊ทธ ์กฐํDELETE /api/usage/proxy-logsโ ๋ชจ๋ ํ๋ก์ ๋ก๊ทธ ์ญ์
ํ์ํ ๊ฒฝ์ฐ SQL์ ํตํด proxy_logs ํ
์ด๋ธ์์ ์ง๊ณ ํต๊ณ๋ฅผ ์ง์ ์กฐํํ ์ ์์ต๋๋ค. ๋์๋ณด๋ UI์์๋ ์ง๊ณ ๋ณด๊ธฐ๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค.
์ผ๋ฐ์ ์ธ ํจํด
์น์ ์ ๋ชฉ: โ์ผ๋ฐ์ ์ธ ํจํดโ๋ถ์์ ํ ํ๋ก์ ๊ฐ์ง(์ฑ๊ณต๊ณผ ์คํจ๊ฐ ๋ฒ๊ฐ์ ๋ฐ์ํ๋ ๊ฒฝ์ฐ):
SELECT proxy_url, COUNT(*) AS total, SUM(CASE WHEN status >= 500 THEN 1 ELSE 0 END) AS errors, ROUND(100.0 * SUM(CASE WHEN status >= 500 THEN 1 ELSE 0 END) / COUNT(*), 1) AS error_pctFROM proxy_logsWHERE timestamp > datetime('now', '-1 hour')GROUP BY proxy_urlHAVING error_pct > 5ORDER BY error_pct DESC;๋๋ฆฐ ํ๋ก์ ์ฐพ๊ธฐ(p95 ์ง์ฐ ์๊ฐ > 2์ด):
WITH ranked AS ( SELECT proxy_url, latency_ms, PERCENT_RANK() OVER (PARTITION BY proxy_url ORDER BY latency_ms) AS pct FROM proxy_logs WHERE timestamp > datetime('now', '-24 hour'))SELECT proxy_url, latency_msFROM rankedWHERE pct >= 0.95ORDER BY latency_ms DESC;๋กํ ์ด์ ์ ๋ต ์์ฌ ๊ฒฐ์ ํธ๋ฆฌ
์น์ ์ ๋ชฉ: โ๋กํ ์ด์ ์ ๋ต ์์ฌ ๊ฒฐ์ ํธ๋ฆฌโ์ฌ๋ฌ ํ๋ก์๊ฐ ํ๋์ ๋ฒ์์ ํ ๋น๋๋ฉด OmniRoute๋ ๊ฐ ์์ฒญ์ ์ฌ์ฉํ ํ๋ก์๋ฅผ ์ ํํ๊ธฐ ์ํด ๋กํ ์ด์ ์ ๋ต์ ์ฌ์ฉํฉ๋๋ค. ์ ๋ต์ ๋ฒ์ ์์ค(์ ์ญ, ์ ๊ณต์๋ณ, ๊ณ์ ๋ณ, ์กฐํฉ๋ณ)์์ ์ค์ ๋ฉ๋๋ค.
์ฌ์ฉ ๊ฐ๋ฅํ ์ ๋ต
์น์ ์ ๋ชฉ: โ์ฌ์ฉ ๊ฐ๋ฅํ ์ ๋ตโ| ์ ๋ต | ์ฌ์ฉ ์์ | ์ฅ๋จ์ |
|---|---|---|
quality (๊ธฐ๋ณธ๊ฐ) |
ํ์ง์ด ์๋ก ๋ค๋ฅธ ํ๋ก์๋ฅผ ์ฌ์ฉํ๋ ํ๋ก๋์ | ํ์ ์ด ๋์ ํ๋ก์๋ฅผ ์ ํธํ๋ฉฐ, ๋ฎ์ ํ๋ก์๋ ๋ฐฐ์ ๋ ์ ์์ |
random |
๋ถํ ๋ถ์ฐ, ๊ฐ์ธ์ ๋ณด ๋ณดํธ | ๊ณ ๋ฅด๊ฒ ๋ถ์ฐ๋์ง๋ง ํ์ง ์ ํธ๋ฅผ ๋ฌด์ํจ |
sequential |
๋๋ฒ๊น , ๊ฒฐ์ ๋ก ์ ํ ์คํธ | ํ๋ก์๋ฅผ ์์๋๋ก ์ํํ๋ฏ๋ก ๋์์ ์ดํดํ๊ธฐ ์ฌ์ |
์์ฌ ๊ฒฐ์ ํธ๋ฆฌ
์น์ ์ ๋ชฉ: โ์์ฌ ๊ฒฐ์ ํธ๋ฆฌโ ํ๋ก์์ ํ์ง ์ ์๊ฐ ์์ต๋๊น? โ โโโโโโโโโโโโโดโโโโโโโโโโโโ โ โ ์ ์๋์ โ โ ๋ชจ๋ ํ๋ก์์ โ ํ์ง์ด ๋์ฒด๋ก โ ๋์ผํฉ๋๊น? โ โ โ โโโโโโดโโโโโ โ โ โ โ ์ ์๋์ ์ฌ์ฉ โ โ `random` โ โ (๊ณ ๋ฅด๊ฒ ๋ถ์ฐํ์ฌ โ โ ์๊ฐ์ ๋ฐ๋ผ ํ์ง โ โ ๋ฐ์ดํฐ ์ถ์ ) โ โ โ `quality` ์ฌ์ฉ โ (์๋ก ๋ค๋ฅธ ํ์ง์ โ ๊ฐ์ฅ ์ ํฉ) โ`random` ์ฌ์ฉ(๋ถํ๋ฅผ ๊ณ ๋ฅด๊ฒ๋ถ์ฐ)์์ฒด ํ๋ก์์ ์๋ ์ฅ์ ์ ์ธ
์น์ ์ ๋ชฉ: โ์์ฒด ํ๋ก์์ ์๋ ์ฅ์ ์ ์ธโ1proxy ๋ง์ผํ๋ ์ด์ค ํ์ ์ด๋ฏธ ์คํจํ ํ๋ก์์ ๋ฑ๊ธ์ ์์ฒด์ ์ผ๋ก ์๋ ํํฅ ์กฐ์ ํฉ๋๋ค(ํ๋ก์ ํ์ง ์ ์ ์ฐธ์กฐ). ๋ ์ง์คํธ๋ฆฌ์ ์ง์ ์ถ๊ฐํ ํ๋ก์์ ๊ฒฝ์ฐ, ๋ฐฑ๊ทธ๋ผ์ด๋ ์ํ ์ค์ผ์ค๋ฌ(src/lib/proxyHealth/scheduler.ts)๊ฐ ์๋ฌด๊ฒ๋ ์ญ์ ํ์ง ์์ผ๋ฉด์ ๋์ผํ โ์๋ํ์ง ์๋ ๊ตฌ์ฑ์์ ์ฒด์ธ์์ ์๋ ์ ์ธโํ๋ ๋์์ ์ ๊ณตํฉ๋๋ค.
# .env โ ์ฐ์๋ ํ๋ก๋ธ๊ฐ 3๋ฒ ์คํจํ๋ฉด ํ๋ก์๋ฅผ ์ผ์์ ์ผ๋ก ๋นํ์ฑํํ๊ณ ,# ํ๋ก๋ธ์ ๋ค์ ์๋ตํ๊ธฐ ์์ํ๋ฉด ์๋์ผ๋ก ๋ค์ ํ์ฑํํฉ๋๋ค.PROXY_AUTO_DISABLE=truePROXY_AUTO_REMOVE_AFTER=3๋ค์ค ํ๋ก์ ์ฒด์ธ์์ ์๋ํ๋ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ์ค์ผ์ค๋ฌ๋ ๋ฑ๋ก๋ ๋ชจ๋ ํ๋ก์๋ฅผ
PROXY_HEALTH_INTERVAL_MS๊ฐ๊ฒฉ์ผ๋ก ํ๋ก๋ธํฉ๋๋ค (๊ธฐ๋ณธ๊ฐ 10๋ถ, ์ต์๊ฐ 1๋ถ). - ์ฐ์์ผ๋ก
PROXY_AUTO_REMOVE_AFTER๋ฒ์ ํ์ ์ ์ฅ์ ๊ฐ ๋ฐ์ํ๋ฉด(์ค์ ์ฐ๊ฒฐ ์ฅ์ ๋ฅผ ์๋ฏธํ๋ฉฐ, ์๊ฐ ์ด๊ณผ ๋๋ ํ๋ก๋ธ ๋์ ์์ฒด์ 5xx ์๋ต์ ์ ๋ ํฌํจ๋์ง ์์ต๋๋ค. ํ๋ก์ ์ํ ํ์ธ ์ฐธ์กฐ), ํ๋ก์์status๊ฐdead๋ก ์ค์ ๋ฉ๋๋ค. dead๋ ํ/๋กํ ์ด์ ํด์์์ ์ฌ์ฉํ๋ ํ์ฑ ์ํ ํํฐ๊ฐ ์ ์ธํ๋ ์ํ ์ค ํ๋์ด๋ฏ๋ก, ํด๋น ๋ฒ์์ ๋กํ ์ด์ (๋ผ์ด๋ ๋ก๋น / ๋ฌด์์ / ๊ณ ์ / ์ง์ฐ ์๊ฐ โ ๋กํ ์ด์ ์ ๋ต ๊ฒฐ์ ํธ๋ฆฌ ์ฐธ์กฐ)์ ์ ์์ฒญ์ ํด๋น ํ๋ก์๋ฅผ ์ฆ์ ํ ๋นํ์ง ์์ต๋๋ค. ํ์ ๋ค๋ฅธ ํ๋ก์๋ ์ํฅ์ ๋ฐ์ง ์์ผ๋ฉฐ, ์ ์ฒด ํ์ด ์ธ์ง๋์ง ์์ ์ฑ ์ง์ ์ฐ๊ฒฐ๋ก ๋์ฒด๋๋ ์ผ๋ ์์ต๋๋ค. ํ์ผ ํด๋ก์ฆ ๋ณดํธ ๊ธฐ๋ฅ์ 4๋จ๊ณ ํ๋ก์ ์์คํ ์ ์ฐธ์กฐํ์ธ์.- ์ค์ผ์ค๋ฌ๋ ๋์ผํ ๊ฐ๊ฒฉ์ผ๋ก
deadํ๋ก์๋ฅผ ๊ณ์ ํ๋ก๋ธํฉ๋๋ค. ๋ค์ ํ๋ก๋ธ๊ฐ ์ฑ๊ณตํ๋ฉดstatus๊ฐ ๋ค์active๋ก ์ ํ๋๊ณ ํ๋ก์๋ ๋กํ ์ด์ ์ ์ฌ์ง์ ํฉ๋๋ค. ์๋์ผ๋ก ๋ค์ ์ถ๊ฐํ ํ์๊ฐ ์์ต๋๋ค.
์ด ๊ธฐ๋ฅ์ ์๋์ ์ผ๋ก ์ตํธ์ธ ๋ฐฉ์์ด๋ฉฐ ๋นํ๊ดด์ ์
๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ค์ผ์ค๋ฌ๋
์คํจ ํ์๋ฅผ ์ง๊ณํ๊ณ ๋ก๊ทธ๋ง ๊ธฐ๋กํ๋ฉฐ(decision.ts์ ์ ์ฑ
C ์ฐธ์กฐ),
PROXY_AUTO_DISABLE์ ํ์ ์ญ์ ํ์ง ์์ต๋๋ค. ํ ์ญ์ ๋ ๋ณ๋์ ๋ ๊ฐ๋ ฅํ
PROXY_AUTO_REMOVE ํ๋๊ทธ๊ฐ ๋ด๋นํฉ๋๋ค. ๋ ๋ค true๋ก ์ค์ ๋ ๊ฒฝ์ฐ
PROXY_AUTO_REMOVE๊ฐ ์ฐ์ ํฉ๋๋ค(๊ณง ์ญ์ ๋ ํ๋ก์๋ฅผ ์ค๊ฐ์ ์ผ์์ ์ผ๋ก
๋นํ์ฑํํ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์
๋๋ค). ์ ์ฒด ๋ณ์ ๋ชฉ๋ก์
ํ๊ฒฝ ๊ตฌ์ฑ ์ฐธ์กฐ ๋ฌธ์๋ฅผ ํ์ธํ์ธ์.
๐ ๊ด๋ จ ๋ฌธ์:
- ์ฌ์ฉ์ ๊ฐ์ด๋ โ ์ผ๋ฐ ์ค์ ๋ฐ ๊ตฌ์ฑ
- API ์ฐธ์กฐ โ ์ ์ฒด API ๋ฌธ์
- ํ๊ฒฝ ๊ตฌ์ฑ โ ๋ชจ๋ ํ๊ฒฝ ๋ณ์
HagiCode
HagiCode๋ ๊ตฌ์กฐํ๋ ์ํฌํ๋ก, ๋ค์ค ์์ด์ ํธ ์คํ, Hero Dungeon ๋ทฐ๋ฅผ ๊ฐ์ถ ์์ด์ ํธ ์ฝ๋ฉ ์์ ๊ณต๊ฐ์ ๋๋ค.
๋ ์ค๋งํธํ๊ณ ๋น ๋ฅด๋ฉฐ ์ฆ๊ฑฐ์ด ์์ด์ ํธ ์ํฌํ๋ก๋ก ์ ์ฉํ ์ํํธ์จ์ด๋ฅผ ๋ง๋์ธ์.

- Smart๊ตฌ์กฐํ๋ ์ํฌํ๋ก๋ ์๋๋ฅผ ์์ด๋์ด๋ถํฐ ๋ฐฐํฌ๊น์ง ์คํ ๊ฐ๋ฅํ ๊ฒฝ๋ก๋ก ๋ฐ๊ฟ๋๋ค.
- Efficient๋ค์ค ์์ด์ ํธ ์ํฌํ๋ก๋ก ์กฐ์ฌ, ๊ตฌํ, ๊ฒํ ๋ฅผ ๋ณ๋ ฌ๋ก ์งํํฉ๋๋ค.
- FunHero Dungeon์ ๊ธด ์ฝ๋ฉ ์ธ์ ์ ์๊ฐ์ ์ด๊ณ ํ์ ์ ์ธ ๊ฒฝํ์ผ๋ก ๋ง๋ญ๋๋ค.