스터디/Flutter
Flutter에서 실무·학습에서 자주 쓰이는 디자인 패턴
행복한 수지아빠
2025. 8. 19. 12:09
반응형
Flutter에서 자주 사용하는 디자인 패턴 정리
Flutter 개발에서 자주 쓰이는 디자인 패턴을 UI 트리, 상태 관리, 아키텍처, 객체지향 패턴의 네 가지 축으로 정리했습니다.
각 패턴은 **왜 쓰는지(Why), 언제 쓰는지(When), 어떻게 쓰는지(How)**를 짧은 예제와 함께 담았습니다.
1. UI 트리 패턴
1-1. Composite 패턴
- 개념: Flutter 위젯 트리 자체가 Composite. 전체와 부분을 동일하게 다룸.
- 장점: UI를 재귀적으로 구성/관리하기 쉬움.
Column(
children: [
Text("안녕"),
Row(children: [Icon(Icons.star), Text("별")]),
],
)
1-2. Decorator 패턴
- 개념: 기능을 감싸면서 꾸밈을 추가.
- 예시:
DecoratedBox(
decoration: BoxDecoration(borderRadius: BorderRadius.circular(12)),
child: Padding(
padding: const EdgeInsets.all(12),
child: Text('안녕'),
),
)
1-3. Builder 패턴
- 개념: 런타임 시점에 콜백으로 위젯 생성.
- 예시:
FutureBuilder<String>(
future: Future.delayed(Duration(seconds: 2), () => "완료"),
builder: (context, snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return Text(snapshot.data!);
},
)
2. 상태 관리 패턴
비교표
패턴 난이도 규모 장점 단점
| setState | 낮음 | 소형 | 간단함 | 위젯 트리 전파 불편 |
| Provider | 낮음 | 소~중 | 표준적, 간단 | 대규모 시 복잡 |
| Riverpod | 중간 | 중~대 | 전역/지역 유연, 테스트 용이 | 개념 학습 필요 |
| BLoC / Cubit | 높음 | 중~대 | 단방향 데이터 흐름, 테스트 용이 | 이벤트/상태 설계 부담 |
| Redux | 중간 | 대형 | 예측 가능, 디버깅 용이 | 보일러플레이트 많음 |
2-1. Provider 예시
class Counter extends ChangeNotifier {
int value = 0;
void inc() { value++; notifyListeners(); }
}
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => Counter(),
child: MyApp(),
),
);
}
class MyHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter = context.watch<Counter>();
return Column(
children: [
Text('${counter.value}'),
ElevatedButton(
onPressed: () => context.read<Counter>().inc(),
child: Text('plus'),
),
],
);
}
}
2-2. Riverpod 예시
final counterProvider = StateNotifierProvider<CounterNotifier, int>(
(ref) => CounterNotifier(),
);
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0);
void inc() => state++;
}
class MyHome extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Column(
children: [
Text('$count'),
ElevatedButton(
onPressed: () => ref.read(counterProvider.notifier).inc(),
child: Text('plus'),
),
],
);
}
}
2-3. Cubit 예시
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void inc() => emit(state + 1);
}
BlocProvider(
create: (_) => CounterCubit(),
child: BlocBuilder<CounterCubit, int>(
builder: (_, count) => Column(
children: [
Text('$count'),
ElevatedButton(
onPressed: () => context.read<CounterCubit>().inc(),
child: Text('plus'),
),
],
),
),
)
3. 아키텍처 패턴
MVVM 구조
lib/
data/ // API, DB
domain/ // Entity, UseCase
presentation/ // View, ViewModel
Clean Architecture
- 레이어: presentation → domain → data
- 원칙: 안쪽 레이어는 바깥 의존 없음. 의존성 역전.
4. Repository 패턴
// domain
abstract class TodoRepo {
Future<List<Todo>> fetchTodos();
}
// data
class TodoRepoImpl implements TodoRepo {
final RemoteApi api;
final LocalDb db;
TodoRepoImpl(this.api, this.db);
@override
Future<List<Todo>> fetchTodos() async {
final cached = await db.read();
if (cached.isNotEmpty) return cached;
final remote = await api.fetch();
await db.save(remote);
return remote;
}
}
5. 객체지향 패턴 예시
- Strategy: 알고리즘 교체
abstract class PriceStrategy { double calc(double base); }
class Discount implements PriceStrategy {
@override double calc(double b) => b * 0.9;
}
class Premium implements PriceStrategy {
@override double calc(double b) => b * 1.2;
}
- Observer: ChangeNotifier, Stream, ValueNotifier
- Factory: 플랫폼별 다른 위젯 반환
6. 네비게이션 패턴
go_router 예시
final router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (_, __) => HomePage(),
),
GoRoute(
path: '/detail/:id',
builder: (_, s) => DetailPage(id: s.pathParameters['id']!),
),
],
);
7. 비동기 패턴
FutureBuilder<User>(
future: api.getUser(),
builder: (context, snapshot) {
if (!snapshot.hasData) return CircularProgressIndicator();
return Text(snapshot.data!.name);
},
)
8. 성능 패턴 (Best Practice)
- const 위젯 활용
- 리빌드 최소화 (Selector, Consumer)
- RepaintBoundary로 복잡 위젯 격리
- ValueKey로 리스트 안정화
9. 상황별 추천 로드맵
- 프로토타입: setState
- 중형 앱: Provider / Riverpod
- 대형 앱: Clean Architecture + Riverpod/BLoC
- 웹/딥링크: go_router
✍️ 정리
Flutter에서의 디자인 패턴은 UI 트리(Composite/Decorator), 상태 관리(Riverpod/BLoC/Provider), 아키텍처(Clean/MVVM) 세 축이 핵심입니다.
반응형