# Monorepo 구조 (v0)

## 결정 요약

RoomfitV2는 **pub workspaces 기반 듀얼 앱 모노레포**로 전환한다.

- B2C 앱 (`apps/b2c/`) — 기존 member 앱 (`lib/`가 이곳으로 이동)
- B2B 앱 (`apps/b2b/`) — trainer/owner 전용 앱 (신규)
- 공유 패키지 (`packages/`) — 하드웨어·프로토콜·디자인 시스템·shop 도메인

Flutter/Dart는 이미 pub workspaces를 정식 지원 (Dart 3.5+, Flutter 3.24+).
별도 `melos` 필요 없음. 루트 `pubspec.yaml`의 `workspace:` 섹션이 모든 멤버를 선언한다.

## 최종 디렉토리 레이아웃

```
RoomfitV2/
├── apps/
│   ├── b2c/                   # 기존 Flutter 앱 (member)
│   │   ├── lib/
│   │   ├── test/
│   │   ├── integration_test/
│   │   ├── ios/
│   │   ├── android/
│   │   ├── pubspec.yaml       # name: roomfit_v2
│   │   └── analysis_options.yaml
│   └── b2b/                   # 신규 Flutter 앱 (trainer/owner)
│       ├── lib/
│       ├── test/
│       ├── integration_test/
│       ├── ios/
│       ├── android/
│       ├── pubspec.yaml       # name: roomfit_studio
│       └── analysis_options.yaml
├── packages/
│   ├── roomfit_protocol/      # (기존) 순수 Dart — 패킷 코덱
│   ├── roomfit_device/        # (기존) 순수 Dart — DeviceGateway + State
│   ├── roomfit_ble/           # (기존) Flutter — HM-10 (0xFFE0/FFE1) transport + scanner
│   ├── roomfit_exercise/      # (기존) 순수 Dart — rep/VBT
│   ├── roomfit_workout/       # (기존) 순수 Dart — SetExecutor, SessionManager, NextSetPreset, RestDetector, SetCutoffTrigger
│   ├── roomfit_firmware/      # (기존) 순수 Dart — YModem + IAP
│   ├── design_system/         # (기존) Flutter — 공유 UI 토큰/컴포넌트 + RestPauseDialog
│   └── roomfit_shop/          # (기존) 순수 Dart — Shop 도메인 (Center, Membership(role+display_name), Role, Repository interface + InMemory)
├── supabase/
│   ├── migrations/
│   ├── functions/invite_member/
│   └── tests/
├── docs/
├── pubspec.yaml               # 루트 workspace coordinator
├── CLAUDE.md
├── README.md
└── AGENTS.md
```

## 루트 pubspec.yaml

루트는 Flutter 앱이 아니라 **워크스페이스 코디네이터**로 전환.
개별 앱/패키지 빌드는 각 멤버에서 수행.

```yaml
name: roomfit_workspace
description: "RoomfitV2 monorepo (B2C + B2B apps + shared packages)"
publish_to: 'none'
environment:
  sdk: ^3.11.0

workspace:
  - apps/b2c
  - apps/b2b
  - packages/roomfit_protocol
  - packages/roomfit_device
  - packages/roomfit_ble
  - packages/roomfit_exercise
  - packages/roomfit_firmware
  - packages/roomfit_shop
  - packages/design_system
```

## 앱 이름 / 번들 정책

| 앱 | Dart 패키지명 | iOS bundle | Android applicationId |
|---|---|---|---|
| B2C | `roomfit_v2` (기존 유지) | `com.roomfit.v2` (기존) | `com.roomfit.v2` (기존) |
| B2B | `roomfit_studio` | `com.roomfit.studio` | `com.roomfit.studio` |

B2B는 스토어 별도 배포. 브랜드/아이콘도 분리 (v0는 공통 Roomfit 로고 + "Studio" 서브타이틀).

## 의존성 방향

```
apps/b2c           apps/b2b
    │                 │
    ├─ design_system ─┤
    ├─ roomfit_ble ───┤          ← 같은 하드웨어 패키지 공유
    ├─ roomfit_device┤
    ├─ roomfit_exercise
    ├─ roomfit_firmware
    └─ roomfit_shop ──┘          ← Shop 도메인은 공유, 단 apps/b2c는 role==null/member일 때 사용 최소
```

규칙:
- `apps/b2c` 와 `apps/b2b` 는 **서로 import 금지**
- `packages/*` 는 앱 어느 쪽도 import 가능
- `roomfit_shop` 은 순수 Dart (Flutter 의존 X) — 두 앱 모두 `ConsumerWidget` 계층에서 래핑

## 빌드/테스트 명령

pub workspaces 기반:

```bash
# 루트에서 전체 의존성 해석
flutter pub get    # 루트 pubspec의 workspace 멤버 전부 해석

# 앱별 빌드
cd apps/b2c && flutter run
cd apps/b2b && flutter run

# 앱별 테스트
cd apps/b2c && flutter test
cd apps/b2c && flutter test integration_test/
cd apps/b2b && flutter test

# 패키지별 분석 (기존과 동일)
cd packages/roomfit_device && dart analyze
cd packages/roomfit_shop && dart analyze
```

