npm package: @ssafy-mhk/e-ver
Description: React 기반 가상 피팅 SDK입니다. `generate-3d`로 생성한 의류 GLB를 불러오고, 웹캠과 MediaPipe Pose 추적을 이용해 body preset 기반 가상 피팅 씬을 구성할 수 있습니다.
Latest version: 1.0.7

# `@ssafy-mhk/e-ver`

React 기반 가상 피팅 SDK입니다. `generate-3d`로 생성한 의류 GLB를 불러오고, 웹캠과 MediaPipe Pose 추적을 이용해 body preset 기반 가상 피팅 씬을 구성할 수 있습니다.

현재 SDK가 책임지는 범위는 다음입니다.

- 의류 생성 API client와 생성 플로우
- webcam, pose tracking, body measurement, body preset selection
- tracked garment 렌더링
- 최종 보정이 반영된 `finalGarmentScale` 계산

현재 SDK가 책임지지 않는 범위는 다음입니다.

- 패널 UI, 디버그 UI, overlay
- foreground occlusion 같은 앱 전용 시각 효과
- 사진 기반 개인 avatar 생성

## 설치

```bash
pnpm add @ssafy-mhk/e-ver
```

필수 peer dependency:

```bash
pnpm add react react-dom three @react-three/fiber @react-three/drei @mediapipe/tasks-vision zustand
```

## 서버와 인증

기본 API 서버는 `http://localhost:8000/api/v1`입니다.

```tsx
import { EverClient } from "@ssafy-mhk/e-ver";

const client = new EverClient();

const publicClient = new EverClient({
  apiKey: "ever_live_xxxxxxxx",
  baseUrl: "http://localhost:8080/api/v1",
});
```

`useEverGeneration`도 동일하게 `apiKey`를 받을 수 있습니다.

## 권장 사용 흐름

가장 권장되는 경로는 아래입니다.

1. `useEverGeneration`으로 의류 생성
2. 생성이 끝나면 `resultUrl` 확보
3. `EverFittingScene`에 `garmentUrl={resultUrl}` 전달
4. `onRuntimeStateChange`에서 `measurements`, `bodyPresetSelection`, `finalGarmentScale` 소비

## 핵심 API

| 분류     | 모듈                     | 역할                                                                       |
| -------- | ------------------------ | -------------------------------------------------------------------------- |
| Client   | `EverClient`             | body preset 조회/매칭, garment 생성, 이미지 업로드, `generate-3d`, polling |
| Hook     | `useEverGeneration`      | 의류 생성 플로우를 훅으로 제공                                             |
| Scene    | `EverFittingScene`       | webcam, tracking, measurement, body preset selection, garment 렌더링 통합  |
| Scene    | `EverTrackedGarment`     | 준비된 의류 GLB를 추적 렌더링                                              |
| Hook     | `useEverFitting`         | 고수준 fitting runtime 상태 제공                                           |
| Hook     | `useBodyPresetSelection` | 측정값 기반 body preset 자동 선택                                          |
| Renderer | `EverCanvas`             | 저수준 R3F canvas wrapper                                                  |

## Quick Start

```tsx
import { EverFittingScene, useEverGeneration } from "@ssafy-mhk/e-ver";

function Demo() {
  const { createGarment, resultUrl, status } = useEverGeneration({
    apiKey: process.env.NEXT_PUBLIC_EVER_API_KEY,
  });

  const handleGenerate = async () => {
    await createGarment(
      { name: "오버핏 셔츠", category: "top" },
      frontImageBlob,
      backImageBlob,
    );
  };

  return (
    <div className="relative h-screen w-full">
      <button onClick={handleGenerate} disabled={status !== "idle"}>
        3D 생성
      </button>

      <EverFittingScene
        garmentUrl={resultUrl}
        enabled
        measurementEnabled
        autoStartMeasurement
        fitType="regular"
        onRuntimeStateChange={(runtime) => {
          console.log(runtime.measurements);
          console.log(runtime.bodyPresetSelection);
          console.log(runtime.finalGarmentScale);
        }}
      />
    </div>
  );
}
```

## 생성 API

### `useEverGeneration`

`createGarment`는 아래 순서를 묶습니다.

1. garment 생성
2. front/back 이미지 업로드
3. `generate-3d` 요청
4. 의류 모델 준비 완료까지 polling

```tsx
import { useEverGeneration } from "@ssafy-mhk/e-ver";

function Generator() {
  const { createGarment, resultUrl, status, error } = useEverGeneration();

  return (
    <>
      <button
        onClick={() =>
          createGarment(
            { name: "니트", category: "top" },
            frontImageBlob,
            backImageBlob,
          )
        }
      >
        생성
      </button>
      <p>{status}</p>
      {error ? <p>{error}</p> : null}
      {resultUrl ? <p>{resultUrl}</p> : null}
    </>
  );
}
```

## 고수준 Scene

### `EverFittingScene`

가장 권장되는 엔트리입니다. 내부에서 다음을 수행합니다.

- webcam 준비
- MediaPipe Pose tracking
- 측정값 계산
- body preset 선택
- tracked garment 렌더링
- 최종 보정 scale 계산

주요 props:

- `garmentUrl: string | null`
- `enabled?: boolean`
- `measurementEnabled?: boolean`
- `autoStartMeasurement?: boolean`
- `fitType?: "slim" | "regular" | "oversize"`
- `garmentScaleHint?: number | null`
- `onRuntimeStateChange?: (runtime) => void`
- `onGarmentLoadStateChange?: (state) => void`

`runtime`에서 특히 많이 쓰는 값:

- `measurements`
- `bodyPresetSelection`
- `sizeRecommendation`
- `garmentScale`
- `finalGarmentScale`
- `bodyMorphResult`
- `isTracking`
- `webcamError`

## 저수준 조립

직접 조립이 필요하면 `useEverFitting`과 `EverTrackedGarment`를 사용할 수 있습니다.

```tsx
import {
  EverCanvas,
  EverTrackedGarment,
  useEverFitting,
} from "@ssafy-mhk/e-ver";

function CustomScene({ garmentUrl }: { garmentUrl: string }) {
  const fitting = useEverFitting({
    enabled: true,
    fitType: "oversize",
    garmentScaleHint: 1.04,
  });

  return (
    <EverCanvas showEnvironment={false}>
      <EverTrackedGarment
        url={garmentUrl}
        landmarks={fitting.landmarks}
        worldLandmarks={fitting.worldLandmarks}
        poseFrameWidth={fitting.poseFrameWidth}
        poseFrameHeight={fitting.poseFrameHeight}
      />
    </EverCanvas>
  );
}
```

## fitting 결과

`finalGarmentScale`은 아래 요소를 합성한 최종 결과입니다.

- body measurement 기반 scale
- body preset selection
- `fitType`
- `garmentScaleHint`

showcase와 동일한 fitting 결과가 필요하면 소비 앱에서 별도 보정하지 말고 `runtime.finalGarmentScale`을 그대로 사용하면 됩니다.

## 주의 사항

**`generateAvatar`는 사진 기반 개인 avatar 생성이 아닙니다.**  
현재 버전에서는 body preset 매칭을 통해 기본 아바타 모델 URL을 찾습니다.

**SDK는 UI kit이 아닙니다.**  
측정 패널, 디버그 패널, overlay는 소비 앱에서 조립해야 합니다.

**SDK 범위는 body preset 기반 fitting입니다.**  
개인 사진 기반 avatar 생성이나 앱 전용 시각 효과는 현재 범위 밖입니다.