생산 등급 동요 모노레포 설계: 레고 모듈식 경계, 멜로 및 BLOC_SIGNALS

작성자

카테고리:

← 피드로
DEV Community · Ali El-Khatib · 2026-08-29 개발(SW)

Ali El-Khatib

When scaling Flutter applications from a hobby project to an enterprise-grade codebase, teams almost always hit one of two architectural extremes:

  1. The Monolithic Mess: All business logic, HTTP clients, and UI widgets are dumped into one or two folders. Global state is everywhere, modules are tightly coupled, and making a change in one screen breaks three others.
  2. The “Over-Abstracted” Clean Architecture: In an attempt to follow Clean Architecture strictly, developers create 15 nested folders (data sources, raw DTOs, mappers, domain entities, use cases, presenters) just to display a simple settings toggle.

To solve this dilemma, I designed and open-sourced Flutter Production Starter — a modular, feature-first monorepo template built for real-world development speed and long-term maintainability.

In this article, I’ll walk you through the architectural principles, dependency boundaries, and modern stack choices behind this starter.

🧱 The Core Philosophy: “LEGO” Modular Boundaries

The fundamental rule of this architecture is LEGO Modularity: every feature should be a self-contained building block with a clear responsibility, minimal coupling, and an intentional public API.

┌───────────────────────────────────────────────┐
│                  APPLICATION                  │
│ Bootstrap • Config • DI • Routing • Observers │
└───────────────────────┬───────────────────────┘
                        │
                        ▼
┌───────────────────────────────────────────────┐
│               FEATURE MODULES                 │
│ Auth │ Profile │ Home │ Settings │ Payments   │
└───────────────────────┬───────────────────────┘
                        │
                        ▼
┌───────────────────────────────────────────────┐
│                SHARED PACKAGES                │
│ app_core │ network │ storage │ design_system  │
└───────────────────────────────────────────────┘

Enter fullscreen mode Exit fullscreen mode

1. Feature-First Colocation

Instead of organizing the entire codebase by layer (data/, domain/, presentation/), all code belonging to a business capability is colocated in apps/mobile/lib/features/<feature>/.

2. Public API Barrel Files

A feature must never reach into the private implementation files of another feature. Instead, features expose only intentional contracts through their root barrel file:

// ✅ Clean: Importing through the feature's public API
import 'package:mobile/features/auth/auth.dart';

// ❌ Forbidden: Deep import into private data sources
import 'package:mobile/features/auth/data/datasources/auth_remote_data_source.dart';

Enter fullscreen mode Exit fullscreen mode

⚖️ Pragmatic Clean Architecture (3 Complexity Tiers)

Clean Architecture should be applied where complexity justifies it, not blindly everywhere:

  • Tier 1 — Simple Feature (e.g. settings): Presentation + State only. No need for use cases or DTOs when updating a local theme mode.
  • Tier 2 — Medium Feature (e.g. profile): Entity contract, Repository implementation, DTO mapping, and presentation.
  • Tier 3 — Complex Feature (e.g. auth): Complete Clean Architecture with Use Cases, Remote Data Sources, Token Storage, and Route Guards.
  • Pluggability (e.g. auth_v2): Proves you can swap out an entire feature’s underlying data/service layer behind its domain interface via Dependency Injection without modifying consumer code.

📁 Monorepo Structure with Melos

Managing multiple packages in a single repository is powered by Melos:

/
├── apps/
│   └── mobile/              # Main app (Bootstrap, Environments, DI, Routes, Features)
├── packages/
│   ├── app_core/            # Result<T> monad, domain Failure taxonomy, Sanitized AppLogger
│   ├── app_network/         # Centralized Dio, interceptors, error mappers, ApiClient
│   ├── app_storage/         # SecureStorage, KeyValueStorage, TTL MemoryCache
│   ├── design_system/       # Tokens (Spacing, Radius), Light/Dark themes, Primitives
│   └── app_lints/           # Strict linting & static analysis configuration
├── melos.yaml               # Monorepo scripts (analyze, test, format, run)
└── ARCHITECTURE.md          # Architectural guide

Enter fullscreen mode Exit fullscreen mode

Why Dedicated Shared Packages?

  • app_core: Pure Dart abstractions (Result<T>, Failure, sanitized logger) with zero Flutter/UI dependencies.
  • app_network: Centralized Dio instance. Features never instantiate Dio() directly. It owns token injection, exponential backoff retries, and automatic sensitive data redaction (passwords and bearer tokens are never logged in plain text).
  • design_system: Standalone visual primitives, tokens (AppSpacing, AppRadius, AppDurations), and complete Material 3 Light/Dark themes.

⚡ Modern Technology Stack

Capability Library / Solution Rationale Routing kaisel: ^1.1.0 Strongly-typed declarative routing and route guards (AuthRouteGuard). State bloc_signals + signals_flutter Fine-grained reactive signals without boilerplate. DI get_it + injectable Constructor injection with compile-time code generation. Networking dio: ^5.11.0 Enterprise HTTP client encapsulated in app_network. Models freezed Immutable union states, DTOs, and copyable entities. Feedback toastification: ^3.2.0 Clean presentation-only feedback and snackbars.

🛡️ Functional Error Pipeline

Instead of leaking raw HTTP exceptions into widgets, the app uses a functional Result<T> and Failure hierarchy:

// Fetching data cleanly with functional Result
final result = await loginUseCase(email: email, password: password);

result.fold(
  onSuccess: (session) => router.toHome(),
  onFailure: (failure) {
    // FailureMessageResolver resolves friendly messages
    feedback.showError(context, failureResolver.resolve(failure));
  },
);

Enter fullscreen mode Exit fullscreen mode

🧪 Testing & CI

A starter is only as good as its verification. Every package in the monorepo has automated tests and strict linting:

# Run tests across all 6 packages simultaneously
melos run test

# Check static analysis across the entire monorepo
melos run analyze

Enter fullscreen mode Exit fullscreen mode

GitHub Actions CI is already pre-configured (.github/workflows/ci.yml) to validate every commit and PR automatically.

🚀 Try It Out

The entire template is open-source under the MIT License!

👉 GitHub Repository: https://github.com/Ali-El-Khatib/flutter-production-starter

# Clone the repository
git clone https://github.com/Ali-El-Khatib/flutter-production-starter.git

# Bootstrap packages
cd flutter-production-starter
melos bootstrap

# Run the app
melos run run:dev

Enter fullscreen mode Exit fullscreen mode

If you find this architecture helpful for your Flutter projects, feel free to give it a ⭐ on GitHub and share your thoughts in the comments below! What architectural patterns do you prefer for large-scale Flutter apps?

원문에서 계속 ↗