# Superport API Migration Guide

> **최종 업데이트**: 2025-08-13  
> **분석 대상**: `/Users/maximilian.j.sul/Documents/flutter/superport_api/`  
> **프론트엔드 영향**: Flutter Clean Architecture 기반

## 📋 목차

- [주요 변경사항 요약](#주요-변경사항-요약)
- [Breaking Changes](#breaking-changes)
- [신규 기능](#신규-기능)
- [프론트엔드 마이그레이션](#프론트엔드-마이그레이션)
- [API 엔드포인트 변경사항](#api-엔드포인트-변경사항)
- [데이터베이스 스키마 변경](#데이터베이스-스키마-변경)
- [실행 계획](#실행-계획)

---

## 🚨 주요 변경사항 요약

### ✅ 완료된 주요 기능
1. **소프트 딜리트 시스템 전면 구현**
2. **권한 기반 접근 제어 강화**
3. **API 엔드포인트 표준화**
4. **페이지네이션 최적화**
5. **에러 처리 개선**

### 🔄 변경 영향도 매트릭스

| 영역 | 변경 수준 | 영향도 | 대응 필요도 |
|------|-----------|--------|-------------|
| **Authentication** | 중간 | 🟡 Medium | 토큰 구조 업데이트 |
| **Companies API** | 높음 | 🔴 High | DTO 모델 전면 수정 |
| **Equipment API** | 높음 | 🔴 High | 상태 관리 로직 수정 |
| **Users API** | 중간 | 🟡 Medium | 권한 처리 로직 수정 |
| **Licenses API** | 낮음 | 🟢 Low | 소프트 딜리트 대응 |
| **Overview API** | 신규 | 🔵 New | 새로운 통합 필요 |

---

## ⚠️ Breaking Changes

### 1. 소프트 딜리트 도입

**변경 내용**: 모든 주요 엔티티에서 물리 삭제 → 논리 삭제로 변경

**영향을 받는 API**:
```
DELETE /companies/{id}     → is_active = false
DELETE /equipment/{id}     → is_active = false  
DELETE /licenses/{id}      → is_active = false
DELETE /warehouse-locations/{id} → is_active = false
```

**프론트엔드 수정 필요사항**:
```dart
// Before (기존)
class CompanyListRequest {
  final int? page;
  final int? perPage;
}

// After (수정 필요)
class CompanyListRequest {
  final int? page;
  final int? perPage;
  final bool? isActive;  // 추가 필요
}
```

### 2. 응답 형식 표준화

**변경 내용**: 모든 API 응답이 표준 형식으로 통일

**Before**:
```json
{
  "data": [...],
  "total": 100
}
```

**After**:
```json
{
  "status": "success",
  "message": "Operation completed successfully",
  "data": [...],
  "meta": {
    "pagination": {
      "current_page": 1,
      "per_page": 20,
      "total": 100,
      "total_pages": 5
    }
  }
}
```

### 3. 권한 시스템 변경

**변경 내용**: JWT 클레임 구조 및 권한 체크 로직 강화

**새로운 JWT 구조**:
```json
{
  "sub": 1,           // user_id
  "username": "admin",
  "role": "admin",    // admin|manager|staff
  "exp": 1700000000,
  "iat": 1699999000
}
```

**권한별 접근 제한**:
- `staff`: 조회 권한만, 삭제 권한 없음
- `manager`: 모든 권한, 단 사용자 관리 제외
- `admin`: 모든 권한

---

## 🆕 신규 기능

### 1. Overview API (대시보드용)

**새로운 엔드포인트**:
```
GET /overview/stats              # 대시보드 통계
GET /overview/recent-activities  # 최근 활동
GET /overview/equipment-status   # 장비 상태 분포
GET /overview/license-expiry     # 라이선스 만료 요약
```

**통합 예시**:
```dart
// 새로 추가할 UseCase
class GetDashboardStatsUseCase {
  Future<Either<Failure, DashboardStats>> call(int? companyId) async {
    return await overviewRepository.getDashboardStats(companyId);
  }
}
```

### 2. Lookups API (마스터 데이터)

**새로운 엔드포인트**:
```
GET /lookups          # 전체 마스터 데이터
GET /lookups/type     # 타입별 마스터 데이터
```

**활용 방안**:
- 드롭다운 옵션 동적 로딩
- 캐싱을 통한 성능 최적화

### 3. Health Check API

**새로운 엔드포인트**:
```
GET /health          # 서버 상태 체크
```

**프론트엔드 활용**:
- 앱 시작 시 서버 연결 상태 확인
- 주기적 헬스체크 구현

---

## 🎯 프론트엔드 마이그레이션

### Phase 1: DTO 모델 업데이트

#### 1.1 Company DTO 수정
```dart
// 기존 CreateCompanyRequest에 추가
@JsonSerializable()
class CreateCompanyRequest {
  // 기존 필드들...
  final List<String>? companyTypes;  // 추가
  final bool? isPartner;             // 추가  
  final bool? isCustomer;            // 추가
}

// 새로운 필터링 옵션
@JsonSerializable()
class CompanyListRequest {
  final int? page;
  final int? perPage;
  final bool? isActive;              // 추가 (소프트 딜리트)
}
```

#### 1.2 Equipment DTO 수정
```dart
// Equipment 상태 Enum 확장
enum EquipmentStatus {
  @JsonValue('available') available,
  @JsonValue('inuse') inuse,
  @JsonValue('maintenance') maintenance,
  @JsonValue('disposed') disposed,    // 새로 추가
}

// 페이지네이션 쿼리 확장
@JsonSerializable()
class EquipmentListRequest {
  final int? page;
  final int? perPage;
  final String? status;
  final int? companyId;
  final int? warehouseLocationId;
  final bool? isActive;              // 추가
}
```

### Phase 2: Repository 인터페이스 수정

#### 2.1 소프트 딜리트 지원
```dart
abstract class CompanyRepository {
  // 기존 메서드 시그니처 수정
  Future<Either<Failure, PaginatedResponse<Company>>> getCompanies({
    int? page,
    int? perPage,
    bool? isActive,  // 추가
  });
  
  // 삭제 메서드 동작 변경 (소프트 딜리트)
  Future<Either<Failure, Unit>> deleteCompany(int id);
  
  // 복구 메서드 추가
  Future<Either<Failure, Company>> restoreCompany(int id);  // 신규
}
```

#### 2.2 새로운 Repository 추가
```dart
// 새로 추가할 Repository
abstract class OverviewRepository {
  Future<Either<Failure, DashboardStats>> getDashboardStats(int? companyId);
  Future<Either<Failure, PaginatedResponse<Activity>>> getRecentActivities({
    int? page,
    int? perPage,
    String? entityType,
    int? companyId,
  });
  Future<Either<Failure, EquipmentStatusDistribution>> getEquipmentStatusDistribution(int? companyId);
  Future<Either<Failure, LicenseExpirySummary>> getLicenseExpirySummary(int? companyId);
}

abstract class LookupRepository {
  Future<Either<Failure, Map<String, List<LookupItem>>>> getAllLookups();
  Future<Either<Failure, List<LookupItem>>> getLookupsByType(String type);
}
```

### Phase 3: API 클라이언트 수정

#### 3.1 Retrofit 인터페이스 업데이트
```dart
@RestApi()
abstract class SuperportApiClient {
  // Overview API 추가
  @GET('/overview/stats')
  Future<ApiResponse<DashboardStats>> getDashboardStats(
    @Query('company_id') int? companyId,
  );

  @GET('/overview/license-expiry')
  Future<ApiResponse<LicenseExpirySummary>> getLicenseExpirySummary(
    @Query('company_id') int? companyId,
  );

  // Lookups API 추가
  @GET('/lookups')
  Future<ApiResponse<Map<String, List<LookupItem>>>> getAllLookups();

  // 기존 API 파라미터 추가
  @GET('/companies')
  Future<ApiResponse<PaginatedResponse<Company>>> getCompanies(
    @Query('page') int? page,
    @Query('per_page') int? perPage,
    @Query('is_active') bool? isActive,  // 추가
  );
}
```

#### 3.2 응답 형식 변경 대응
```dart
// 기존 ApiResponse 클래스 수정
@JsonSerializable()
class ApiResponse<T> {
  final String status;          // 추가
  final String? message;        // 추가
  final T data;
  final ResponseMeta? meta;     // 변경 (기존 meta와 구조 다름)
}

@JsonSerializable()
class ResponseMeta {
  final PaginationMeta? pagination;  // 중첩 구조로 변경
}
```

### Phase 4: 상태 관리 업데이트

#### 4.1 Controller 수정
```dart
class CompanyController extends ChangeNotifier {
  // 소프트 딜리트 상태 관리
  bool _showDeleted = false;
  bool get showDeleted => _showDeleted;

  void toggleShowDeleted() {
    _showDeleted = !_showDeleted;
    _loadCompanies();  // 목록 다시 로드
    notifyListeners();
  }

  // 복구 기능 추가
  Future<void> restoreCompany(int id) async {
    final result = await _restoreCompanyUseCase(id);
    result.fold(
      (failure) => _handleError(failure),
      (company) {
        _companies[id] = company;
        notifyListeners();
      },
    );
  }
}
```

#### 4.2 새로운 Controller 추가
```dart
class DashboardController extends ChangeNotifier {
  DashboardStats? _stats;
  List<Activity> _recentActivities = [];
  bool _isLoading = false;

  // Getters...

  Future<void> loadDashboardData() async {
    _isLoading = true;
    notifyListeners();

    // 병렬로 데이터 로드
    await Future.wait([
      _loadStats(),
      _loadRecentActivities(),
    ]);

    _isLoading = false;
    notifyListeners();
  }
}
```

---

## 📡 API 엔드포인트 변경사항

### 새로 추가된 엔드포인트

| Method | Endpoint | 설명 | 우선순위 |
|--------|----------|------|----------|
| `GET` | `/overview/stats` | 대시보드 통계 | 🔴 높음 |
| `GET` | `/overview/license-expiry` | 라이선스 만료 요약 | 🟡 중간 |
| `GET` | `/overview/equipment-status` | 장비 상태 분포 | 🟡 중간 |
| `GET` | `/overview/recent-activities` | 최근 활동 내역 | 🟢 낮음 |
| `GET` | `/lookups` | 전체 마스터 데이터 | 🟡 중간 |
| `GET` | `/lookups/type` | 타입별 마스터 데이터 | 🟢 낮음 |
| `GET` | `/health` | 서버 상태 체크 | 🟢 낮음 |

### 기존 엔드포인트 변경사항

| Endpoint | 변경 내용 | 마이그레이션 필요도 |
|----------|-----------|---------------------|
| `GET /companies` | `is_active` 파라미터 추가 | 🔴 필수 |
| `GET /equipment` | `is_active` 파라미터 추가 | 🔴 필수 |
| `DELETE /companies/{id}` | 소프트 딜리트로 변경 | 🔴 필수 |
| `DELETE /equipment/{id}` | 권한 체크 강화 | 🟡 권장 |
| 모든 응답 | 표준 형식으로 통일 | 🔴 필수 |

---

## 🗄️ 데이터베이스 스키마 변경

### 새로 추가된 컬럼

| 테이블 | 컬럼 | 타입 | 설명 |
|--------|------|------|------|
| `companies` | `is_active` | `BOOLEAN` | 소프트 딜리트 플래그 |
| `companies` | `is_partner` | `BOOLEAN` | 파트너사 여부 |
| `companies` | `is_customer` | `BOOLEAN` | 고객사 여부 |
| `companies` | `company_types` | `TEXT[]` | 회사 유형 배열 |
| `equipment` | `is_active` | `BOOLEAN` | 소프트 딜리트 플래그 |
| `licenses` | `is_active` | `BOOLEAN` | 소프트 딜리트 플래그 |
| `warehouse_locations` | `is_active` | `BOOLEAN` | 소프트 딜리트 플래그 |
| `addresses` | `is_active` | `BOOLEAN` | 소프트 딜리트 플래그 |
| `users` | `is_active` | `BOOLEAN` | 소프트 딜리트 플래그 |

### 새로 추가된 인덱스

```sql
-- 소프트 딜리트 최적화용 인덱스
CREATE INDEX idx_companies_is_active ON companies(is_active);
CREATE INDEX idx_equipment_is_active ON equipment(is_active);
CREATE INDEX idx_licenses_is_active ON licenses(is_active);

-- 복합 인덱스 (성능 최적화)
CREATE INDEX idx_equipment_company_id_is_active ON equipment(company_id, is_active);
CREATE INDEX idx_licenses_company_id_is_active ON licenses(company_id, is_active);
```

---

## 🛠️ 실행 계획

### Phase 1: 백엔드 API 통합 (1주차)
- [ ] Overview API 통합 (`/overview/license-expiry` 우선)
- [ ] 소프트 딜리트 대응 (필터링 로직)
- [ ] 응답 형식 변경 대응

### Phase 2: 프론트엔드 모델 업데이트 (2주차)
- [ ] DTO 클래스 수정 (Freezed 재생성)
- [ ] Repository 인터페이스 확장
- [ ] API 클라이언트 업데이트

### Phase 3: UI/UX 개선 (3주차)
- [ ] 소프트 딜리트 UI 구현 (복구 버튼, 필터링)
- [ ] 대시보드 통계 위젯 구현
- [ ] 권한별 UI 제어 강화

### Phase 4: 성능 최적화 (4주차)
- [ ] Lookups API 캐싱 구현
- [ ] 페이지네이션 최적화
- [ ] 에러 처리 개선

### Phase 5: 테스트 및 배포 (5주차)
- [ ] 단위 테스트 업데이트
- [ ] 통합 테스트 실행
- [ ] 프로덕션 배포

---

## 🧪 테스트 업데이트 가이드

### 1. 단위 테스트 수정
```dart
// Repository 테스트 수정 예시
group('CompanyRepository', () {
  test('should return active companies when isActive is true', () async {
    // Given
    when(mockApiClient.getCompanies(
      page: 1,
      perPage: 20,
      isActive: true,  // 추가된 파라미터 테스트
    )).thenAnswer((_) async => mockActiveCompaniesResponse);

    // When
    final result = await repository.getCompanies(
      page: 1,
      perPage: 20,
      isActive: true,
    );

    // Then
    expect(result.isRight(), true);
  });
});
```

### 2. Widget 테스트 수정
```dart
testWidgets('should show restore button for deleted companies', (tester) async {
  // Given
  final deletedCompany = Company(id: 1, name: 'Test', isActive: false);
  
  // When
  await tester.pumpWidget(CompanyListItem(company: deletedCompany));
  
  // Then
  expect(find.text('복구'), findsOneWidget);
  expect(find.byIcon(Icons.restore), findsOneWidget);
});
```

### 3. 통합 테스트 수정
```dart
group('Company CRUD Integration', () {
  test('soft delete should set is_active to false', () async {
    // Create company
    final company = await createTestCompany();
    
    // Delete (soft delete)
    await apiClient.deleteCompany(company.id);
    
    // Verify soft delete
    final companies = await apiClient.getCompanies(isActive: false);
    expect(companies.data.any((c) => c.id == company.id), true);
  });
});
```

---

## 🚨 주의사항

### 1. 데이터 마이그레이션
- 기존 삭제된 데이터는 복구 불가능
- 소프트 딜리트 전환 후에만 복구 가능

### 2. 성능 영향
- `is_active` 필터링으로 인한 쿼리 복잡도 증가
- 인덱스 활용으로 성능 최적화 필요

### 3. 권한 관리
- 새로운 권한 체크 로직 확인 필요
- Staff 권한 사용자의 기능 제한 확인

### 4. 캐싱 전략
- Lookups API 응답 캐싱 구현 권장
- 대시보드 통계 캐싱으로 성능 개선

---

## 📞 지원 및 문의

### 개발팀 연락처
- **백엔드 API**: `superport_api` 레포지토리 이슈 생성
- **프론트엔드**: 현재 레포지토리 이슈 생성
- **데이터베이스**: DBA 팀 문의

### 유용한 리소스
- [API_SCHEMA.md](./API_SCHEMA.md) - 완전한 API 명세서
- [ENTITY_MAPPING.md](./ENTITY_MAPPING.md) - 데이터베이스 구조
- 백엔드 소스: `/Users/maximilian.j.sul/Documents/flutter/superport_api/`

---

**마이그레이션 가이드 버전**: 1.0  
**최종 검토**: 2025-08-13  
**담당자**: Full-Stack Development Team