npm package: @fuzionx/framework
Description: Full-stack MVC framework built on @fuzionx/core — Controller, Service, Model, Middleware, DI, EventBus
Latest version: 0.1.69

# @fuzionx/framework

> Laravel-inspired full-stack MVC framework powered by Rust N-API bridge, achieving an unprecedented **618K+ Req/Sec** in the Node.js ecosystem.

```
@fuzionx/framework          ← npm install (개발자가 설치)
  └── @fuzionx/core          ← HTTP 엔진 (libuv Fusion, WebSocket, 세션, 크립토)
      └── @fuzionx/bridge    ← Rust N-API 네이티브 모듈
```

---

## Quick Start

```bash
# 글로벌 CLI 설치 (fx + create-fuzionx)
npm install -g create-fuzionx

# 프로젝트 생성
fx new my-app
# 또는: npx create-fuzionx my-app

cd my-app
npm install

# 개발 서버
fx dev              # 또는: npx fx dev

# 또는 직접 실행
node app.js
```

서버가 `http://localhost:49080` 에서 시작됩니다.

---

## 🚀 Why FuzionX? (The Differentiator)

FuzionX is not just another framework wrapper. It fundamentally redesigns how HTTP requests are handled in the Node.js ecosystem by shifting heavy networking and parsing logic to Rust.

- **Rust N-API Direct TCP Handling**: Bypasses the standard Node.js `http` parser. Raw TCP buffers are processed at native speeds via Rust's LibUV bindings, maximizing I/O efficiency.
- **Kernel-Level Load Balancing (`SO_REUSEPORT`)**: Completely eliminates the single-thread IPC bottlenecks and PM2 cluster routing overhead. The OS kernel directly distributes incoming connections across all available CPU cores.
- **Zero-Allocation Dispatch Pipeline**: Reusable Context (`ctx`) design and optimized closures drastically minimize V8 Garbage Collection (GC) pressure, reducing tail latencies under heavy concurrent loads.
- **Full-Stack with S-Tier Speed**: Offers a robust Laravel-inspired MVC Developer Experience (ORM, i18n, WebSockets, Schedulers) while delivering routing and throughput capabilities normally reserved for hyper-optimized minimalist C++ servers like `uWebSockets.js`.

---

## 📊 Performance Benchmark

**Hardware Environment**: Intel® Core™ Ultra 9 285H (16 Cores), 16GB RAM  
**Test Configuration**: `wrk -t4 -c100 -d10s /api/benchmark` (Routing & Framework fully active, Sessions disabled)

| Framework | Req/sec | Avg Latency | Max Latency |
|:---|---:|---:|---:|
| 🥇 **FuzionX** (SO_REUSEPORT) | **618,521** | **172.07µs** | **13.03ms** |
| 🥈 Node.js (Pure HTTP + PM2) | 393,264 | 278.33µs | 37.26ms |
| 🥉 Fastify (PM2) | 278,526 | 393.45µs | 43.65ms |
| 4th Express (PM2) | 141,597 | 950.00µs | 66.91ms |

> FuzionX outperforms **Fastify by +122%** and **Node.js Pure HTTP by +57%**, making it one of the absolute fastest full-stack frameworks available in the global JS ecosystem.

---

## 프로젝트 구조

```
my-app/
├── fuzionx.yaml              # 서버 + DB + 세션 설정
├── .env                      # 환경변수
├── app.js                    # 엔트리포인트
│
├── routes/                   # 라우트 정의
│   ├── api.js
│   └── web.js
│
├── controllers/              # HTTP 컨트롤러 (자동 스캔)
│   └── UserController.js
│
├── models/                   # ORM 모델 (자동 스캔)
│   └── User.js
│
├── services/                 # 비즈니스 로직 (자동 스캔)
│   └── UserService.js
│
├── middleware/                # 미들웨어 클래스 (자동 스캔)
│   └── AuthMiddleware.js
│
├── ws/                       # WebSocket 핸들러 (자동 스캔)
├── jobs/                     # 스케줄러/큐 Job (자동 스캔)
├── events/                   # 이벤트 리스너
│
├── views/                    # 템플릿 (Tera SSR / Bridge 렌더링)
│   └── default/
│       ├── layouts/
│       │   └── main.html
│       └── pages/
│           └── home.html
│
├── locales/                  # i18n 번역 파일
│   ├── ko.yaml
│   └── en.yaml
│
├── storage/                  # 로그, 업로드
└── public/                   # 정적 파일
```

