모듈 구조
한 앱을 두 팀이 나눠 만들 때 어떻게 붙이고 어떻게 떼는지를 정리했습니다.
패키지 구조
app (발주사)
홈 · 블랙박스 연동 · 영상
라우터 · FCM · 로그인
등록만 한다
contract (연결 규약)
ui_kit (공통 부품)
기능 박스를 누르면 외주·내부가 바뀝니다
- · 기능 패키지는 서로를 참조하지 않습니다
- · 기능 패키지는 app을 참조하지 않습니다. contract와 ui_kit만 참조합니다
- · app은 기능 패키지를 등록만 합니다. 기능 내부를 알지 않습니다
떼어내기
기능 옆 버튼을 누르면 그 기능을 발주사가 직접 맡을 때 바뀌는 파일이 나옵니다.
주행·주차 리포트
운전 점수
주정차 단속 알림
가치봄
내가 가본 곳
파인케어
파인케어를 발주사 개발팀이 직접 맡는 경우
바뀌는 파일
app/pubspec.yaml - feature_finecare: - path: ../packages/feature_finecare app/lib/router.dart - ...finecareRoutes, app/lib/push/handlers.dart - FinecarePushHandler(),
다른 기능 패키지 변경0개✓
contract 변경0개✓
패키지 폴더는 그대로 두고 소유만 발주사로 넘기면 됩니다. 폴더 안에 화면·데이터·테스트·검증용 앱이 함께 있어 발주사 개발팀이 그대로 이어서 개발할 수 있습니다.
연결 규약
이 표가 1주차에 두 팀이 합의할 문서의 초안입니다.
| 항목 | 누가 제공 | 기능 패키지가 하는 일 |
|---|---|---|
| 화면 이동 | app이 라우터 소유 | 자기 화면 목록과 진입 경로를 내보낸다 |
| 로그인 정보 | app이 세션 제공 | contract의 세션 값을 읽기만 한다 |
| 서버 호출 | app이 API 클라이언트 제공 (토큰 갱신 포함) | 받은 클라이언트로 자기 API만 부른다 |
| 푸시 | app이 FCM 초기화와 수신 | 알림 유형별 처리기를 등록한다 |
| 권한 | 공통 권한 서비스 | 필요한 권한을 요청만 한다 |
| 차량 상태 | app (블랙박스 연동 담당) | 주행 중 여부를 읽는다 (주정차 단속 알림 이용 제한에 필요) |
| 테마 | 발주사 디자인 토큰 | 토큰만 쓴다. 색·글자 크기를 직접 정하지 않는다 |
| 로그·분석 | app | 이벤트 이름과 값만 넘긴다 |
세션을 contract에 선언하고 app이 채운다
// packages/contract/lib/session.dart
final sessionProvider = Provider<Session>(
(ref) => throw UnimplementedError('app에서 채웁니다'),
);
// app/lib/main.dart
ProviderScope(
overrides: [
sessionProvider.overrideWithValue(currentSession),
],
child: const App(),
);푸시는 app이 받고 유형별로 넘긴다
// packages/contract/lib/push.dart
abstract class PushHandler {
bool canHandle(String type);
void open(BuildContext context, Map<String, dynamic> data);
}
// packages/feature_gachibom/lib/gachibom_push_handler.dart
class GachibomPushHandler implements PushHandler {
@override
bool canHandle(String type) => type.startsWith('gachibom.');
...
}FCM을 두 곳에서 초기화하지 않도록 수신은 app 한 곳에서 하고 기능은 처리기만 등록합니다.
저장소와 통합 순서
(발주사 저장소) ├─ app/ 발주사 ├─ packages/ │ ├─ contract/ 1주차 합의 후 공동 관리 │ ├─ ui_kit/ 발주사 소유, 저희는 PR로 기여 │ ├─ feature_report/ │ │ ├─ lib/src/ │ │ │ ├─ data/ API 호출, 모델(freezed) │ │ │ ├─ domain/ 계산·규칙 │ │ │ └─ presentation/ 화면, ViewModel(Riverpod) │ │ ├─ example/ 기능 검증용 Demo App │ │ └─ test/ │ ├─ feature_score/ │ └─ ... └─ melos.yaml 패키지 전체 분석·테스트 한 번에
example/ — 결과물로 요구하신 기능 검증용 Demo App입니다. contract를 가짜 값으로 채워 app 없이 기능만 따로 돌려볼 수 있습니다.
통합 순서 (주차 단위)
- 1주차contract 초안 합의 · 6개 기능의 빈 화면을 app에 먼저 붙인다합치는 길을 첫 주에 뚫어 둡니다
- 2주차~매주 금요일 병합 · 발주사 개발팀이 PR 리뷰서버 API가 준비되지 않은 기능은 합의한 명세로 가짜 응답을 두고 개발
- 마지막기능별 인수 · 빌드·통합 가이드 전달
마지막에 한꺼번에 합치면 어긋남을 늦게 발견합니다. 첫 주에 빈 화면이라도 합쳐 두는 것이 재작업을 줄이는 가장 확실한 방법입니다.