## B2B 앱 UI 스텁 (v0 첫 빌드)

```
apps/b2b/lib/
├── main.dart                   # B2B _AuthGate (role=owner|trainer 만 허용)
├── core/                       # logger, providers wiring (B2C에서 최소 복제 또는 packages/로 추출)
└── features/
    └── shop/
        ├── domain/
        ├── data/
        └── presentation/
            └── screens/
                ├── create_shop_screen.dart
                ├── shop_home_screen.dart
                ├── invite_member_screen.dart
                ├── member_detail_screen.dart
                └── supervised_workout_screen.dart  # workout flow를 supervised 컨텍스트로 감싼 화면
```

B2B 앱에서 "수업 세션 실행" 화면은 `roomfit_exercise` + `roomfit_ble`를 그대로 활용하되,
세션 start 파라미터에 `memberUserId`, `trainerUserId`, `centerId`, `sessionType='supervised'`를 주입.

## 공통 core 중복 처리

현재 B2C의 `lib/core/` 에 `logger`, `providers` 등 공용 유틸이 있다.
B2B에도 동일 유틸이 필요하면 세 가지 중 택일:

1. **복사 (v0 간단 선택)** — `apps/b2c/lib/core/` 와 `apps/b2b/lib/core/` 에 각각 작은 scaffold. 초기 divergence risk 낮음.
2. **packages/roomfit_app_core/ 추출** — 나중에 두 앱이 실제로 같은 유틸을 쓰는 게 확인되면 추출.
3. **Full share from day one** — 위험. 두 앱의 DI wiring이 미묘히 달라질 가능성 큼.

v0은 옵션 1. 중복이 3곳 이상 생기면 옵션 2로 리팩터.

## CLAUDE.md 의 경계 규칙 업데이트 필요 사항

(본 문서에 정의한 방향을 `CLAUDE.md` 에도 반영한다.)

- `lib/features/` → `apps/b2c/lib/features/` 로 경로 교체 (기존 B2C 규칙 유지)
- 신규: `apps/b2b/lib/features/shop/presentation/` → `apps/b2b/lib/features/shop/domain/` 만 import
- 신규: `apps/b2c/` 와 `apps/b2b/` 상호 import 금지
- `roomfit_shop` 패키지는 순수 Dart, Flutter 의존 금지

## 이행 단계 (Tidy First — 구조적 변경만)

본 restructure는 **동작 변경 없는 구조적 커밋**이어야 한다.

1. `git mv lib test integration_test ios android pubspec.yaml pubspec.lock analysis_options.yaml apps/b2c/`
2. `apps/b2c/pubspec.yaml` 에서 `workspace:` 섹션 제거 (멤버는 workspace 선언 불가)
3. 루트에 새 `pubspec.yaml` 작성 (workspace coordinator)
4. `apps/b2b/` 디렉토리에 `flutter create --org com.roomfit --project-name roomfit_studio --platforms ios,android .` 실행
5. `apps/b2b/pubspec.yaml` 를 workspace member 형식으로 편집 (resolution: workspace)
6. `packages/roomfit_shop/` 스캐폴드 (`flutter create --template package`)
7. 루트에서 `flutter pub get` 으로 workspace 해결
8. `cd apps/b2c && flutter test` → 기존 테스트 전부 통과
9. `cd apps/b2c && flutter analyze` → warning 0
10. 단일 commit: "refactor(repo): move to pub workspace monorepo (apps/b2c + apps/b2b + roomfit_shop)"

이후 B2B 구현은 이 commit 위에 쌓는다.

## 리스크

- **iOS Runner.xcodeproj 경로**: Flutter CLI가 생성한 Xcode 프로젝트는 상대 경로로 pubspec.yaml 참조. 이동 후 재빌드 시 경로 체인이 깨질 가능성 낮지만, `Runner.xcworkspace` 열었을 때 확인 필요.
- **Android Gradle**: `android/app/build.gradle` → `flutter.versionName` 등이 parent pubspec을 찾는데, `flutter.gradle` 스크립트가 parent directory의 pubspec을 자동 탐지. 정상 동작 확인 필요.
- **pub workspaces + Flutter**: 아직 일부 Flutter tooling (특히 `flutter create` inside workspace)이 edge case 있음. 문제 시 melos 도입 고려.
- **CI 없음**: 현재 .github/workflows 없어서 영향 무. 추후 apps/b2c, apps/b2b 각각 workflow 추가.

## 검증 기준

- [ ] `cd apps/b2c && flutter run` 성공
- [ ] `cd apps/b2b && flutter run` 성공 (스텁 Hello World)
- [ ] `cd apps/b2c && flutter test integration_test/app_e2e_test.dart` → 12/12 통과 (회귀 없음)
- [ ] `flutter analyze` 루트에서 0 warning
- [ ] 루트 `pubspec.lock` 없음 (workspace 멤버가 각자 lock)
- [ ] 기존 `packages/roomfit_*` 6개 + 신규 `roomfit_shop` 로 총 7개 패키지 인식
