# Label Studio Integration - 구현 가이드

## 개요

Things-Factory와 Label Studio의 완전한 통합을 위한 구현이 완료되었습니다.

## 구현된 기능

### ✅ Phase 1: 프로젝트 및 태스크 관리

#### 1. 프로젝트 관리 GraphQL API

**Query:**
```graphql
# 프로젝트 목록 조회
query {
  labelStudioProjects {
    id
    title
    description
    taskCount
    completedTaskCount
    completionRate
    createdAt
    updatedAt
  }
}

# 단일 프로젝트 조회
query {
  labelStudioProject(projectId: 1) {
    id
    title
    labelConfig
  }
}

# 프로젝트 통계
query {
  labelStudioProjectMetrics(projectId: 1) {
    totalTasks
    completedTasks
    completionRate
    annotatorStats {
      email
      annotationCount
      avgTime
    }
  }
}
```

**Mutation:**
```graphql
# 프로젝트 생성
mutation {
  createLabelStudioProject(input: {
    title: "New Project"
    description: "Project description"
    labelConfig: "<View>...</View>"
  }) {
    id
    title
  }
}

# 프로젝트 삭제
mutation {
  deleteLabelStudioProject(projectId: 1)
}
```

#### 2. 태스크 관리 GraphQL API

**Query:**
```graphql
# 태스크 목록
query {
  labelStudioTasks(projectId: 1, page: 1, pageSize: 100) {
    id
    data
    annotationCount
    isCompleted
  }
}

# 어노테이션 조회
query {
  labelStudioTaskAnnotations(taskId: 1) {
    id
    result
    completedBy
    leadTime
  }
}
```

**Mutation:**
```graphql
# 태스크 임포트
mutation {
  importTasksToLabelStudio(
    projectId: 1
    tasks: [
      { data: "{\"text\": \"Sample text\"}" }
    ]
  ) {
    imported
    failed
    taskIds
  }
}

# 어노테이션 익스포트
mutation {
  exportLabelStudioAnnotations(projectId: 1, format: "JSON") {
    exportPath
    annotationCount
    format
  }
}

# 어노테이션 동기화
mutation {
  syncAnnotationsToDatabase(projectId: 1)
}
```

### ✅ Phase 2: 웹훅 및 실시간 동기화

#### 3. 웹훅 관리

**GraphQL API:**
```graphql
# 웹훅 등록
mutation {
  registerLabelStudioWebhook(projectId: 1) {
    id
    url
    isActive
  }
}

# 웹훅 조회
query {
  labelStudioWebhooks(projectId: 1) {
    id
    url
    isActive
  }
}

# 웹훅 삭제
mutation {
  deleteLabelStudioWebhook(webhookId: 1)
}
```

**REST API 엔드포인트:**
```bash
# 웹훅 수신 (Label Studio → Things-Factory)
POST /label-studio/webhook

# 웹훅 등록 (Things-Factory → Label Studio)
POST /label-studio/webhook/register
{
  "projectId": 1
}

# 웹훅 조회
GET /label-studio/webhook/:projectId
```

**지원하는 이벤트:**
- `ANNOTATION_CREATED` - 어노테이션 생성
- `ANNOTATION_UPDATED` - 어노테이션 수정
- `ANNOTATION_DELETED` - 어노테이션 삭제
- `TASK_CREATED` - 태스크 생성
- `PROJECT_UPDATED` - 프로젝트 업데이트

### ✅ Phase 3: ML Backend 연동

#### 4. ML Backend 관리

**GraphQL API:**
```graphql
# ML Backend 조회
query {
  labelStudioMLBackends(projectId: 1) {
    id
    url
    title
    isInteractive
    modelVersion
  }
}

# ML Backend 추가
mutation {
  addMLBackendToProject(
    projectId: 1
    input: {
      url: "http://ml-backend:9090"
      title: "Auto-labeling Model"
      isInteractive: true
    }
  ) {
    id
    url
  }
}

# 예측 실행
mutation {
  triggerLabelStudioPredictions(
    projectId: 1
    taskIds: [1, 2, 3]
  )
}

# 모델 학습
mutation {
  trainLabelStudioModel(mlBackendId: 1)
}
```

### ✅ Phase 4: 클라이언트 UI 컴포넌트

#### 5. UI 컴포넌트

**프로젝트 목록 컴포넌트:**
```html
<label-studio-project-list></label-studio-project-list>
```

**기능:**
- 프로젝트 카드 그리드 뷰
- 프로젝트 통계 표시 (완료율, 태스크 수)
- 프로젝트 생성 버튼
- 프로젝트 클릭 → Label Studio 오픈

## 아키텍처

```
┌─────────────────────────────────────────────────────────────┐
│                    Things-Factory                           │
│                                                              │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────┐  │
│  │   GraphQL    │  │  Webhook     │  │  UI Components   │  │
│  │   Resolvers  │  │  Handler     │  │                  │  │
│  └──────┬───────┘  └──────┬───────┘  └────────┬─────────┘  │
│         │                 │                   │             │
│         └─────────────────┴───────────────────┘             │
│                           │                                 │
│                  ┌────────▼────────┐                        │
│                  │  API Client     │                        │
│                  └────────┬────────┘                        │
└───────────────────────────┼─────────────────────────────────┘
                            │
                   ┌────────▼────────┐
                   │  Label Studio   │
                   │  REST API       │
                   └─────────────────┘
```

