update(docs)
This commit is contained in:
parent
0441774df2
commit
e09992f851
5 changed files with 60 additions and 34 deletions
|
|
@ -9,6 +9,7 @@
|
|||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| GET | `/health` | 서버 상태 확인 (status, timestamp) |
|
||||
| GET | `/admin/health` | Admin 라우터 상태 확인 (status, timestamp) |
|
||||
|
||||
## OpenAI-Compatible Proxy (인증 필요)
|
||||
|
||||
|
|
@ -65,7 +66,7 @@
|
|||
| DELETE | `/admin/scripts/:id` | 스크립트 삭제 |
|
||||
| POST | `/admin/scripts/:id/activate` | 스크립트 활성화 |
|
||||
| POST | `/admin/scripts/:id/deactivate` | 스크립트 비활성화 |
|
||||
| POST | `/admin/scripts/:id/test` | 스크립트 테스트 실행 |
|
||||
| POST | `/admin/scripts/:id/test` | 스크립트 테스트 실행 (`request` 필수, `user`/`backend` 선택) |
|
||||
|
||||
### Analytics
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
# Client UI Kit Workbench
|
||||
|
||||
`client`의 새 UI kit은 실제 라우트와 분리된 공통 레이어로 구성한다. 목적은 기존 인라인 스타일을 바로 교체하는 것이 아니라, 먼저 Storybook에서 조밀한 운영 콘솔 스타일을 검토하고 안정화한 뒤 앱으로 이식하는 것이다.
|
||||
`client`의 UI kit은 실제 라우트와 Storybook이 함께 사용하는 공통 레이어다. 초기 목적은 workbench 검증이었지만, 현재는 앱 셸과 주요 페이지 패턴에도 연결되어 있다.
|
||||
|
||||
## 구성
|
||||
|
||||
- `client/src/ui/styles.css`
|
||||
- 전역 semantic token, density, light/dark theme, 공통 primitive class
|
||||
- 전역 semantic token 진입점, 하위 style 레이어 import
|
||||
- `client/src/ui/primitives`
|
||||
- `@kobalte/core` wrapper와 공통 스타일 계약
|
||||
- `client/src/ui/patterns`
|
||||
- `DataGrid`, `LogConsole`, `CommandBar`, `FieldRow`, `StatusBadge`
|
||||
- `AppShell`, `DataGrid`, `LogConsole`, `CommandBar`, `FieldRow`, `StatusBadge` 등
|
||||
- `client/src/ui/index.ts`
|
||||
- app/routes 에서 사용하는 primitives/patterns 재수출
|
||||
- `client/src/ui/stories`
|
||||
- primitive와 pattern 검토용 Storybook stories
|
||||
- `client/.storybook`
|
||||
|
|
@ -32,6 +34,12 @@
|
|||
- `LogConsole`
|
||||
- dense metadata cluster
|
||||
|
||||
현재 반영:
|
||||
|
||||
- `Layout` → `AppShell`
|
||||
- `Users`, `Backends`, `Permissions`, `Analytics`, `DetailLogs`, `Scripts` 에서 공통 패턴 사용
|
||||
- Storybook preview 에서 동일한 `client/src/ui/styles.css` 를 로드
|
||||
|
||||
## 실행
|
||||
|
||||
```bash
|
||||
|
|
@ -42,6 +50,6 @@ pnpm --filter client build-storybook
|
|||
## 원칙
|
||||
|
||||
- 앱 코드에서 `@kobalte/core` primitive를 직접 사용하지 않는다.
|
||||
- 새 스타일은 Storybook에서 먼저 검토하고, 이후 라우트에 연결한다.
|
||||
- 새 스타일은 가능하면 Storybook에서 먼저 검토하고, 이후 라우트에 반영한다.
|
||||
- 대용량 표는 pagination 우선을 기본으로 한다.
|
||||
- 로그 콘솔은 1차에서 읽기 중심으로 유지하고, streaming append는 후속 확장으로 둔다.
|
||||
|
|
|
|||
|
|
@ -7,22 +7,29 @@ Admin 대시보드. 진입점: `client/src/index.tsx`
|
|||
```
|
||||
client/src/
|
||||
index.tsx # DOM 렌더링 진입점
|
||||
App.tsx # 라우터 정의 (6개 라우트)
|
||||
App.tsx # 라우터 정의 (7개 라우트)
|
||||
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, detail_logging)
|
||||
Permissions.tsx # 권한 관리 — user-backend 매핑
|
||||
Analytics.tsx # 분석 — 월별 요청 로그, 사용량 통계, 백엔드 메트릭
|
||||
Scripts.tsx # 스크립트 관리 — CRUD, 테스트, 활성화/비활성화
|
||||
Dashboard.tsx # 홈 — 운영 요약 스트립 + 최근 요청 테이블
|
||||
Users.tsx # 사용자 관리 — CRUD, API 키 재발급, 검색, 상세 로깅 토글
|
||||
Backends.tsx # 백엔드 관리 — CRUD (name, base_url, api_key, detail_logging, is_active)
|
||||
Permissions.tsx # 권한 관리 — user-backend 매핑, 추가/회수
|
||||
Analytics.tsx # 분석 — 최근 요청, 사용량 집계, 백엔드 메트릭 패널
|
||||
DetailLogs.tsx # 상세 로그 탐색 — 월/일/검색/사용자/백엔드 필터 + 페이징 + 페이로드 인스펙터
|
||||
Scripts.tsx # 스크립트 관리 — 목록, 요약, 편집기, 테스트, 활성화/비활성화
|
||||
components/
|
||||
Layout.tsx # 사이드바 네비게이션 + 메인 콘텐츠 레이아웃
|
||||
EditModal.tsx # 범용 편집 모달 (동적 폼 필드)
|
||||
Layout.tsx # AppShell 래퍼
|
||||
EditModal.tsx # 레거시 범용 편집 모달
|
||||
ScriptEditor.tsx # Monaco 에디터 래퍼 (TypeScript 하이라이팅)
|
||||
ui/
|
||||
index.ts # primitives/patterns 재수출
|
||||
primitives/ # Button, Dialog, Select, Tabs, TextField 등
|
||||
patterns/ # AppShell, DataGrid, PageHeader, SummaryStrip 등
|
||||
styles/ # token/base/layout/pattern CSS 레이어
|
||||
stories/ # Storybook workbench 스토리
|
||||
```
|
||||
|
||||
## Routes
|
||||
|
|
@ -33,14 +40,18 @@ client/src/
|
|||
| `/users` | Users | 사용자 관리 |
|
||||
| `/backends` | Backends | 백엔드 관리 |
|
||||
| `/permissions` | Permissions | 권한 관리 |
|
||||
| `/analytics` | Analytics | 분석 대시보드 |
|
||||
| `/analytics` | Analytics | 집계 기반 분석 대시보드 |
|
||||
| `/detail-logs` | DetailLogs | 상세 요청 로그 탐색/인스펙션 |
|
||||
| `/scripts` | Scripts | 스크립트 관리 |
|
||||
|
||||
## Styling
|
||||
|
||||
CSS 프레임워크 없음. 인라인 `style` props 사용.
|
||||
- 다크 사이드바 (#1e293b), 라이트 배경 (#f1f5f9), 화이트 카드
|
||||
- Flexbox / Grid 레이아웃
|
||||
공통 UI 레이어는 `client/src/ui/styles.css` 에서 시작하며, 내부적으로 `tokens.css`, `base.css`, `layout.css`, `patterns.css`, `pages.css` 를 불러온다.
|
||||
|
||||
- `@kobalte/core` 기반 primitive wrapper와 공통 pattern을 사용한다.
|
||||
- 페이지는 `AppShell`, `PageHeader`, `Panel`, `DataGrid`, `SummaryStrip`, `FormDialog`, `ConfirmDialog` 조합으로 구성된다.
|
||||
- Storybook(`client/.storybook`)에서 같은 스타일 레이어를 사용해 workbench를 유지한다.
|
||||
- 라이트/다크 테마와 dense 콘솔형 레이아웃을 기본 전제로 한다.
|
||||
|
||||
## Dependencies
|
||||
|
||||
|
|
@ -48,6 +59,8 @@ CSS 프레임워크 없음. 인라인 `style` props 사용.
|
|||
|---------|---------|
|
||||
| solid-js | UI 프레임워크 |
|
||||
| @solidjs/router | 클라이언트 사이드 라우팅 |
|
||||
| @kobalte/core | headless UI primitive |
|
||||
| lucide-solid | 아이콘 세트 |
|
||||
| solid-monaco | Monaco 에디터 통합 |
|
||||
| vite | 빌드 도구 + 개발 서버 |
|
||||
|
||||
|
|
@ -57,5 +70,6 @@ CSS 프레임워크 없음. 인라인 `style` props 사용.
|
|||
|
||||
## Analytics Notes
|
||||
|
||||
- 요청 로그 조회는 월별 request_logs 파일을 대상으로 한다.
|
||||
- analytics API 클라이언트는 `month`, `date`, `q`, `limit`, `offset` 등 필터를 지원한다.
|
||||
- `Analytics` 화면은 최근 요청/사용량/메트릭의 집계 뷰를 보여준다.
|
||||
- 상세 요청 로그 탐색은 별도 `DetailLogs` 화면에서 처리한다.
|
||||
- analytics API 클라이언트는 `month`, `date`, `q`, `limit`, `offset`, `userId`, `backendId`, `endpoint`, `detailLogged` 필터를 지원한다.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ isolated-vm 기반 JavaScript 샌드박스에서 요청/응답을 조작하는
|
|||
|
||||
### onResponse
|
||||
|
||||
백엔드 응답 수신 후 실행. context를 수정하여 응답을 변조할 수 있다.
|
||||
백엔드 응답 수신 후 실행. 현재 구현에서는 응답 컨텍스트를 검사하거나 로그/부가 처리를 수행하는 용도로 실행되며, 훅이 반환한 변경 내용이 최종 HTTP 응답에 다시 반영되지는 않는다.
|
||||
|
||||
## Script Context
|
||||
|
||||
|
|
@ -36,6 +36,7 @@ interface ScriptContextData {
|
|||
참고:
|
||||
- `request.body`, `response.body`는 직렬화 가능한 값이며 보통 JSON 객체로 전달된다.
|
||||
- 스크립트가 body를 수정하면 라우터가 업스트림 전송 전에 최종 body를 기준으로 직렬화하고 `content-length`를 다시 계산한다.
|
||||
- `response` 필드는 실제 프록시 요청의 `onResponse` 단계에서 채워진다. `/admin/scripts/:id/test` 는 훅 존재 여부와 실행 가능성 확인용에 가깝다.
|
||||
|
||||
## Example
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
```
|
||||
server/src/
|
||||
index.ts # Express 앱 팩토리 (CORS, 라우트 설정, health 엔드포인트)
|
||||
index.ts # Express 앱 팩토리 (CORS, 라우트 마운트, health 엔드포인트)
|
||||
config/
|
||||
db-paths.ts # DB_DIR 기준 파일 경로 계산
|
||||
database.ts # Core SQLite 연결 및 스키마 초기화
|
||||
|
|
@ -14,19 +14,18 @@ server/src/
|
|||
request-logs-db.ts # 월별 request_logs SQLite 연결 및 스키마 초기화
|
||||
models/
|
||||
User.ts # 사용자 CRUD (create, findById, findByApiKey, update, delete, regenerateApiKey)
|
||||
Backend.ts # 백엔드 CRUD (create, findById, findAll, activate/deactivate)
|
||||
Backend.ts # 백엔드 CRUD (create, findById, findAll, update, delete)
|
||||
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 관리 엔드포인트
|
||||
admin.ts # Admin CRUD 엔드포인트 (users, backends, permissions, /admin/health, /admin/scripts 마운트)
|
||||
scripts.ts # Script 관리/테스트 엔드포인트
|
||||
analytics.ts # Analytics 조회 엔드포인트
|
||||
services/
|
||||
RouterService.ts # 백엔드 선택 (랜덤 로드밸런싱), HTTP 요청 포워딩, body/content-length 정규화
|
||||
AnalyticsService.ts # 일별 사용량/메트릭 집계
|
||||
RouterService.ts # 활성 백엔드 선택, HTTP 요청 포워딩, header/body 정규화
|
||||
AnalyticsService.ts # 일별 사용량/메트릭 집계 + request_logs 조회
|
||||
RequestLogService.ts # 월별 request_logs 기록/조회
|
||||
ScriptEngine.ts # 스크립트 체인 오케스트레이션 (onRequest/onResponse 훅 적용)
|
||||
ScriptExecutor.ts # isolated-vm 기반 스크립트 컴파일/실행 (5s timeout, 50MB memory)
|
||||
|
|
@ -40,14 +39,18 @@ server/src/
|
|||
|
||||
```
|
||||
Client → auth.ts (API 키 검증, 권한 로드)
|
||||
→ RouterService.selectBackend (랜덤 선택)
|
||||
→ RouterService.selectBackend (허용된 활성 백엔드 중 1개 선택)
|
||||
→ ScriptEngine.applyOnRequestScripts (요청 변조)
|
||||
→ RouterService.forwardRequest (백엔드 프록시)
|
||||
→ ScriptEngine.applyOnResponseScripts (응답 변조)
|
||||
→ ScriptEngine.applyOnResponseScripts (응답 컨텍스트 후처리/검사)
|
||||
→ AnalyticsService.logRequest (집계 + 월별 request_logs 기록)
|
||||
→ Response
|
||||
```
|
||||
|
||||
참고:
|
||||
- 라우트 마운트는 `server/src/index.ts` 에서 직접 수행한다.
|
||||
- `onResponse` 훅은 실행되지만, 현재 구현에서는 훅 반환값을 최종 HTTP 응답에 다시 반영하지 않는다.
|
||||
|
||||
## Time & Storage
|
||||
|
||||
- DB 루트는 `DB_DIR`로 설정한다. 파일은 `core.db`, `analytics.db`, `request_logs/request_logs_YYYY-MM.db` 구조로 생성된다.
|
||||
|
|
@ -62,7 +65,6 @@ Client → auth.ts (API 키 검증, 권한 로드)
|
|||
| better-sqlite3 | SQLite 드라이버 |
|
||||
| isolated-vm | 스크립트 샌드박스 실행 |
|
||||
| zod | 입력 검증 |
|
||||
| node-fetch | 백엔드 HTTP 요청 |
|
||||
| cors | CORS 미들웨어 |
|
||||
| dotenv | 환경변수 로딩 |
|
||||
|
||||
|
|
@ -74,9 +76,9 @@ Client → auth.ts (API 키 검증, 권한 로드)
|
|||
- `routing.test.ts` — 백엔드 선택, 요청 포워딩
|
||||
- `scripts.test.ts` — 스크립트 생성, 실행, 훅
|
||||
|
||||
테스트 유틸: `server/tests/integration/utils/` (testApp.ts, mockBackend.ts)
|
||||
테스트 유틸: `server/tests/utils/` (`testApp.ts`, `mockBackend.ts`)
|
||||
|
||||
벤치마크: `server/benchmarks/` (runner.ts, scenarios.ts, report.ts, stats.ts)
|
||||
벤치마크: `server/benchmarks/` (`index.ts`, `runner.ts`, `scenarios.ts`, `report.ts`, `stats.ts`)
|
||||
|
||||
사용 문서:
|
||||
- [docs/benchmarks.md](/C:/Users/user/Sync/Workspace/kyush-llm-router/docs/benchmarks.md) - benchmark CLI usage, modes, output, caveats
|
||||
- [docs/benchmarks.md](./benchmarks.md) - benchmark CLI usage, modes, output, caveats
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue