feat(docs): 문서 정리
This commit is contained in:
parent
5bb3820784
commit
c78338fc11
8 changed files with 454 additions and 667 deletions
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