feat(docs): 문서 정리
This commit is contained in:
parent
5bb3820784
commit
c78338fc11
8 changed files with 454 additions and 667 deletions
67
AGENTS.md
Normal file
67
AGENTS.md
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# Kyush LLM Router
|
||||
|
||||
다중 사용자 LLM 라우팅 프록시. API 키 인증, 백엔드 라우팅, 스크립트 기반 요청/응답 조작, 사용량 모니터링을 제공한다.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
pnpm monorepo | Express 5 + TypeScript | Solid.js + Vite | SQLite (better-sqlite3) | isolated-vm
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
server/ Express 백엔드 (포트 3000)
|
||||
client/ Solid.js 어드민 대시보드 (포트 3002)
|
||||
shared/ 공유 TypeScript 타입
|
||||
database/ SQL 스키마 원본
|
||||
docs/ 세부 문서
|
||||
scripts/ 개발 스크립트
|
||||
```
|
||||
|
||||
## Entry Points
|
||||
|
||||
- Server: `server/src/index.ts`
|
||||
- Client: `client/src/index.tsx`
|
||||
- Shared types: `shared/types.ts`
|
||||
- DB schema: `database/schema.sql`, `database/analytics-schema.sql`
|
||||
|
||||
## Key Concepts
|
||||
|
||||
**인증**: `Authorization: Bearer <api_key>` → `auth.ts` 미들웨어 → 사용자 식별 + 권한 로드
|
||||
|
||||
**요청 흐름**:
|
||||
```
|
||||
Client → Auth → Script(onRequest) → RouterService → Backend → Script(onResponse) → Response
|
||||
→ AnalyticsService(log)
|
||||
```
|
||||
|
||||
**Script Engine**: isolated-vm 샌드박스에서 JS 실행. 3가지 타입: per-user, per-backend, per-user-backend
|
||||
|
||||
**Database**: core.db (users, backends, permissions, user_scripts) + analytics.db (request_logs, usage_stats, backend_metrics)
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
pnpm install # 의존성 설치
|
||||
pnpm run dev # 서버 + 클라이언트 동시 실행
|
||||
pnpm test # 서버 테스트 실행
|
||||
pnpm run bench # 벤치마크 실행
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `SERVER_PORT` | 3000 | Express 서버 포트 |
|
||||
| `CLIENT_PORT` | 3001 | Vite 개발 서버 포트 |
|
||||
| `CORE_DB_PATH` | ./data/core.db | Core DB 경로 |
|
||||
| `ANALYTICS_DB_PATH` | ./data/analytics.db | Analytics DB 경로 |
|
||||
| `ADMIN_PASSWORD` | (필수) | 어드민 비밀번호 |
|
||||
| `CORS_ORIGINS` | localhost origins | 허용 CORS 오리진 |
|
||||
|
||||
## Detailed Docs
|
||||
|
||||
- [docs/server.md](docs/server.md) — 서버 구조, 서비스, 모델, 의존성
|
||||
- [docs/client.md](docs/client.md) — 클라이언트 구조, 라우트, 컴포넌트
|
||||
- [docs/database.md](docs/database.md) — DB 테이블 스키마 전체
|
||||
- [docs/api.md](docs/api.md) — API 엔드포인트 레퍼런스
|
||||
- [docs/scripts.md](docs/scripts.md) — Script Engine 사용법, 타입, 예제
|
||||
477
ARCHITECTURE.md
477
ARCHITECTURE.md
|
|
@ -1,477 +0,0 @@
|
|||
# Kyush LLM Router Architecture Document
|
||||
|
||||
## Overview
|
||||
|
||||
Kyush LLM Router is a proxy server that manages multiple users and routes their requests to various OpenAI-compatible backend APIs. It provides API key-based authentication, user permission management, and usage monitoring through an admin web dashboard.
|
||||
|
||||
## System Architecture
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────────────────────────────┐
|
||||
│ Client Layer │
|
||||
├─────────────────────┬───────────────────────────────┬─────────────────────┤
|
||||
│ LLM Clients │ Admin Dashboard │ Vite Dev Server │
|
||||
│ (OpenAI SDK etc) │ (Solid.js + Vite) │ (Port 5173) │
|
||||
└──────────┬──────────┴──────────────┬────────────────┴──────────┬──────────┘
|
||||
│ │ │
|
||||
│ OpenAI-Compatible API │ REST API │
|
||||
│ (Port 3000) │ (Port 3001) │
|
||||
▼ ▼ │
|
||||
┌───────────────────────────────────────────────────────────────────────────┐
|
||||
│ Router Server (Node.js/Express) │
|
||||
│ (Port 3000) │
|
||||
├───────────────────────────────────────────────────────────────────────────┤
|
||||
│ ┌───────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Authentication Middleware │ │
|
||||
│ │ - API Key Validation │ │
|
||||
│ │ - Rate Limiting │ │
|
||||
│ └───────────────────────────────────────────────────────────────────┘ │
|
||||
│ ┌───────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Request Router │ │
|
||||
│ │ - Backend Selection │ │
|
||||
│ │ - Load Balancing (optional) │ │
|
||||
│ │ - Request/Response Transformation │ │
|
||||
│ └───────────────────────────────────────────────────────────────────┘ │
|
||||
│ ┌───────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Admin API Endpoints (proxied to Vite dev server) │ │
|
||||
│ │ - User Management │ │
|
||||
│ │ - Backend Management │ │
|
||||
│ │ - Permission Management │ │
|
||||
│ │ - Usage Analytics │ │
|
||||
│ └───────────────────────────────────────────────────────────────────┘ │
|
||||
└────────────────────────────┬──────────────────────────────────────────────┘
|
||||
│
|
||||
┌─────────────────┴─────────────────┐
|
||||
▼ ▼
|
||||
┌───────────────────────┐ ┌─────────────────────────┐
|
||||
│ Core Database │ │ Analytics Database │
|
||||
│ (SQLite - core.db) │ │ (SQLite - analytics.db)│
|
||||
├───────────────────────┤ ├─────────────────────────┤
|
||||
│ - users │ │ - request_logs │
|
||||
│ - backends │ │ - usage_stats │
|
||||
│ - permissions │ │ - backend_metrics │
|
||||
└───────────────────────┘ └─────────────────────────┘
|
||||
│ │
|
||||
└─────────────────┬─────────────────┘
|
||||
▼
|
||||
┌───────────────────────────────────────────────────────────────────────────┐
|
||||
│ Backend Layer │
|
||||
├───────────────────────────────────────────────────────────────────────────┤
|
||||
│ Multiple OpenAI-Compatible APIs (vLLM, SGLang, etc.) │
|
||||
└───────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
kyush-llm-router/
|
||||
├── server/
|
||||
│ ├── src/
|
||||
│ │ ├── index.ts # Express app entry point
|
||||
│ │ ├── config/
|
||||
│ │ │ ├── database.ts # Core SQLite connection
|
||||
│ │ │ └── analytics-db.ts # Analytics SQLite connection
|
||||
│ │ ├── routes/
|
||||
│ │ │ ├── api.ts # OpenAI-compatible API proxy
|
||||
│ │ │ ├── admin.ts # Admin management API
|
||||
│ │ │ └── auth.ts # Authentication middleware
|
||||
│ │ ├── models/
|
||||
│ │ │ ├── User.ts # User model
|
||||
│ │ │ ├── Backend.ts # Backend model
|
||||
│ │ │ └── Permission.ts # Permission model
|
||||
│ │ ├── analytics/
|
||||
│ │ │ ├── RequestLog.ts # Request log model (analytics DB)
|
||||
│ │ │ ├── UsageStats.ts # Usage stats model (analytics DB)
|
||||
│ │ │ └── BackendMetrics.ts # Backend metrics model
|
||||
│ │ ├── services/
|
||||
│ │ │ ├── AuthService.ts # API key validation
|
||||
│ │ │ ├── RouterService.ts # Backend routing logic
|
||||
│ │ │ └── AnalyticsService.ts # Usage tracking
|
||||
│ │ └── utils/
|
||||
│ │ └── logger.ts # Logging utility
|
||||
│ ├── package.json
|
||||
│ └── tsconfig.json
|
||||
│
|
||||
├── client/
|
||||
│ ├── src/
|
||||
│ │ ├── index.tsx # Solid.js entry point
|
||||
│ │ ├── App.tsx # Main application component
|
||||
│ │ ├── routes/
|
||||
│ │ │ ├── Dashboard.tsx # Main dashboard
|
||||
│ │ │ ├── Users.tsx # User management
|
||||
│ │ │ ├── Backends.tsx # Backend management
|
||||
│ │ │ ├── Permissions.tsx # Permission management
|
||||
│ │ │ └── Analytics.tsx # Usage monitoring
|
||||
│ │ ├── components/
|
||||
│ │ │ ├── Layout.tsx # Admin layout
|
||||
│ │ │ ├── UserTable.tsx # User list table
|
||||
│ │ │ ├── BackendTable.tsx # Backend list table
|
||||
│ │ │ └── StatsChart.tsx # Usage chart component
|
||||
│ │ ├── api/
|
||||
│ │ │ └── client.ts # API client for admin endpoints
|
||||
│ │ └── types/
|
||||
│ │ └── index.ts # TypeScript type definitions
|
||||
│ ├── package.json
|
||||
│ ├── vite.config.ts
|
||||
│ └── tsconfig.json
|
||||
│
|
||||
├── shared/
|
||||
│ └── types.ts # Shared type definitions
|
||||
│
|
||||
├── database/
|
||||
│ ├── schema.sql # Core database schema
|
||||
│ └── analytics-schema.sql # Analytics database schema
|
||||
│
|
||||
├── scripts/
|
||||
│ └── dev.js # Dev server launcher (runs both)
|
||||
│
|
||||
├── docker-compose.yml # Docker Compose setup
|
||||
├── package.json # Root package.json (scripts)
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Core Components
|
||||
|
||||
### 1. Server (Node.js/Express)
|
||||
|
||||
#### Authentication Middleware (`src/routes/auth.ts`)
|
||||
- Validates API keys from incoming requests
|
||||
- Extracts user identity from `Authorization: Bearer <api_key>` header
|
||||
- Returns 401 if authentication fails
|
||||
- Attaches user info to request object for downstream handlers
|
||||
|
||||
#### API Proxy Route (`src/routes/api.ts`)
|
||||
```typescript
|
||||
// OpenAI-compatible endpoints
|
||||
POST /v1/chat/completions
|
||||
POST /v1/completions
|
||||
GET /v1/models
|
||||
```
|
||||
- Forwards requests to selected backend
|
||||
- Handles request/response transformation
|
||||
- Logs all requests for analytics
|
||||
|
||||
#### Admin API Route (`src/routes/admin.ts`)
|
||||
```typescript
|
||||
// User Management
|
||||
POST /admin/users # Create user
|
||||
GET /admin/users # List users
|
||||
PUT /admin/users/:id # Update user
|
||||
DELETE /admin/users/:id # Delete user
|
||||
|
||||
// Backend Management
|
||||
POST /admin/backends # Add backend
|
||||
GET /admin/backends # List backends
|
||||
PUT /admin/backends/:id # Update backend
|
||||
DELETE /admin/backends/:id # Delete backend
|
||||
|
||||
// Permission Management
|
||||
POST /admin/permissions # Grant permission
|
||||
DELETE /admin/permissions # Revoke permission
|
||||
GET /admin/permissions # List permissions
|
||||
|
||||
// Analytics
|
||||
GET /admin/analytics/usage # Usage statistics
|
||||
GET /admin/analytics/requests # Request logs
|
||||
```
|
||||
|
||||
#### Router Service (`src/services/RouterService.ts`)
|
||||
- Selects appropriate backend based on:
|
||||
- User's permissions
|
||||
- Backend availability
|
||||
- Load balancing strategy (round-robin, least-loaded)
|
||||
- Handles backend failures with retry logic
|
||||
|
||||
### 2. Client (Solid.js + Vite)
|
||||
|
||||
#### Pages
|
||||
- **Dashboard**: Overview of system status, recent activity
|
||||
- **Users**: CRUD operations for users, API key generation
|
||||
- **Backends**: Manage backend API configurations
|
||||
- **Permissions**: Assign/revoke backend access per user
|
||||
- **Analytics**: View usage statistics and request logs
|
||||
|
||||
#### Key Features
|
||||
- Real-time updates via polling or WebSocket (optional)
|
||||
- Form validation for user/backend input
|
||||
- Error handling with user-friendly messages
|
||||
- Responsive design for various screen sizes
|
||||
|
||||
### 3. Databases (SQLite)
|
||||
|
||||
#### Core Database Schema (core.db)
|
||||
|
||||
```sql
|
||||
-- Users table
|
||||
CREATE TABLE users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
api_key TEXT UNIQUE NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT,
|
||||
is_active BOOLEAN DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Backends table
|
||||
CREATE TABLE backends (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT UNIQUE NOT NULL,
|
||||
base_url TEXT NOT NULL,
|
||||
api_key TEXT,
|
||||
is_active BOOLEAN DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Permissions table (many-to-many: users ↔ backends)
|
||||
CREATE TABLE permissions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
backend_id INTEGER NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
FOREIGN KEY (backend_id) REFERENCES backends(id),
|
||||
UNIQUE(user_id, backend_id)
|
||||
);
|
||||
|
||||
-- Indexes for performance
|
||||
CREATE INDEX idx_users_api_key ON users(api_key);
|
||||
CREATE INDEX idx_permissions_user ON permissions(user_id);
|
||||
CREATE INDEX idx_permissions_backend ON permissions(backend_id);
|
||||
```
|
||||
|
||||
#### Analytics Database Schema (analytics.db)
|
||||
|
||||
```sql
|
||||
-- Request logs table
|
||||
CREATE TABLE request_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
backend_id INTEGER NOT NULL,
|
||||
endpoint TEXT NOT NULL,
|
||||
request_model TEXT,
|
||||
response_model TEXT,
|
||||
prompt_tokens INTEGER,
|
||||
completion_tokens INTEGER,
|
||||
total_tokens INTEGER,
|
||||
status_code INTEGER,
|
||||
response_time_ms INTEGER,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
FOREIGN KEY (backend_id) REFERENCES backends(id)
|
||||
);
|
||||
|
||||
-- Usage stats table (aggregated daily)
|
||||
CREATE TABLE usage_stats (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
backend_id INTEGER NOT NULL,
|
||||
date DATE NOT NULL,
|
||||
total_requests INTEGER DEFAULT 0,
|
||||
total_tokens INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
FOREIGN KEY (backend_id) REFERENCES backends(id),
|
||||
UNIQUE(user_id, backend_id, date)
|
||||
);
|
||||
|
||||
-- Backend metrics table (aggregated metrics per backend)
|
||||
CREATE TABLE backend_metrics (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
backend_id INTEGER NOT NULL,
|
||||
date DATE NOT NULL,
|
||||
total_requests INTEGER DEFAULT 0,
|
||||
total_tokens INTEGER DEFAULT 0,
|
||||
avg_response_time_ms REAL DEFAULT 0,
|
||||
error_count INTEGER DEFAULT 0,
|
||||
success_rate REAL DEFAULT 1.0,
|
||||
FOREIGN KEY (backend_id) REFERENCES backends(id),
|
||||
UNIQUE(backend_id, date)
|
||||
);
|
||||
|
||||
-- Indexes for performance
|
||||
CREATE INDEX idx_request_logs_user ON request_logs(user_id);
|
||||
CREATE INDEX idx_request_logs_backend ON request_logs(backend_id);
|
||||
CREATE INDEX idx_request_logs_date ON request_logs(created_at);
|
||||
CREATE INDEX idx_usage_stats_user ON usage_stats(user_id);
|
||||
CREATE INDEX idx_usage_stats_date ON usage_stats(date);
|
||||
CREATE INDEX idx_backend_metrics_backend ON backend_metrics(backend_id);
|
||||
CREATE INDEX idx_backend_metrics_date ON backend_metrics(date);
|
||||
```
|
||||
|
||||
## API Design
|
||||
|
||||
### OpenAI-Compatible API Proxy
|
||||
|
||||
The router exposes the same API interface as OpenAI, making it easy for clients to integrate.
|
||||
|
||||
#### Example Request
|
||||
```bash
|
||||
curl http://localhost:3000/v1/chat/completions \
|
||||
-H "Authorization: Bearer <user_api_key>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "llama-3",
|
||||
"messages": [{"role": "user", "content": "Hello"}]
|
||||
}'
|
||||
```
|
||||
|
||||
#### Example Response
|
||||
```json
|
||||
{
|
||||
"id": "chatcmpl-xxx",
|
||||
"object": "chat.completion",
|
||||
"created": 1234567890,
|
||||
"model": "llama-3",
|
||||
"choices": [{
|
||||
"index": 0,
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "Hello! How can I help you?"
|
||||
},
|
||||
"finish_reason": "stop"
|
||||
}],
|
||||
"usage": {
|
||||
"prompt_tokens": 10,
|
||||
"completion_tokens": 15,
|
||||
"total_tokens": 25
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Admin API
|
||||
|
||||
#### Create User
|
||||
```bash
|
||||
POST /admin/users
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "John Doe",
|
||||
"email": "john@example.com"
|
||||
}
|
||||
|
||||
Response: {
|
||||
"id": 1,
|
||||
"name": "John Doe",
|
||||
"api_key": "sk-xxx...",
|
||||
"created_at": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
#### Add Backend
|
||||
```bash
|
||||
POST /admin/backends
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "vLLM Server 1",
|
||||
"base_url": "http://localhost:8000/v1",
|
||||
"api_key": "backend-key-xxx"
|
||||
}
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **API Key Storage**: API keys are stored hashed in the database
|
||||
2. **Transport Security**: Use HTTPS in production
|
||||
3. **Rate Limiting**: Implement per-user rate limits
|
||||
4. **Input Validation**: Validate all admin API inputs
|
||||
5. **CORS**: Configure CORS for admin dashboard only
|
||||
|
||||
## Deployment
|
||||
|
||||
### Development
|
||||
|
||||
Run both server and client with a single command:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
This starts:
|
||||
- Express server on port 3000
|
||||
- Vite dev server on port 3001 (admin API routes proxied from Express)
|
||||
|
||||
### Docker Compose
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
router:
|
||||
build: .
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- SERVER_PORT=3000
|
||||
- CLIENT_PORT=3001
|
||||
- CORE_DB_PATH=/data/core.db
|
||||
- ANALYTICS_DB_PATH=/data/analytics.db
|
||||
volumes:
|
||||
- router-data:/data
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
router-data:
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `SERVER_PORT` | Express server port | `3000` |
|
||||
| `CLIENT_PORT` | Vite dev server port | `3001` |
|
||||
| `CORE_DB_PATH` | Core database path | `./data/core.db` |
|
||||
| `ANALYTICS_DB_PATH` | Analytics database path | `./data/analytics.db` |
|
||||
| `ADMIN_PASSWORD` | Admin dashboard password | (required) |
|
||||
|
||||
## Development Roadmap
|
||||
|
||||
### Phase 1: Core Infrastructure
|
||||
- [ ] Set up Express server with TypeScript
|
||||
- [ ] Implement SQLite database schema
|
||||
- [ ] Create user and backend models
|
||||
- [ ] Implement API key authentication
|
||||
|
||||
### Phase 2: API Proxy
|
||||
- [ ] Implement OpenAI-compatible API endpoints
|
||||
- [ ] Add request forwarding to backends
|
||||
- [ ] Implement basic routing logic
|
||||
- [ ] Add request logging
|
||||
|
||||
### Phase 3: Admin API
|
||||
- [ ] Implement CRUD endpoints for users
|
||||
- [ ] Implement CRUD endpoints for backends
|
||||
- [ ] Implement permission management
|
||||
- [ ] Add usage analytics endpoints
|
||||
|
||||
### Phase 4: Admin Dashboard
|
||||
- [ ] Set up Solid.js + Vite project
|
||||
- [ ] Create user management UI
|
||||
- [ ] Create backend management UI
|
||||
- [ ] Create permission management UI
|
||||
- [ ] Create analytics dashboard
|
||||
|
||||
### Phase 5: Advanced Features
|
||||
- [ ] Add rate limiting
|
||||
- [ ] Implement load balancing
|
||||
- [ ] Add WebSocket for real-time updates
|
||||
- [ ] Implement backend health checks
|
||||
|
||||
## Technology Stack Summary
|
||||
|
||||
| Component | Technology |
|
||||
|-----------|------------|
|
||||
| Backend | Node.js 18+, Express.js, TypeScript |
|
||||
| Core Database | SQLite (better-sqlite3) |
|
||||
| Analytics Database | SQLite (better-sqlite3) |
|
||||
| Frontend | Solid.js, Vite, TypeScript |
|
||||
| HTTP Client | Axios/Fetch |
|
||||
| Charts | Chart.js or Solid-chart |
|
||||
| Styling | Tailwind CSS or CSS Modules |
|
||||
| Validation | Zod |
|
||||
| Testing | Vitest (frontend), Jest (backend) |
|
||||
| Dev Server | Concurrently for running both servers |
|
||||
195
README.md
195
README.md
|
|
@ -1,202 +1,17 @@
|
|||
# Kyush LLM Router
|
||||
|
||||
Multi-user LLM routing proxy with API key management, usage monitoring, and script-based request/response manipulation.
|
||||
|
||||
## Features
|
||||
|
||||
- **Multi-user support**: Manage multiple users with individual API keys
|
||||
- **Backend routing**: Route requests to multiple OpenAI-compatible backends (vLLM, SGLang, etc.) with load balancing
|
||||
- **Permission management**: Control which users can access which backends
|
||||
- **Usage monitoring**: Track request logs, token usage, and backend metrics
|
||||
- **Script engine**: Execute JavaScript code in secure isolates to manipulate requests/responses
|
||||
- `onRequest`: Modify requests before forwarding to backend
|
||||
- `onResponse`: Modify responses before returning to client
|
||||
- Script types: `per-user`, `per-backend`, `per-user-backend`
|
||||
- **Admin dashboard**: Web UI for managing users, backends, permissions, and scripts
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌──────────────────────────────────────┐
|
||||
│ LLM Clients │────▶│ Router Server (Port 3000) │
|
||||
│ (OpenAI SDK) │ │ - Authentication │
|
||||
└─────────────────┘ │ - Request Routing │
|
||||
│ - Script Execution (isolated-vm) │
|
||||
│ - Admin API │
|
||||
└─────────────────┬────────────────────┘
|
||||
│
|
||||
┌─────────────────┴────────────────────┐
|
||||
▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐
|
||||
│ core.db │ │ analytics.db │
|
||||
│ - users │ │ - request_logs │
|
||||
│ - backends │ │ - usage_stats │
|
||||
│ - permissions │ │ - metrics │
|
||||
│ - user_scripts │ │ │
|
||||
└─────────────────┘ └─────────────────┘
|
||||
```
|
||||
다중 사용자 LLM 라우팅 프록시 — API 키 인증, 백엔드 라우팅, 스크립트 기반 요청/응답 조작, 사용량 모니터링.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Development
|
||||
|
||||
1. Install dependencies:
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
2. Start development servers:
|
||||
```bash
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
This starts:
|
||||
- Express API server on http://localhost:3000
|
||||
- Vite admin dashboard on http://localhost:3001
|
||||
- API 서버: http://localhost:3000
|
||||
- 어드민 대시보드: http://localhost:3002
|
||||
|
||||
### Production with Docker
|
||||
## Documentation
|
||||
|
||||
1. Build and run:
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
2. Set admin password via environment variable:
|
||||
```bash
|
||||
ADMIN_PASSWORD=your_secure_password docker-compose up -d
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
kyush-llm-router/
|
||||
├── server/ # Express backend
|
||||
│ ├── src/
|
||||
│ │ ├── config/ # Database configuration
|
||||
│ │ ├── models/ # Data models (User, Backend, Permission, Script)
|
||||
│ │ ├── routes/ # API routes (admin, api, scripts, analytics)
|
||||
│ │ ├── services/ # RouterService, ScriptEngine, AnalyticsService
|
||||
│ │ └── utils/ # Utilities (apiKey, logger)
|
||||
│ ├── tests/ # Integration tests
|
||||
│ └── benchmarks/ # Performance benchmarks
|
||||
├── client/ # Solid.js admin dashboard
|
||||
│ └── src/
|
||||
│ ├── api/ # API client
|
||||
│ ├── components/ # UI components
|
||||
│ └── types/ # TypeScript types
|
||||
├── shared/ # Shared TypeScript types
|
||||
├── scripts/ # Development scripts
|
||||
└── docs/ # Documentation
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### OpenAI-Compatible API (Port 3000)
|
||||
|
||||
```
|
||||
POST /v1/chat/completions # Chat completions with routing & scripting
|
||||
GET /v1/models # List available models
|
||||
```
|
||||
|
||||
### Admin API (Port 3001)
|
||||
|
||||
```
|
||||
# User Management
|
||||
POST /admin/users # Create user
|
||||
GET /admin/users # List all users
|
||||
GET /admin/users/:id # Get user by ID
|
||||
PUT /admin/users/:id # Update user
|
||||
DELETE /admin/users/:id # Delete user
|
||||
POST /admin/users/:id/regenerate-api-key # Regenerate API key
|
||||
|
||||
# Backend Management
|
||||
POST /admin/backends # Create backend
|
||||
GET /admin/backends # List all backends
|
||||
GET /admin/backends/:id # Get backend by ID
|
||||
PUT /admin/backends/:id # Update backend
|
||||
DELETE /admin/backends/:id # Delete backend
|
||||
|
||||
# Permission Management
|
||||
POST /admin/permissions # Create permission
|
||||
GET /admin/permissions # List all permissions
|
||||
GET /admin/permissions/user/:userId # Get permissions by user
|
||||
GET /admin/permissions/backend/:backendId # Get permissions by backend
|
||||
DELETE /admin/permissions # Delete permission (query params: user_id, backend_id)
|
||||
|
||||
# Script Management
|
||||
GET /admin/scripts # List all scripts
|
||||
GET /admin/scripts/active # List active scripts
|
||||
GET /admin/scripts/type/:type # List scripts by type
|
||||
GET /admin/scripts/:id # Get script by ID
|
||||
POST /admin/scripts # Create script
|
||||
PUT /admin/scripts/:id # Update script
|
||||
DELETE /admin/scripts/:id # Delete script
|
||||
POST /admin/scripts/:id/activate # Activate script
|
||||
POST /admin/scripts/:id/deactivate # Deactivate script
|
||||
POST /admin/scripts/:id/test # Test script
|
||||
|
||||
# Analytics
|
||||
GET /admin/analytics/usage # Get usage statistics
|
||||
GET /admin/analytics/requests # Get request logs
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `SERVER_PORT` | Express server port | `3000` |
|
||||
| `CLIENT_PORT` | Vite dev server port | `3001` |
|
||||
| `CORE_DB_PATH` | Core database path | `./data/core.db` |
|
||||
| `ANALYTICS_DB_PATH` | Analytics database path | `./data/analytics.db` |
|
||||
| `ADMIN_PASSWORD` | Admin dashboard password | Required |
|
||||
| `CORS_ORIGINS` | Comma-separated allowed origins | `http://localhost:5173,http://localhost:3001` |
|
||||
|
||||
## Script Engine
|
||||
|
||||
The router supports JavaScript code execution in secure isolated VMs for request/response manipulation.
|
||||
|
||||
### Script Types
|
||||
|
||||
- **per-user**: Applied to all requests from a specific user
|
||||
- **per-backend**: Applied to all requests going to a specific backend
|
||||
- **per-user-backend**: Applied to requests from a specific user to a specific backend
|
||||
|
||||
### Script Context
|
||||
|
||||
Scripts have access to:
|
||||
- `user`: User information (id, name, email)
|
||||
- `backend`: Backend information (id, name, base_url)
|
||||
- `request`: Request details (method, path, headers, body, isStream)
|
||||
- `response`: Response details (status, headers, body, isStream)
|
||||
|
||||
### Example Script
|
||||
|
||||
```javascript
|
||||
export async function onRequest(context) {
|
||||
// Add custom headers to all requests
|
||||
context.request.headers['X-Custom-Header'] = 'value';
|
||||
return context;
|
||||
}
|
||||
|
||||
export async function onResponse(context) {
|
||||
// Log response status
|
||||
console.log(`Response status: ${context.response.status}`);
|
||||
return context;
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Run tests:
|
||||
```bash
|
||||
pnpm test
|
||||
```
|
||||
|
||||
Run benchmarks:
|
||||
```bash
|
||||
pnpm run bench
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
프로젝트 구조와 개발 가이드는 [AGENTS.md](AGENTS.md)를 참조.
|
||||
|
|
|
|||
76
docs/api.md
Normal file
76
docs/api.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# API Reference
|
||||
|
||||
서버 포트: `SERVER_PORT` (기본 3000)
|
||||
|
||||
---
|
||||
|
||||
## Health
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| GET | `/health` | 서버 상태 확인 (status, timestamp) |
|
||||
|
||||
## OpenAI-Compatible Proxy (인증 필요)
|
||||
|
||||
`Authorization: Bearer <user_api_key>` 헤더 필수.
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| POST | `/v1/chat/completions` | Chat completions 프록시 (스크립트 적용, 분석 로깅) |
|
||||
| GET | `/v1/models` | 사용 가능한 모델 목록 |
|
||||
|
||||
## Admin API
|
||||
|
||||
### Users
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| GET | `/admin/users` | 전체 사용자 목록 |
|
||||
| POST | `/admin/users` | 사용자 생성 (API 키 자동 발급) |
|
||||
| GET | `/admin/users/:id` | 사용자 조회 |
|
||||
| PUT | `/admin/users/:id` | 사용자 수정 (name, email, is_active) |
|
||||
| DELETE | `/admin/users/:id` | 사용자 삭제 |
|
||||
| POST | `/admin/users/:id/regenerate-api-key` | API 키 재발급 |
|
||||
|
||||
### Backends
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| GET | `/admin/backends` | 전체 백엔드 목록 |
|
||||
| POST | `/admin/backends` | 백엔드 생성 (name, base_url, api_key) |
|
||||
| GET | `/admin/backends/:id` | 백엔드 조회 |
|
||||
| PUT | `/admin/backends/:id` | 백엔드 수정 |
|
||||
| DELETE | `/admin/backends/:id` | 백엔드 삭제 |
|
||||
|
||||
### Permissions
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| GET | `/admin/permissions` | 전체 권한 목록 |
|
||||
| GET | `/admin/permissions/user/:userId` | 사용자별 권한 조회 |
|
||||
| GET | `/admin/permissions/backend/:backendId` | 백엔드별 권한 조회 |
|
||||
| POST | `/admin/permissions` | 권한 부여 (user_id, backend_id) |
|
||||
| DELETE | `/admin/permissions?user_id=X&backend_id=Y` | 권한 삭제 |
|
||||
|
||||
### Scripts
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| GET | `/admin/scripts` | 전체 스크립트 목록 |
|
||||
| GET | `/admin/scripts/active` | 활성 스크립트 목록 |
|
||||
| GET | `/admin/scripts/type/:type` | 타입별 스크립트 목록 |
|
||||
| GET | `/admin/scripts/:id` | 스크립트 조회 |
|
||||
| POST | `/admin/scripts` | 스크립트 생성 |
|
||||
| PUT | `/admin/scripts/:id` | 스크립트 수정 |
|
||||
| DELETE | `/admin/scripts/:id` | 스크립트 삭제 |
|
||||
| POST | `/admin/scripts/:id/activate` | 스크립트 활성화 |
|
||||
| POST | `/admin/scripts/:id/deactivate` | 스크립트 비활성화 |
|
||||
| POST | `/admin/scripts/:id/test` | 스크립트 테스트 실행 |
|
||||
|
||||
### Analytics
|
||||
|
||||
| Method | Path | Query Params | Description |
|
||||
|--------|------|-------------|-------------|
|
||||
| GET | `/admin/analytics/usage` | userId, backendId, days | 사용량 통계 |
|
||||
| GET | `/admin/analytics/requests` | limit, offset | 요청 로그 (페이지네이션) |
|
||||
| GET | `/admin/analytics/metrics` | backendId, days | 백엔드 성능 메트릭 |
|
||||
56
docs/client.md
Normal file
56
docs/client.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Client (Solid.js + Vite)
|
||||
|
||||
Admin 대시보드. 진입점: `client/src/index.tsx`
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
client/src/
|
||||
index.tsx # DOM 렌더링 진입점
|
||||
App.tsx # 라우터 정의 (6개 라우트)
|
||||
api/
|
||||
client.ts # Admin API 클라이언트 (users, backends, permissions, scripts, analytics)
|
||||
types/
|
||||
index.ts # TypeScript 타입 정의
|
||||
routes/
|
||||
Dashboard.tsx # 홈 — 요약 카드 (사용자 수, 활성 백엔드, 최근 요청) + 최근 요청 테이블
|
||||
Users.tsx # 사용자 관리 — CRUD, API 키 발급/재발급, 활성화 토글
|
||||
Backends.tsx # 백엔드 관리 — CRUD (name, base_url, api_key)
|
||||
Permissions.tsx # 권한 관리 — user-backend 매핑
|
||||
Analytics.tsx # 분석 — 요청 로그, 사용량 통계, 백엔드 메트릭
|
||||
Scripts.tsx # 스크립트 관리 — CRUD, 테스트, 활성화/비활성화
|
||||
components/
|
||||
Layout.tsx # 사이드바 네비게이션 + 메인 콘텐츠 레이아웃
|
||||
EditModal.tsx # 범용 편집 모달 (동적 폼 필드)
|
||||
ScriptEditor.tsx # Monaco 에디터 래퍼 (TypeScript 하이라이팅)
|
||||
```
|
||||
|
||||
## Routes
|
||||
|
||||
| URL | Component | Description |
|
||||
|-----|-----------|-------------|
|
||||
| `/` | Dashboard | 시스템 개요 |
|
||||
| `/users` | Users | 사용자 관리 |
|
||||
| `/backends` | Backends | 백엔드 관리 |
|
||||
| `/permissions` | Permissions | 권한 관리 |
|
||||
| `/analytics` | Analytics | 분석 대시보드 |
|
||||
| `/scripts` | Scripts | 스크립트 관리 |
|
||||
|
||||
## Styling
|
||||
|
||||
CSS 프레임워크 없음. 인라인 `style` props 사용.
|
||||
- 다크 사이드바 (#1e293b), 라이트 배경 (#f1f5f9), 화이트 카드
|
||||
- Flexbox / Grid 레이아웃
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Purpose |
|
||||
|---------|---------|
|
||||
| solid-js | UI 프레임워크 |
|
||||
| @solidjs/router | 클라이언트 사이드 라우팅 |
|
||||
| solid-monaco | Monaco 에디터 통합 |
|
||||
| vite | 빌드 도구 + 개발 서버 |
|
||||
|
||||
## Dev Server
|
||||
|
||||
포트: 3002 (vite.config.ts), API 프록시: `/api` → `http://localhost:3000`
|
||||
123
docs/database.md
Normal file
123
docs/database.md
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
# Database Schema
|
||||
|
||||
두 개의 SQLite 데이터베이스를 사용한다. 설정 데이터는 `core.db`, 운영 데이터는 `analytics.db`에 저장된다.
|
||||
|
||||
스키마 원본: [database/schema.sql](../database/schema.sql), [database/analytics-schema.sql](../database/analytics-schema.sql)
|
||||
|
||||
---
|
||||
|
||||
## Core Database (core.db)
|
||||
|
||||
### users
|
||||
|
||||
| Column | Type | Constraints |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | PRIMARY KEY AUTOINCREMENT |
|
||||
| api_key | TEXT | UNIQUE NOT NULL |
|
||||
| name | TEXT | NOT NULL |
|
||||
| email | TEXT | |
|
||||
| is_active | BOOLEAN | DEFAULT 1 |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP |
|
||||
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP |
|
||||
|
||||
Indexes: `idx_users_api_key(api_key)`
|
||||
|
||||
### backends
|
||||
|
||||
| Column | Type | Constraints |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | PRIMARY KEY AUTOINCREMENT |
|
||||
| name | TEXT | UNIQUE NOT NULL |
|
||||
| base_url | TEXT | NOT NULL |
|
||||
| api_key | TEXT | |
|
||||
| is_active | BOOLEAN | DEFAULT 1 |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP |
|
||||
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP |
|
||||
|
||||
### permissions
|
||||
|
||||
users와 backends의 many-to-many 관계.
|
||||
|
||||
| Column | Type | Constraints |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | PRIMARY KEY AUTOINCREMENT |
|
||||
| user_id | INTEGER | NOT NULL, FK → users(id) |
|
||||
| backend_id | INTEGER | NOT NULL, FK → backends(id) |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP |
|
||||
|
||||
Unique: `(user_id, backend_id)`
|
||||
Indexes: `idx_permissions_user(user_id)`, `idx_permissions_backend(backend_id)`
|
||||
|
||||
### user_scripts
|
||||
|
||||
| Column | Type | Constraints |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | PRIMARY KEY AUTOINCREMENT |
|
||||
| name | TEXT | UNIQUE NOT NULL |
|
||||
| script_type | TEXT | NOT NULL, CHECK IN ('per-user-backend', 'per-backend', 'per-user') |
|
||||
| target_user_id | INTEGER | FK → users(id) |
|
||||
| target_backend_id | INTEGER | FK → backends(id) |
|
||||
| script_code | TEXT | NOT NULL |
|
||||
| is_active | BOOLEAN | DEFAULT 1 |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP |
|
||||
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP |
|
||||
|
||||
Indexes: `idx_user_scripts_type`, `idx_user_scripts_active`, `idx_user_scripts_target_user`, `idx_user_scripts_target_backend`
|
||||
|
||||
---
|
||||
|
||||
## Analytics Database (analytics.db)
|
||||
|
||||
### request_logs
|
||||
|
||||
| Column | Type | Constraints |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | PRIMARY KEY AUTOINCREMENT |
|
||||
| user_id | INTEGER | NOT NULL |
|
||||
| backend_id | INTEGER | NOT NULL |
|
||||
| endpoint | TEXT | NOT NULL |
|
||||
| request_model | TEXT | |
|
||||
| response_model | TEXT | |
|
||||
| prompt_tokens | INTEGER | |
|
||||
| completion_tokens | INTEGER | |
|
||||
| total_tokens | INTEGER | |
|
||||
| status_code | INTEGER | |
|
||||
| response_time_ms | INTEGER | |
|
||||
| error_message | TEXT | |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP |
|
||||
|
||||
Indexes: `idx_request_logs_user`, `idx_request_logs_backend`, `idx_request_logs_date(created_at)`, `idx_request_logs_user_backend`
|
||||
|
||||
### usage_stats
|
||||
|
||||
일별 집계 테이블.
|
||||
|
||||
| Column | Type | Constraints |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | PRIMARY KEY AUTOINCREMENT |
|
||||
| user_id | INTEGER | NOT NULL |
|
||||
| backend_id | INTEGER | NOT NULL |
|
||||
| date | DATE | NOT NULL |
|
||||
| total_requests | INTEGER | DEFAULT 0 |
|
||||
| total_tokens | INTEGER | DEFAULT 0 |
|
||||
|
||||
Unique: `(user_id, backend_id, date)`
|
||||
Indexes: `idx_usage_stats_user`, `idx_usage_stats_date`
|
||||
|
||||
### backend_metrics
|
||||
|
||||
백엔드별 일별 성능 집계.
|
||||
|
||||
| Column | Type | Constraints |
|
||||
|--------|------|-------------|
|
||||
| id | INTEGER | PRIMARY KEY AUTOINCREMENT |
|
||||
| backend_id | INTEGER | NOT NULL |
|
||||
| date | DATE | NOT NULL |
|
||||
| total_requests | INTEGER | DEFAULT 0 |
|
||||
| total_tokens | INTEGER | DEFAULT 0 |
|
||||
| avg_response_time_ms | REAL | DEFAULT 0 |
|
||||
| error_count | INTEGER | DEFAULT 0 |
|
||||
| success_rate | REAL | DEFAULT 1.0 |
|
||||
|
||||
Unique: `(backend_id, date)`
|
||||
Indexes: `idx_backend_metrics_backend`, `idx_backend_metrics_date`
|
||||
58
docs/scripts.md
Normal file
58
docs/scripts.md
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Script Engine
|
||||
|
||||
isolated-vm 기반 JavaScript 샌드박스에서 요청/응답을 조작하는 미들웨어 시스템.
|
||||
|
||||
## Script Types
|
||||
|
||||
| Type | Target | Description |
|
||||
|------|--------|-------------|
|
||||
| `per-user` | target_user_id | 특정 사용자의 모든 요청에 적용 |
|
||||
| `per-backend` | target_backend_id | 특정 백엔드로 가는 모든 요청에 적용 |
|
||||
| `per-user-backend` | target_user_id + target_backend_id | 특정 사용자-백엔드 조합에 적용 |
|
||||
|
||||
## Hooks
|
||||
|
||||
### onRequest
|
||||
|
||||
백엔드 포워딩 전에 실행. context를 수정하여 요청을 변조할 수 있다.
|
||||
|
||||
### onResponse
|
||||
|
||||
백엔드 응답 수신 후 실행. context를 수정하여 응답을 변조할 수 있다.
|
||||
|
||||
## Script Context
|
||||
|
||||
스크립트에서 접근 가능한 데이터:
|
||||
|
||||
```typescript
|
||||
interface ScriptContextData {
|
||||
user: { id, name, email }
|
||||
backend: { id, name, base_url }
|
||||
request: { method, path, headers, body, isStream }
|
||||
response?: { status, headers, body, isStream } // onResponse에서만
|
||||
}
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```javascript
|
||||
export async function onRequest(context) {
|
||||
// 요청 헤더 추가
|
||||
context.request.headers['X-Custom-Header'] = 'value';
|
||||
return context;
|
||||
}
|
||||
|
||||
export async function onResponse(context) {
|
||||
// 응답 로깅
|
||||
console.log(`Status: ${context.response.status}`);
|
||||
return context;
|
||||
}
|
||||
```
|
||||
|
||||
## Execution Environment
|
||||
|
||||
- **Runtime**: isolated-vm (V8 isolate)
|
||||
- **Timeout**: 5초
|
||||
- **Memory**: 50MB per isolate
|
||||
- **Console**: logger에 바인딩됨
|
||||
- 관련 코드: `server/src/services/ScriptEngine.ts`, `server/src/services/ScriptExecutor.ts`
|
||||
69
docs/server.md
Normal file
69
docs/server.md
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# Server (Express + TypeScript)
|
||||
|
||||
진입점: `server/src/index.ts`
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
server/src/
|
||||
index.ts # Express 앱 팩토리 (CORS, 라우트 설정, health 엔드포인트)
|
||||
config/
|
||||
database.ts # Core SQLite 연결 및 스키마 초기화
|
||||
analytics-db.ts # Analytics SQLite 연결 및 스키마 초기화
|
||||
models/
|
||||
User.ts # 사용자 CRUD (create, findById, findByApiKey, update, delete, regenerateApiKey)
|
||||
Backend.ts # 백엔드 CRUD (create, findById, findAll, activate/deactivate)
|
||||
Permission.ts # 권한 관리 (user-backend 매핑)
|
||||
Script.ts # 스크립트 CRUD (타입별 필터링, 활성화/비활성화)
|
||||
routes/
|
||||
index.ts # 라우트 마운팅
|
||||
auth.ts # Bearer 토큰 인증 미들웨어 (API 키 검증, 권한 로드)
|
||||
api.ts # OpenAI 호환 프록시 엔드포인트 (/v1/chat/completions, /v1/models)
|
||||
admin.ts # Admin CRUD 엔드포인트 (users, backends, permissions)
|
||||
scripts.ts # Script 관리 엔드포인트
|
||||
analytics.ts # Analytics 조회 엔드포인트
|
||||
services/
|
||||
RouterService.ts # 백엔드 선택 (랜덤 로드밸런싱) 및 HTTP 요청 포워딩
|
||||
AnalyticsService.ts # 요청 로깅, 일별 사용량/메트릭 집계
|
||||
ScriptEngine.ts # 스크립트 체인 오케스트레이션 (onRequest/onResponse 훅 적용)
|
||||
ScriptExecutor.ts # isolated-vm 기반 스크립트 컴파일/실행 (5s timeout, 50MB memory)
|
||||
utils/
|
||||
apiKey.ts # API 키 생성 (sk-{timestamp}-{random}, crypto.randomBytes)
|
||||
logger.ts # 컬러 콘솔 로거
|
||||
```
|
||||
|
||||
## Request Flow
|
||||
|
||||
```
|
||||
Client → auth.ts (API 키 검증, 권한 로드)
|
||||
→ RouterService.selectBackend (랜덤 선택)
|
||||
→ ScriptEngine.applyOnRequestScripts (요청 변조)
|
||||
→ RouterService.forwardRequest (백엔드 프록시)
|
||||
→ ScriptEngine.applyOnResponseScripts (응답 변조)
|
||||
→ AnalyticsService.logRequest (로깅)
|
||||
→ Response
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Purpose |
|
||||
|---------|---------|
|
||||
| express@5 | 웹 프레임워크 |
|
||||
| better-sqlite3 | SQLite 드라이버 |
|
||||
| isolated-vm | 스크립트 샌드박스 실행 |
|
||||
| zod | 입력 검증 |
|
||||
| node-fetch | 백엔드 HTTP 요청 |
|
||||
| cors | CORS 미들웨어 |
|
||||
| dotenv | 환경변수 로딩 |
|
||||
|
||||
## Tests
|
||||
|
||||
통합 테스트: `server/tests/integration/`
|
||||
- `api.test.ts` — 인증, 인가, 프록시 엔드포인트
|
||||
- `admin.test.ts` — Admin CRUD
|
||||
- `routing.test.ts` — 백엔드 선택, 요청 포워딩
|
||||
- `scripts.test.ts` — 스크립트 생성, 실행, 훅
|
||||
|
||||
테스트 유틸: `server/tests/integration/utils/` (testApp.ts, mockBackend.ts)
|
||||
|
||||
벤치마크: `server/benchmarks/` (runner.ts, scenarios.ts, report.ts, stats.ts)
|
||||
Loading…
Add table
Add a link
Reference in a new issue