E-VER SDK

@ssafy-mhk/e-ver는 React 기반 가상 피팅 SDK입니다. 백엔드 generate-3d와 body preset API를 호출하는 EverClient, 의류 생성용 useEverGeneration, 그리고 webcam/tracking/measurement/rendering을 묶은 EverFittingScene을 제공합니다.

Installation

sh
npm install @ssafy-mhk/e-ver
sh
pnpm add @ssafy-mhk/e-ver
sh
yarn add @ssafy-mhk/e-ver

Peer Dependencies

아래 패키지가 프로젝트에 설치되어 있어야 합니다:

json
{
  "react": ">=16.8.0",
  "react-dom": ">=16.8.0",
  "three": ">=0.150.0",
  "@react-three/fiber": ">=8.0.0",
  "@react-three/drei": ">=9.0.0",
  "@mediapipe/tasks-vision": ">=0.10.0",
  "zustand": ">=4.0.0"
}

EverClient

백엔드 API와 통신하는 핵심 클라이언트입니다. 쿠키 인증과 API Key 인증을 모두 지원합니다.

Constructor

typescript
const client = new EverClient();

const publicClient = new EverClient({
  apiKey: "ever_live_xxxxxxxx",
});
ParameterTypeDefaultDescription
configstring | { baseUrl?: string; apiKey?: string }"http://localhost:8000/api/v1"API 서버 URL 또는 설정 객체

Methods

listBodyPresets

typescript
const presets = await client.listBodyPresets("female");

matchBodyPreset

typescript
const preset = await client.matchBodyPreset({
  gender: "female",
  height_cm: 165,
  chest_cm: 88,
  waist_cm: 68,
});

listGarments

typescript
const result = await client.listGarments({
  category: "top",
  search: "맨투맨",
  page: 1,
  size: 20,
});

getGarment

typescript
const garment = await client.getGarment("garment-uuid");

getPipelineStatus

typescript
const status = await client.getPipelineStatus("garment-uuid");

createGarment

typescript
const garment = await client.createGarment({
  name: "오버핏 맨투맨",
  category: "top",
  description: "편안한 오버핏 디자인",
  material: "cotton",
  price: 39000,
});

uploadGarmentImage

typescript
await client.uploadGarmentImage(garment.id, frontBlob, "front");
await client.uploadGarmentImage(garment.id, backBlob, "back");

generateGarment3D

typescript
await client.generateGarment3D(garment.id, {
  include_measurements: true,
  target_fit_types: ["regular", "slim"],
});

waitForGarmentModel

typescript
const resolvedGarment = await client.waitForGarmentModel(garment.id, {
  intervalMs: 2000,
  timeoutMs: 120000,
});

resolveAssetUrl

typescript
const url = client.resolveAssetUrl("/uploads/garment/front.png");

Quick Start

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

function FittingDemo() {
  const { createGarment, resultUrl } = useEverGeneration();

  const handleGenerate = async () => {
    await createGarment(
      { name: "니트", category: "top" },
      frontImageBlob,
      backImageBlob,
    );
  };

  return (
    <div className="relative h-screen w-full">
      <button onClick={handleGenerate}>3D 생성</button>
      <EverFittingScene
        garmentUrl={resultUrl}
        enabled
        measurementEnabled
        autoStartMeasurement
        fitType="regular"
        onRuntimeStateChange={(runtime) => {
          console.log(runtime.finalGarmentScale);
        }}
      />
    </div>
  );
}

Hooks

useEverGeneration

의류 등록 → 이미지 업로드 → 3D 생성 전체 플로우를 관리하는 훅입니다.

PropertyTypeDescription
statusGenerationStatus"idle" | "uploading" | "processing" | "ready" | "error"
resultUrlstring | null생성된 3D 모델 URL
errorstring | null에러 메시지
generateAvatar(input?) => Promise<string>체형 프리셋 기반 아바타 모델 URL 조회
createGarment(data, front, back?, dims?) => Promise<string>의류 생성 전체 플로우
reset() => void상태 초기화

useEverFitting

웹캠, 포즈 추적, 측정, body preset 선택 상태를 한 번에 반환하는 고수준 훅입니다.

typescript
import { useEverFitting } from "@ssafy-mhk/e-ver";

function RuntimeView() {
  const runtime = useEverFitting({
    enabled: true,
    measurementEnabled: true,
    autoStartMeasurement: true,
    fitType: "regular",
    garmentScaleHint: 1.0,
  });

  return (
    <>
      <p>Tracking: {String(runtime.isTracking)}</p>
      <p>Preset: {runtime.bodyPresetSelection?.presetId}</p>
      <p>Scale X: {runtime.finalGarmentScale.scaleX.toFixed(2)}</p>
    </>
  );
}

useBodyPresetSelection

측정 결과를 바탕으로 body preset을 자동 선택합니다.

typescript
import { useBodyPresetSelection } from "@ssafy-mhk/e-ver";

function PresetBadge({ measurements }) {
  const preset = useBodyPresetSelection(measurements, {
    gender: "female",
    renderMode: "rigged_avatar",
  });

  return (
    <p>{preset.selection.presetId}</p>
  );
}

EverFittingScene

가장 권장되는 고수준 Scene 컴포넌트입니다. webcam, tracking, measurement, garment rendering을 한 번에 제공합니다.

typescript
import { EverFittingScene } from "@ssafy-mhk/e-ver";

function FittingScene({ garmentUrl }) {
  return (
    <EverFittingScene
      garmentUrl={garmentUrl}
      enabled
      measurementEnabled
      autoStartMeasurement
      fitType="regular"
      onRuntimeStateChange={(runtime) => {
        console.log(runtime.measurements);
        console.log(runtime.finalGarmentScale);
      }}
    />
  );
}

EverTrackedGarment

생성된 의류 GLB URL만 이미 확보했다면 EverCanvas 안에서 저수준으로 직접 렌더링할 수 있습니다.


Fitting Scale

EverFittingSceneuseEverFitting은 body preset 선택, 측정값, fit type, garment scale hint를 합성한 최종 보정 결과를 runtime.finalGarmentScale로 제공합니다.

  • fitType: "slim" | "regular" | "oversize"
  • garmentScaleHint: 추가적인 의류 스케일 보정 계수

소비 앱이 showcase와 동일한 fitting 결과를 원한다면 frontend에서 별도 보정하지 말고 finalGarmentScale을 그대로 사용하면 됩니다.

준비된 의류 GLB URL을 canvas 안에서 추적 렌더링하는 저수준 컴포넌트입니다.

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

function Scene({ garmentUrl }) {
  const runtime = useEverFitting({ enabled: true });

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

현재 generateAvatar는 사진 기반 개인 아바타 생성이 아니라 body preset 매칭입니다. 또한 EverFittingScene은 패널 UI까지 포함하지 않으므로, 측정 결과 패널과 디버그 UI는 소비 앱에서 조립해야 합니다.