---

## 엔트리포인트 (app.js)

```javascript
import { Application } from '@fuzionx/framework';
import apiRoutes from './routes/api.js';
import webRoutes from './routes/web.js';

const app = new Application({ configPath: './fuzionx.yaml' });

// 라우트 등록
app.routes(apiRoutes);
app.routes(webRoutes);

// 서비스 등록 (Lazy 싱글톤)
app.register('mailer', () => new MailService(app.config.get('app.mail')));

// 라이프사이클 훅
app.on('booted', async () => {
    console.log(`DB 연결 완료`);
});

// 서버 시작
app.listen(49080, () => {
    console.log('🚀 FuzionX running on http://localhost:49080');
});
```

---

## 라우팅 & 컨트롤러

### 라우트 파일

```javascript
// routes/api.js
import UserController from '../controllers/UserController.js';
import Joi from 'joi';

export default (r) => {
    r.group('/api', { middleware: ['apiAuth'] }, (r) => {
        r.group('/users', (r) => {
            r.get('/',       UserController.index);
            r.get('/:id',   UserController.show);
            r.post('/',     UserController.store, {
                validate: { body: Joi.object({
                    name: Joi.string().min(2).required(),
                    email: Joi.string().email().required(),
                }) }
            });
            r.put('/:id',    UserController.update);
            r.delete('/:id', UserController.destroy);
        });
    });
};
```

```javascript
// routes/web.js
import HomeController from '../controllers/HomeController.js';

export default (r) => {
    r.get('/', HomeController.index);
    r.get('/about', HomeController.about);
};
```

### 컨트롤러

```javascript
// controllers/UserController.js
import { Controller } from '@fuzionx/framework';

export default class UserController extends Controller {

    async index(ctx) {
        const users = await this.db.User.paginate(ctx.query.page || 1, 20);
        ctx.json(users);
    }

    async show(ctx) {
        const user = await this.db.User.findOrFail(ctx.params.id);
        ctx.json(user);
    }

    async store(ctx) {
        const user = await this.service('UserService').register(ctx.body);
        ctx.status(201).json(user);
    }

    async update(ctx) {
        const user = await this.db.User.findOrFail(ctx.params.id);
        await user.update(ctx.body);
        ctx.json(user);
    }

    async destroy(ctx) {
        await this.service('UserService').deactivate(ctx.params.id);
        ctx.status(204).end();
    }
}
```

미들웨어는 `글로벌 → 그룹 → 라우트별` 3단계로 적용됩니다.

---

## Context (`ctx`)

모든 핸들러, 미들웨어에 전달되는 통합 객체:

### Request

```javascript
ctx.method              // 'GET', 'POST', ...
ctx.url                 // '/users/42?page=1'
ctx.path                // '/users/42'
ctx.params              // { id: '42' }
ctx.query               // { page: '1' }
ctx.body                // JSON 자동 파싱된 요청 바디
ctx.headers             // 요청 헤더
ctx.ip                  // 클라이언트 IP
ctx.user                // 인증된 사용자 (미들웨어에서 설정)
ctx.session             // 세션
ctx.cookies             // 파싱된 쿠키 객체
ctx.locale              // 현재 locale ('ko', 'en')
ctx.files               // 업로드된 파일 메타데이터 배열

ctx.get(header)         // 헤더 값
ctx.is(type)            // Content-Type 확인
ctx.accepts('json','html') // Accept 협상
ctx.t(key, vars)        // i18n 번역
```

### Response

