https://pub.dev/packages/mvc_pattern
1. MVCํจํด์ ์ฌ์ฉํด์ผ ํ๋ ์ด์ ์ ๋ํ์ฌ
๋ง์ฝ ๋ด๊ฐ ํ์ฌ์ ๋ค์ด๊ฐ์ ํ๋ก์ ํธ๋ฅผ ๋งก๊ฒ ๋๊ณ ๋ด๊ฐ ํผ์์ ์ฝ๋๋ฅผ ์์ฑํด์ ๊ณ์ํด์ ์ ์ง๋ณด์๋ฅผ ํ๊ณ ์๋ค๊ณ ๊ฐ์ ํด๋ณด์.
๋น์ฐํ ๋ด๊ฐ ์์ฑํ ์ฝ๋์ด๋ฏ๋ก ๋ด๊ฐ ๋ณด๊ธฐ ํธํ๊ฒ ์์ฑํ์ผ๋ฏ๋ก ๋ ํผ์๋ง ๋ณธ๋ค ๊ฐ์ ํ๋ฉด ๋ฌธ์ ๊ฐ ์๋ค.
ํ์ง๋ง ์ฌ์ ์ด ์๊ฒจ์ ๋ค๋ฅธ ์ฌ๋์๊ฒ ์ ์ง๋ณด์๋ฅผ ๋งก๊ฒจ์ผ ํ๋์ผ์ด ๋ฐ์ํ๋ค๊ณ ๊ฐ์ ํ๋ค๋ฉด
๋๋ง์ ๊ท์น์ผ๋ก ์์ฑํ ๋ด ์ฝ๋๋ฅผ ๋ค๋ฅธ ์ฌ๋์ด ๋ณด๊ธฐ์๋ ์ดํดํ๊ธฐ ์ด๋ ค์ด ์ฝ๋๊ฐ ๋ ๊ฒ ์ด๋ค.
์ฐ๋ฆฌ๋ ๊ฐ์ ์ฝ๋ฉํ๋ ์ฌ๊ณ ๋ฐฉ์์ด ๋ค๋ฅด๊ธฐ์ ๋๊ฐ์ ๊ฐ์ ๋ก์ง์ ๊ฐ๋ฐํด๋ ๋๊ฐ์ ์ฝ๋๊ฐ ๋์ฌ์๊ฐ ์๋ค.
์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด์ ์ฐ๋ฆฌ๋ MVC๋ผ๋ ๊ท์น์ ํตํด ๋๊ฐ ์ฝ๋ฉ์ ํ๋์ง ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ฝ๋๋ก ๋ง๋๋ ๊ฒ์ด๋ค.
M (Model) -> ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ณด(๋ฐ์ดํฐ)
V (View) -> ํ ์คํธ, ์ฒดํฌ๋ฐ์ค, ๋ฑ๊ณผ ๊ฐ์ ์ฌ์ฉ์ ์ธํฐํ์ด์ค ์์
C (Controller) -> ๋ฐ์ดํฐ์ ๋น์ฆ๋์ค ๋ก์ง ์ฌ์ด์ ์ํธ๋์ ๊ด๋ฆฌ
MVCํจํด์ ์ฌ์ฉํ ๊ฒฝ์ฐ์ ์ฅ์
1. ๊ฐ๋ฐ์๋์ ํฅ์
2. ๋ค๋ฅธ ์ฌ๋์ด ๊ฐ๋ฐํ ์ฝ๋์ ํจํด์ ์ฝ๊ฒ ํ์ ์ด ๊ฐ๋ฅ
3. MVCํจํด์ ์ด๋ฏธ ๊ฒ์ฆ๋ ๋ฐฉ์์ด๋ผ ๋์ ์ ๋ขฐ์ฑ
4. ์ฝ๋๋ฆฌ๋ทฐ๋ฅผ ํ ๋ ์ํํ ์ปค๋ฎค๋์ผ์ด์ ์ด ๊ฐ๋ฅ
๋ชจ๋ธ-๋ทฐ-์ปจํธ๋กค๋ฌ๋ ์ํํธ์จ์ด ๋์์ธ ํจํด์ผ๋ก. ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ก๋ถํฐ ๋น์ฆ๋์ค ๋ก์ง์ ๋ถ๋ฆฌํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ์๊ฐ์ ์์๋ ๋ค์์ ์คํ๋๋ ๋น์ฆ๋์ค ๋ก์ง์ ์๋ก ์ํฅ ์์ด ์ฝ๊ฒ ์์ ์ด ๊ฐ๋ฅํ๋๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค ์ ์๋ค.
1. ํจํด์๋ ์ผ๋ฐ์ ์ธ ์ฝ๋
class NormalPattern extends StatefulWidget {
const NormalPattern({super.key});
@override
State<NormalPattern> createState() => _NormalPatternState();
}
class _NormalPatternState extends State<NormalPattern> {
int count = 0;
// ํจ์ ์์
void update() => setState(() {});
void increment() {
count++;
update();
}
void decrement() {
if (count > 0) {
count--;
update();
}
}
// ํจ์ ๋
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Normal Pattern')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('$count', style: const TextStyle(fontSize: 120)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
increment();
},
child: const Text('+'),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
decrement();
},
child: const Text('-'),
),
),
],
)
],
),
),
);
}
}
๋ฐ๋ก ๊ธฐ๋ฅ์ ๋ถ๋ฅํด์ ๊ด๋ฆฌํ์ง ์๊ณ ํ ํ์ผ์ ๋ค๊ฐ์ด ๋ฃ์ด์ ์คํ๋๊ฒ ๋๋ค.
+ ๋ฒํผ์ ๋๋ฅด๋ฉด ๊ฐ์ด 1 ์ฆ๊ฐํ๊ณ , - ๋ฒํผ์ ๋๋ฅด๋ฉด ๊ฐ์ด -1 ๊ฐ์ํ๊ฒ ๋๋ ๊ฐ๋จํ ๋ก์ง์ด๋ค.
๋ณํ๋ ๊ฐ์ ํ๋ฉด์ ๊ทธ๋ ค์ฃผ๊ธฐ ์ํด์ setState(){}๋ฅผ ํตํด์ ์ฌ๋น๋๋ฅผ ํด์ค๋ค.
์์ ๊ฐ์ด ํจํด ์์ด ๊ตฌ์ฑํ๊ฒ ๋๋ค๋ฉด ํ ์ฝ๋์์ ๋ชจ๋ ๊ธฐ๋ฅ์ด ๋ค์ด์์ผ๋ฏ๋ก ์ฌ์์ ๋ฐ ๊ธฐ๋ฅ ์ถ๊ฐ์ ์ฝ๋์ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง๊ฒ ๋๋ค.
2. MVC ํจํด์ ํตํ ๊ตฌํ
์ ์ฝ๋๋ฅผ 3๊ฐ์ ํ์ผ๋ก ๋๋ ๋ณด์!
Model
View
Controller
`model.dart`
class Model {
int _count = 0;
int get counter => _count;
int increment() => ++_count;
int decrement() => --_count;
int reset() => _count = 0;
}
๋ชจ๋ธ๋ถ๋ถ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ํ๋๋์คํฌ๋ผ ์๊ฐํ๋ฉด ๊ฐํธํ๋ค.
์ฆ ์ฌ๊ธฐ์ ๋ชจ๋ ๋ฐ์ดํฐ์ ์ค์ ๊ฐ์ ์ ์ฅํ๊ณ ์์ ํ๋ ์ญํ์ ํ๊ฒ ๋๋ค.
`mvc_controller.dart`
import 'package:flutter_application_1/model/model.dart';
import 'package:mvc_pattern/mvc_pattern.dart';
class MvcController extends ControllerMVC {
factory MvcController([StateMVC? state]) => _this ??= MvcController._(state);
MvcController._(StateMVC? state)
: model = Model(),
super(state);
static MvcController? _this;
final Model model;
// ํจ์ ์์
void update() {
setState(() {});
}
int get count => model.counter;
void increment() {
model.increment();
update();
}
void decrement() {
if (count > 0) {
model.decrement();
update();
}
}
void reset() {
model.reset();
update();
}
// ํจ์ ๋
}
๋ชจ๋ธ์ ๊ฐ์ด ๋ณํ๊ฐ ๋๋ค๋ฉด ์ปจํธ๋กค๋ฌ์์๋ ๊ฐ์ด ๋ณ๊ฒฝ๋ฌ์ผ๋ ๊ฐ์ ์์ ํ๋ผ๊ณ ๋ช ๋ น์ ๋ด๋ฆฐ๋ค.
์๋ฅผ๋ค์ด์ View์์ ๋ฒํผ์ ํด๋ฆญํด์ ๊ฐ์ +1 ์ฆ๊ฐ์ํค๋๋ก ํ์๋ค๋ฉด ์ปจํธ๋กค๋ฌ์์๋ ๊ฐ์ +1 ์ฆ๊ฐ์ํค๋ ํจ์๊ฐ ์คํ์ด๋๊ณ
Model์์๋ ์ค์ง์ ์ผ๋ก ๊ฐ์ด ์์ ์ด ๋๋ ๋ฐฉ์์ด๋ค.
`mvc_view.dart`
import 'package:flutter/material.dart';
import 'package:flutter_application_1/mvc/controller/mvc_controller.dart';
import 'package:mvc_pattern/mvc_pattern.dart';
class MvcPattern extends StatefulWidget {
const MvcPattern({super.key});
@override
StateMVC<MvcPattern> createState() => _MvcPatternState();
}
class _MvcPatternState extends StateMVC<MvcPattern> {
// StateMVC๋ฅผ ์์๋ฐ์
_MvcPatternState() : super(MvcController()) {
con = controller as MvcController;
}
late MvcController con;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Mvc Pattern'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(con.count.toString(), style: const TextStyle(fontSize: 120)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: ElevatedButton(
onPressed: () {
con.increment();
},
child: const Text('+')),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: ElevatedButton(
onPressed: () {
con.decrement();
},
child: const Text('-')),
),
],
),
ElevatedButton(
onPressed: () {
con.reset();
},
child: const Text('์ด๊ธฐํ')),
],
),
),
);
}
}
๋ทฐ์์๋ ๋จ์ํ UI๋ฅผ ๊พธ๋ฉฐ์ฃผ๋ ๋ถ๋ถ์ด๋ค. ๋ฐ๋ก ์์คํ ์ด ์๋๋๋ ๋ก์ง๋ถ๋ถ์ ์ ๊ฒฝ์ฐ์ง ์์๋ ๋๋ค.
๋๋จธ์ง๋ ์ ๋ถ ์ปจํธ๋กค๋ฌ์ ๋ชจ๋ธ์์ ์ฒ๋ฆฌ๊ฐ ๋๋ฏ๋ก
์ด๋ก์จ ๊ฐ๋จํ์ง๋ง MVC ํจํด์ ๋ํด์ ์์๋ณด์๋ค.
๊ทธ๋ ๋ค๋ฉด MVC๋ง ์ฌ์ฉํ๋ค๋ฉด ์ฐ๋ฆฌ๋ ์๋ฒฝํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋๊ฒ์ผ๊น?
๊ทธ๋ ์ง ์๋ค ์ฌ์ค MVC์๋ ๋ฌธ์ ์ ์ด ์๋ค ๊ทธ๋์ ์ด๋ฅผ ๋ณด์ํ๊ธฐ ์ํด MVVM์ด๋๊ฒ ์๋ค.
MVVM์ ๋ํด์๋ ๋ค์ ํฌ์คํ ์ ์์ฑํ๋๋ก ํ๊ฒ ๋ค.