Flutter Modular은 스마트한 프로젝트 구조, 내장된 종속성 주입 및 중앙 집중식 라우팅 관리를 통해 Flutter 애플리케이션을 조직하는 강력한 프레임워크입니다. 모듈을 통해 관심사의 분리를 통해 깔끔한 아키텍처를 촉진하여 대규모 앱의 유지보수와 확장성을 쉽게 만듭니다. 이 패키지는 화면 간 탐색을 단순화하고 의존성을 자동으로 관리하여 반복 코드를 줄입니다. 모든 주요 플랫폼을 지원하며 모바일에서 웹과 데스크톱까지 일관된 개발 워크플로우를 가능하게 합니다. 모듈형 설계는 팀 협업과 테스트 가능성에 기여합니다.
사용 사례
대규모 플러터 애플리케이션
모듈러 앱 아키텍처
의존성 주입
중앙 집중형 라우팅
팀 기반 개발
크로스 플랫폼 일관성
주요 기능
내장된 종속성 주입
모듈 기반 아키텍처
자동 라우트 관리
모든 플랫폼 지원
간편한 탐색 처리
관심사의 명확한 분리
적합한 대상
복잡한 Flutter 앱을 개발하는 개발자
구조화된 코드 조직이 필요한 팀
확장 가능한 아키텍처가 필요한 프로젝트
다중 플랫폼 대상 애플리케이션
반복 코드를 줄이고 싶은 개발자
고려 사항
초보자를 위한 학습 곡선이 더 가파릅니다
모듈러 디자인 패턴에 대한 이해가 필요합니다
매우 작은 프로젝트에는 오버헤드가 추가될 수 있습니다
주류 패키지에 비해 커뮤니티 자원이 제한적
원본 README
연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.
Flutter Modular
A smart, modular project structure
Route management, dependency injection and scoped state — organized by feature, the Flutter way.
Let's find out how to implement a Modular structure in your project.
What is Modular?
Modular proposes to solve two problems:
Modularized routes.
Modularized Dependency Injection.
In a monolithic architecture, where we have our entire application as a single module, we design our software in a quick and
elegant way, taking advantage of all the amazing features of Flutter💙. However, producing a larger app in a "monolithic" way
can generate technical debt in both maintanance and scalability. With this in mind, developers adopted architectural strategies to better divide the code, minimizing the negative impacts on the project's maintainability and scalability..
By better dividing the scope of features, we gain:
Improved understanding of features.
Less breaking changes.
Add new non-conflicting features.
Less blind spots in the project's main business rule.
Improved developer turnover.
With a more readable code, we extend the life of the project. See example of a standard MVC with 3 features(Auth, Home, Product):
What we did in this structure was to continue using MVC, but this time in scope. This means that
each feature has its own MVC, and this simple approach solves many scalability and maintainability issues.
We call this approach "Smart Structure". But two things were still Global and clashed with the structure itself, so we created Modular to solve this impasse.
In short: Modular is a solution to modularize the route and dependency injection system, making each scope have
its own routes and injections independent of any other factor in the structure.
We create objects to group the Routes and Injections and call them Modules.
Ready to get started?
Modular is not only ingenious for doing something amazing like componentizing Routes and Dependency Injections, it's amazing
for being able to do all this simply!
Go to the next topic and start your journey towards an intelligent structure.
Common questions
Does Modular work with any state management approach?
Yes, the dependency injection system is agnostic to any kind of class
including the reactivity that makes up state management.
Can I use dynamic routes?
Yes! The entire route tree responds as on the Web. You can use dynamic :params,
query strings, relative paths, nested routes and persistent shells (RouterOutlet).
Use a route guard to redirect (e.g. to a 404 or a login page).
Do I need to create a Module for all features?
No. You can create a module only when you think it's necessary or when the feature is no longer a part of
the scope in which it is being worked on.
✨ Usage
flutter_modular 7 is a ground-up rewrite. A Module is now exactly the two things that couple a Flutter app — Dependency Injection + Routes — declared with a small functional API. State is page-scoped, tied to the route lifecycle, so ownership and disposal stop being your problem and the durable truth lives in a repository/service registered in DI. Full, runnable demonstrations (nested routes, RouterOutlet shells, route guards, per-module DI lifecycle, arguments/pop-results) live in example/.
Install
dependencies:flutter_modular:^7.0.0
or run flutter pub add flutter_modular.
Declare a module
A module groups routes and dependency injection. Shared dependencies are registered with addSingleton/add*, routes with route(...), and submodules with module(...).
context.pushNamed('/details/42'); // stacks a page (push stays out of the URL)
context.navigate('/'); // replaces the stack (owns the URL, resets history)
context.pop(result); // pops, delivering a result to the awaiting pushNamed
Page-scoped state
State lives 1:1 with a view via provide — built in a page-local scope and disposed when the route leaves, so there are no floating globals and no manual dispose.
c.route('/counter',
provide: (s) => s.addChangeNotifier<CounterViewModel>(CounterViewModel.new),
child: (ctx, state) => constCounterPage(),
);
// inside the page:final vm = context.watch<CounterViewModel>(); // rebuilds when the VM notifies// granular: rebuild only when the selected value changes (provider-style)final count = context.select<CounterViewModel, int>((vm) => vm.count);
🧑💻 Contributing
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the appropriate tag.
Don't forget to give the project a star! Thanks again!
Fork the Project
Create your Feature Branch (git checkout -b feature/AmazingFeature)
Commit your Changes (git commit -m 'Add some AmazingFeature')
Push to the Branch (git push origin feature/AmazingFeature)