```javascript
ctx.json(data)                     // JSON 응답
ctx.status(201).json(data)         // 상태 코드 + JSON
ctx.send(html)                     // HTML 응답
ctx.text(string)                   // text/plain
ctx.render('home', { title })      // 템플릿 렌더링 (Rust Bridge SSR)
ctx.redirect('/login')             // 302 리다이렉트
ctx.redirect('/new', 301)          // 301 영구 리다이렉트
ctx.back()                         // Referer로 리다이렉트
ctx.error(404, 'Not found')       // 에러 응답
ctx.download(filePath)             // 파일 다운로드
ctx.stream(readable)               // 스트림 응답
ctx.setHeader(key, value)          // 헤더 설정
ctx.cookie(name, value, opts)      // 쿠키 설정
ctx.end()                          // 응답 종료
```

---

## Model (ORM)

```javascript
// models/User.js
import { Model } from '@fuzionx/framework';

export default class User extends Model {
    static table = 'users';
    static timestamps = true;
    static hidden = ['password'];

    static columns = {
        id:       { type: 'increments' },
        name:     { type: 'string', length: 100 },
        email:    { type: 'string', length: 150, unique: true },
        password: { type: 'string', length: 255 },
        active:   { type: 'boolean', default: true },
    };

    posts()   { return this.hasMany('Post'); }
    profile() { return this.hasOne('Profile'); }

    static findByEmail(email) {
        return this.where('email', email).first();
    }
}
```

**지원 드라이버**: SQLite · MariaDB · PostgreSQL · MongoDB

---

## Service

```javascript
// services/UserService.js
import { Service } from '@fuzionx/framework';

export default class UserService extends Service {

    async register(data) {
        if (await this.db.User.findByEmail(data.email)) {
            throw this.error('이미 존재하는 이메일');
        }
        const user = await this.transaction(async (trx) => {
            const user = await this.db.User.create(data, { trx });
            await this.db.Profile.create({ userId: user.id }, { trx });
            return user;
        });
        this.emit('user:created', user);
        return user;
    }
}
```

---

## Middleware

```javascript
// middleware/AuthMiddleware.js
import { Middleware } from '@fuzionx/framework';

export default class AuthMiddleware extends Middleware {
    static name = 'auth';

    handle(ctx, next) {
        const token = ctx.headers.authorization?.replace('Bearer ', '');
        if (!token) return ctx.error(401, 'Unauthorized');
        ctx.user = this.service('AuthService').verify(token);
        next();
    }
}
```

### 내장 미들웨어

| 이름 | 기능 | 처리 |
|------|------|------|
| `bodyParser` | JSON/Form 바디 파싱 | JS |
| `cors` | CORS 헤더 | Rust |
| `csrf` | CSRF 토큰 검증 | JS |
| `session` | 세션 로드/저장 | Rust |
| `rateLimit` | 요청 제한 | Rust |
| `static` | 정적 파일 서빙 | Rust |

---

## WebSocket

```javascript
// ws/ChatHandler.js
import { WsHandler } from '@fuzionx/framework';

export default class ChatHandler extends WsHandler {
    static namespace = '/chat';
    static middleware = ['auth'];

    static events(e) {
        e.on('chat', this.handleChat);
        e.on('typing', this.handleTyping);
    }

    handleChat(socket, data) {
        socket.to(`room:${data.roomId}`).send({
            type: 'chat',
            data: { user: socket.user, message: data.message },
        });
    }
}
```

---

## 설정 (`fuzionx.yaml`)

```yaml
bridge:
  port: 49080
  workers: 4              # 0 = CPU 수 자동
  cors:
    enabled: true
    origins: ["*"]
  rate_limit:
    enabled: true
    per_ip: 1000
  session:
    enabled: true
    store: memory          # memory | redis
    ttl: 3600
  logging:
    level: info

database:
  main:
    driver: sqlite
    path: ./storage/database.sqlite

app:
  name: 'My App'
  environment: ${NODE_ENV:development}
  auth:
    secret: ${JWT_SECRET:change-me}
    accessTtl: '15m'
  i18n:
    default_locale: 'ko'
```

### 환경변수 치환

```yaml
host: ${DB_HOST:127.0.0.1}     # 없으면 기본값 사용
password: ${DB_PASSWORD}        # 필수 — 없으면 부트 시 에러
redis_url: ${REDIS_URL:}        # 선택 — 없으면 빈 문자열
```

### Config 접근