## 사용 방법

### 1. 환경 설정

**config/label-studio.config.js:**
```javascript
module.exports = {
  labelStudio: {
    serverUrl: process.env.LABEL_STUDIO_URL,
    apiToken: process.env.LABEL_STUDIO_API_TOKEN
  }
}
```

**.env:**
```bash
LABEL_STUDIO_URL=https://label-studio.example.com
LABEL_STUDIO_API_TOKEN=your-api-token
SERVER_URL=https://things-factory.example.com
```

### 2. 프로젝트 생성 워크플로우

```graphql
# 1. 프로젝트 생성
mutation {
  createLabelStudioProject(input: {
    title: "Image Classification"
    labelConfig: """
      <View>
        <Image name="image" value="$image"/>
        <Choices name="choice" toName="image">
          <Choice value="Cat"/>
          <Choice value="Dog"/>
        </Choices>
      </View>
    """
  }) {
    id
  }
}

# 2. 태스크 임포트
mutation {
  importTasksToLabelStudio(
    projectId: 1
    tasks: [
      { data: "{\"image\": \"https://example.com/cat.jpg\"}" }
    ]
  ) {
    imported
  }
}

# 3. 웹훅 등록 (실시간 업데이트)
mutation {
  registerLabelStudioWebhook(projectId: 1) {
    id
  }
}

# 4. ML Backend 추가 (선택사항)
mutation {
  addMLBackendToProject(
    projectId: 1
    input: {
      url: "http://ml-backend:9090"
      title: "Image Classifier"
    }
  ) {
    id
  }
}
```

### 3. 어노테이션 수집 워크플로우

```graphql
# 1. 어노테이션 조회
query {
  labelStudioTaskAnnotations(taskId: 1) {
    id
    result
    completedBy
  }
}

# 2. 익스포트
mutation {
  exportLabelStudioAnnotations(projectId: 1, format: "JSON") {
    exportPath
    annotationCount
  }
}

# 3. Things-Factory DB에 저장
mutation {
  syncAnnotationsToDatabase(projectId: 1)
}
```

## 확장 포인트

### 1. 커스텀 웹훅 핸들러

`server/route/webhook.ts`에서 핸들러 커스터마이징:

```typescript
async function handleAnnotationCreated(payload: WebhookPayload) {
  // 1. Things-Factory DB에 저장
  // 2. 비즈니스 로직 실행
  // 3. 알림 발송
  // 4. 외부 시스템 연동
}
```

### 2. 데이터 소스 연동

Things-Factory 데이터를 Label Studio로 자동 임포트:

```typescript
// server/service/storage/storage-sync.ts
@Mutation()
async syncBizplaceDataToLabelStudio(
  @Arg('bizplaceId') bizplaceId: string,
  @Arg('projectId') projectId: number
) {
  // Bizplace 데이터 조회
  // Label Studio 태스크로 변환
  // 자동 임포트
}
```

### 3. 어노테이션 결과 활용

```typescript
// server/service/annotation/annotation-processor.ts
@Mutation()
async processAnnotationResults(
  @Arg('projectId') projectId: number
) {
  // 어노테이션 익스포트
  // 결과 분석
  // Things-Factory 엔티티 업데이트
}
```

## 테스트

### GraphQL Playground에서 테스트

```bash
# Things-Factory 실행
yarn workspace @things-factory/operato-mms run serve:dev

# GraphQL Playground 접속
http://localhost:3000/graphql
```

### 웹훅 테스트

```bash
# Webhook 엔드포인트 테스트
curl -X POST http://localhost:3000/label-studio/webhook \
  -H "Content-Type: application/json" \
  -d '{
    "action": "ANNOTATION_CREATED",
    "project": {"id": 1, "title": "Test"},
    "annotation": {
      "id": 1,
      "result": [...]
    }
  }'
```

## 다음 단계

### 추가 개발 항목

1. **실시간 대시보드**
   - 프로젝트별 진행률 실시간 표시
   - 사용자별 생산성 차트
   - 어노테이션 품질 메트릭

2. **데이터 소스 자동 연동**
   - Things-Factory Storage → Label Studio
   - 파일 업로드 자동 감지
   - 태스크 자동 생성

3. **어노테이션 검증**
   - Inter-annotator agreement 계산
   - 품질 관리 워크플로우
   - 자동 리뷰 시스템

4. **Advanced ML 통합**
   - Active Learning 구현
   - 모델 성능 모니터링
   - A/B 테스트 지원

## 참고 자료

- [Label Studio API Documentation](https://labelstud.io/api)
- [Things-Factory Module Development Guide](../../CLAUDE.md)
- [Integration Examples](./docs/examples/)
