LIVO 차세대 Flutter 상태 관리
Source: Dev.to
Flutter는 훌륭하지만, 상태 관리는 금방 복잡해질 수 있습니다. 작은 프로젝트에서는 setState를, 큰 앱에서는 Provider, Riverpod, BLoC 등을 사용했을 겁니다—하지만 각각 장단점이 있습니다.
Note: 이 이야기는 원래
reactive_orm에 관한 것이었으며, 현재는 더 이상 사용되지 않습니다. 그 진화된 형태가 LIVO입니다. LIVO는 개선된 명명법, 문서화, 장기 지원과 함께 반응형 객체‑관계 상태‑관리 접근 방식을 지속합니다.
LIVO란?
Enter LIVO: Flutter용 가볍고 반응형인 ORM‑스타일 상태‑관리 라이브러리입니다.
모델 속성이 변경될 때 UI가 자동으로 반응하도록 해줍니다 — 스트림, ChangeNotifier, 혹은 보일러플레이트가 필요 없습니다.
LIVO와 함께 얻는 것
- 객체‑별 및 필드‑별 반응성
- 중첩 및 공유 모델
- 다 → 일 및 다 ↔ 다 관계
- 최소한의 보일러플레이트, 순수 Dart 모델
LIVO 작동 예시
- Object‑wise: 어떤 필드든 업데이트하고 전체 위젯을 재구성합니다
- Field‑wise: 선택된 필드에 대해서만 위젯을 재구성합니다
- Many → One: 여러 모델이 하나의 옵저버에 공급됩니다
- Many ↔ Many: 공유 모델이 여러 부모에 반영됩니다
Getting Started
프로젝트에 LIVO를 추가하세요:
dependencies:
livo: ^
1️⃣ Reactive Model 만들기
import 'package:livo/livo.dart';
class Task extends ReactiveModel {
String _title;
bool _completed = false;
String _status = "Idle";
Task({required String title}) : _title = title;
String get title => _title;
set title(String value) {
if (_title != value) {
_title = value;
notifyListeners(#title); // ✅ Symbol‑based
}
}
bool get completed => _completed;
set completed(bool value) {
if (_completed != value) {
_completed = value;
notifyListeners(#completed);
}
}
String get status => _status;
set status(String value) {
if (_status != value) {
_status = value;
notifyListeners(#status);
}
}
}
✅ 이것은 순수 Dart 코드입니다. LIVO가 필드가 변경될 때 위젯에 알림을 자동으로 처리합니다.
2️⃣ 객체 단위 리액티비티
final objectWise = Task(title: "Object-wise Reactivity");
ReactiveBuilder(
model: objectWise,
builder: (task) {
return ListTile(
title: Text(task.title),
subtitle: Text(task.status),
trailing: Checkbox(
value: task.completed,
onChanged: (v) => task.completed = v!,
),
);
},
);
체크박스를 클릭하면 전체 위젯이 다시 빌드됩니다.
3️⃣ 필드 단위 리액티비티 (최적화)
final fieldWise = Task(title: "Field-wise Reactivity");
ReactiveBuilder(
model: fieldWise,
fields: [#completed, #status],
builder: (task) {
return ListTile(
title: Text(task.title),
subtitle: Text(task.status),
trailing: Checkbox(
value: task.completed,
onChanged: (v) => task.completed = v!,
),
);
},
);
✅ completed 또는 status가 변경될 때만 위젯이 다시 빌드되고, 다른 필드는 무시됩니다.
4️⃣ Many → One (집계)
class Dashboard extends ReactiveModel {
final List sources;
Dashboard(this.sources) {
for (final task in sources) {
addNested(task); // listen to many
}
}
}
final manyA = Task(title: "Task A");
final manyB = Task(title: "Task B");
final dashboard = Dashboard([manyA, manyB]);
ReactiveBuilder(
model: dashboard,
builder: () => Column(
children: [
Text("A: ${manyA.completed}"),
Text("B: ${manyB.completed}"),
],
),
);
manyA 또는 manyB가 업데이트되면 대시보드 위젯이 자동으로 다시 빌드됩니다.
5️⃣ Many ↔ Many (공유 모델)
class Group extends ReactiveModel {
final String name;
final List tasks;
Group({required this.name, required this.tasks}) {
for (final task in tasks) addNested(task);
}
}
final group1 = Group(name: "Group 1", tasks: [objectWise, fieldWise]);
final group2 = Group(name: "Group 2", tasks: [fieldWise, manyA]);
ReactiveBuilder(
model: group1,
builder: (g) => Column(
children: g.tasks
.map((t) => Text("• ${t.title} → ${t.completed}"))
.toList(),
),
);
✅ 작업을 업데이트하면 해당 작업을 포함하고 있는 모든 그룹에 자동으로 반영됩니다.
How LIVO Works
- 모델은
ReactiveModel을 확장합니다 - 필드 세터는 값이 변경될 때마다
notifyListeners(#field)를 호출합니다 ReactiveBuilder위젯은 전체 객체 또는 특정 필드 중 하나를 구독합니다- 중첩된 모델은 변경 사항을 자동으로 상위로 전파합니다
- 스트림이 없습니다. 수동 연결이 없습니다. 모든 것이 안전하고 효율적으로 업데이트됩니다.
Why LIVO
- 최소한의 보일러플레이트로 깔끔한 Dart 모델
- 최적화된 성능을 위한 세밀한 반응성
- 더 쉬운 앱 설계를 위한 ORM‑스타일 사고 모델
- 단일 필드, 중첩 모델, 공유 모델 모두에서 원활하게 작동
링크
- Pub 패키지: LIVO
- GitHub 저장소: github.com/PravinKunnure/livo
독자를 위한 팁
작게 시작하세요: 빠른 프로토타이핑을 위해 객체‑단위 반응성을 사용하세요. 앱이 성장함에 따라 효율성을 위해 필드‑단위 또는 중첩 모델로 전환하세요.
LIVO는 Flutter 상태 관리를 직관적이고 재미있게 만들어 줍니다 — 성능을 희생하지 않으면서.