```javascript
app.config.get('bridge.port')                    // 49080
app.config.get('app.auth.secret')                // JWT secret
app.config.get('app.payment.api_key', null)      // 커스텀 설정 + 기본값
```

---

## CLI

### 프로젝트 생성 (`create-fuzionx`)

```bash
npx create-fuzionx my-app            # 새 프로젝트 스캐폴딩
cd my-app
npm install
```

### 프로젝트 내 명령어 (`fx`)

```bash
npx fx make:controller User          # CRUD 컨트롤러
npx fx make:model User               # ORM 모델
npx fx make:service User             # 서비스
npx fx make:middleware Auth           # 미들웨어
npx fx make:job Cleanup              # 스케줄 Job
npx fx make:task SendEmail           # 큐 Task
npx fx make:ws Chat                  # WebSocket 핸들러
npx fx make:event user               # 이벤트 핸들러
npx fx make:worker Heavy             # Worker (worker_threads)
npx fx make:test User                # 테스트

# DB
npx fx db:sync                       # 모델 ↔ DB 스키마 diff
npx fx db:sync --apply               # 안전 변경 적용

# 개발
npx fx dev                           # 개발 서버 (--watch)
npx fx dev --port=4000               # 포트 지정
npx fx test                          # 테스트 실행 (vitest)
npx fx routes                        # 라우트 테이블 출력
npx fx config                        # 설정 파싱 결과 출력
```

---

## 부트스트랩 순서

```
app.js 실행
  ├── 1. Config 로드           fuzionx.yaml 파싱
  ├── 2. .env 로드             환경변수 주입
  ├── 3. Bridge 부트            Rust 네이티브 초기화
  │      ★ emit('booting')
  ├── 4. DB 연결                Knex/Mongoose
  ├── 5. 모델 로드              models/ 자동 스캔
  │      ★ emit('booted')
  ├── 6. i18n 로드              locales/ 번역 파일
  ├── 7~12. 자동 스캔           services, middleware, controllers,
  │                             ws, jobs, events
  │      ★ emit('ready')
  └── 13. 서버 시작              startFusionServer(port)
         ★ emit('listening')
```

### 라이프사이클 훅

| 훅 | 시점 | 용도 |
|---|------|------|
| `booting` | Config 로드 직후 | 서비스 등록, 환경 설정 |
| `booted` | DB + 모델 로드 완료 | 캐시 워밍 |
| `ready` | 모든 초기화 완료 | 준비 로그 |
| `listening` | 서버 시작 완료 | 포트 표시 |
| `shutdown` | SIGTERM/SIGINT | 리소스 정리 |

---

## 에러 처리

| 에러 타입 | HTTP | JSON | HTML |
|-----------|:----:|------|------|
| ValidationError | 422 | `{ error, fields }` | flash + redirect |
| ServiceError | 400/403/404 | `{ error }` | 테마 에러 페이지 |
| Error (dev) | 500 | `{ error, stack }` | 에러 페이지 + 스택 |
| Error (prod) | 500 | `{ error }` | 에러 페이지 |

---

## 주요 특징

- ⚡ **618K+ Req/Sec** — Rust N-API Bridge (libuv + SO_REUSEPORT)
- 🦀 **Rust 네이티브** — HTTP, 세션, CORS, Rate Limit, 암호화 모두 Rust 처리
- 🎯 **MVC 아키텍처** — Controller, Service, Model 분리
- 📦 **자동 스캔** — controllers/, models/, services/ 등 자동 로드
- 🔌 **WebSocket** — 네임스페이스 기반 이벤트 라우팅
- 🗄️ **Multi-DB ORM** — SQLite, MariaDB, PostgreSQL, MongoDB
- 🔐 **Auth & Session** — JWT + 세션 (Memory/Redis)
- 📡 **EventBus** — 도메인 이벤트 + Hub 연동 (멀티서버)
- ⏰ **Scheduler & Queue** — Job (cron), Task (큐)
- 🌍 **i18n** — 다국어 지원, `ctx.t()`, locale 자동 감지
- 🎨 **Tera SSR** — Rust 기반 템플릿 렌더링
- 📄 **OpenAPI** — 자동 Swagger 문서 생성

---

## License

MIT