ํํฌ ๊ด๋ จ ํ ๋ก #25280
TL;DR: State
๋
ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค. ๋ณต์กํ๊ณ ๊น์ด ์ค์ฒฉ๋ build
๋ฉ์๋๋ก ๋๋๊ฑฐ๋ ์ฌ๋ฌ ์์ ฏ์ ๋
ผ๋ฆฌ๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ด์ผ ํฉ๋๋ค.
๋ฏน์ค์ธ์ด๋ ํจ์๋ฅผ ํตํด ์ด๋ฌํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
์ฌ๋ฌ StatefulWidget
์์ State
๋
ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ ํด๋น ๋
ผ๋ฆฌ๊ฐ ์ฌ๋ฌ ์๋ช
์ฃผ๊ธฐ์ ์์กดํ๋ ํ ๋งค์ฐ ์ด๋ ต์ต๋๋ค.
์ผ๋ฐ์ ์ธ ์๋ TextEditingController
( AnimationController
, ์์์ ์ ๋๋ฉ์ด์
๋ฑ)๋ฅผ ๋ง๋๋ ๋
ผ๋ฆฌ์
๋๋ค. ํด๋น ๋
ผ๋ฆฌ๋ ์ฌ๋ฌ ๋จ๊ณ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
State
์ ๋ณ์๋ฅผ ์ ์ํฉ๋๋ค.dart
TextEditingController controller;
dart
<strong i="25">@override</strong>
void initState() {
super.initState();
controller = TextEditingController(text: 'Hello world');
}
State
๊ฐ ํ๊ธฐ๋ ๋ ์ปจํธ๋กค๋ฌ๋ฅผ ํ๊ธฐํ์ต๋๋ค.dart
<strong i="30">@override</strong>
void dispose() {
controller.dispose();
super.dispose();
}
build
๋ด๋ถ์ ํด๋น ๋ณ์๋ก ์ํ๋ ๋ชจ๋ ์์
์ ์ํํฉ๋๋ค.debugFillProperties
์ ํด๋น ์์ฑ์ ๋
ธ์ถํฉ๋๋ค.dart
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty('controller', controller));
}
์ด๊ฒ์ ๊ทธ ์์ฒด๋ก ๋ณต์กํ์ง ์์ต๋๋ค. ๋ฌธ์ ๋ ํด๋น ์ ๊ทผ ๋ฐฉ์์ ํ์ฅํ ๋ ์์๋ฉ๋๋ค.
์ผ๋ฐ์ ์ธ Flutter ์ฑ์๋ ์์ญ ๊ฐ์ ํ
์คํธ ํ๋๊ฐ ์์ ์ ์์ต๋๋ค. ์ฆ, ์ด ๋
ผ๋ฆฌ๊ฐ ์ฌ๋ฌ ๋ฒ ๋ณต์ ๋ฉ๋๋ค.
์ด ๋ ผ๋ฆฌ๋ฅผ ๋ชจ๋ ๊ณณ์ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ผ๋ฉด "์๋"ํ์ง๋ง ์ฝ๋์ ์ฝ์ ์ด ์๊น๋๋ค.
dispose
ํธ์ถํ๋ ๊ฒ์ ์์)์ด ๋ ผ๋ฆฌ๋ฅผ ์ธ์๋ถํดํ๋ ์ฒซ ๋ฒ์งธ ์๋๋ mixin์ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
mixin TextEditingControllerMixin<T extends StatefulWidget> on State<T> {
TextEditingController get textEditingController => _textEditingController;
TextEditingController _textEditingController;
<strong i="11">@override</strong>
void initState() {
super.initState();
_textEditingController = TextEditingController();
}
<strong i="12">@override</strong>
void dispose() {
_textEditingController.dispose();
super.dispose();
}
<strong i="13">@override</strong>
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty('textEditingController', textEditingController));
}
}
๊ทธ๋ฐ ๋ค์ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ์ต๋๋ค.
class Example extends StatefulWidget {
<strong i="17">@override</strong>
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example>
with TextEditingControllerMixin<Example> {
<strong i="18">@override</strong>
Widget build(BuildContext context) {
return TextField(
controller: textEditingController,
);
}
}
๊ทธ๋ฌ๋ ์ฌ๊ธฐ์๋ ๋ค๋ฅธ ๊ฒฐํจ์ด ์์ต๋๋ค.
mixin์ ํด๋์ค๋น ํ ๋ฒ๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค. StatefulWidget
์ฌ๋ฌ ๊ฐ์ TextEditingController
ํ์ํ๋ฉด ๋ ์ด์ ๋ฏน์ค์ธ ๋ฐฉ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ฏน์ค์ธ์ ์ํด ์ ์ธ๋ "์ํ"๋ ๋ค๋ฅธ ๋ฏน์ค์ธ ๋๋ State
์์ฒด์ ์ถฉ๋ํ ์ ์์ต๋๋ค.
๋ ๊ตฌ์ฒด์ ์ผ๋ก ๋งํ๋ฉด ๋ ๊ฐ์ ๋ฏน์ค์ธ์ด ๊ฐ์ ์ด๋ฆ์ ์ฌ์ฉํ๋ ๋ฉค๋ฒ๋ฅผ ์ ์ธํ๋ฉด ์ถฉ๋์ด ๋ฐ์ํฉ๋๋ค.
์ต์
์ ์๋๋ฆฌ์ค๋ ์ถฉ๋ํ๋ ๊ตฌ์ฑ์์ด ๊ฐ์ ์ ํ์ด๋ฉด ์๋์ผ๋ก ์คํจํฉ๋๋ค.
์ด๋ก ์ธํด ๋ฏน์ค์ธ์ ์ด์์ ์ด์ง ์๊ณ ์ง์ ํ ์๋ฃจ์ ์ด ๋๊ธฐ์๋ ๋๋ฌด ์ํํฉ๋๋ค.
๋ ๋ค๋ฅธ ํด๊ฒฐ์ฑ
์ StreamBuilder
& co์ ๋์ผํ ํจํด์ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค.
์ปจํธ๋กค๋ฌ๋ฅผ ๊ด๋ฆฌํ๋ TextEditingControllerBuilder
์์ ฏ์ ๋ง๋ค ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ฉด ์ฐ๋ฆฌ์ build
๋ฉ์๋์์ ์์ ๋กญ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด๋ฌํ ์์ ฏ์ ์ผ๋ฐ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํ๋ฉ๋๋ค.
class TextEditingControllerBuilder extends StatefulWidget {
const TextEditingControllerBuilder({Key key, this.builder}) : super(key: key);
final Widget Function(BuildContext, TextEditingController) builder;
<strong i="12">@override</strong>
_TextEditingControllerBuilderState createState() =>
_TextEditingControllerBuilderState();
}
class _TextEditingControllerBuilderState
extends State<TextEditingControllerBuilder> {
TextEditingController textEditingController;
<strong i="13">@override</strong>
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(
DiagnosticsProperty('textEditingController', textEditingController));
}
<strong i="14">@override</strong>
void dispose() {
textEditingController.dispose();
super.dispose();
}
<strong i="15">@override</strong>
Widget build(BuildContext context) {
return widget.builder(context, textEditingController);
}
}
๊ทธ๋ฐ ๋ค์ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉ๋ฉ๋๋ค.
class Example extends StatelessWidget {
<strong i="19">@override</strong>
Widget build(BuildContext context) {
return TextEditingControllerBuilder(
builder: (context, controller) {
return TextField(
controller: controller,
);
},
);
}
}
์ด๊ฒ์ ๋ฏน์ค์ธ์์ ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํฉ๋๋ค.
์ฌ์ฉ๋ฒ์ด ๋งค์ฐ ์ฅํฉํฉ๋๋ค. ์ด๋ ๋จ์ผ ๋ณ์ ์ ์ธ์ ๋ํด ํจ๊ณผ์ ์ผ๋ก 4์ค์ ์ฝ๋ + 2๋จ๊ณ ๋ค์ฌ์ฐ๊ธฐ์
๋๋ค.
์ฌ๋ฌ ๋ฒ ์ฌ์ฉํ๋ ค๋ ๊ฒฝ์ฐ์๋ ๋์ฑ ๊ทธ๋ ์ต๋๋ค. TextEditingControllerBuilder
๋ด๋ถ์
<strong i="28">@override</strong>
Widget build(BuildContext context) {
return TextEditingControllerBuilder(
builder: (context, controller1) {
return TextEditingControllerBuilder(
builder: (context, controller2) {
return Column(
children: <Widget>[
TextField(controller: controller1),
TextField(controller: controller2),
],
);
},
);
},
);
}
๊ทธ๊ฒ์ ๋จ์ง ๋ ๊ฐ์ ๋ณ์๋ฅผ ์ ์ธํ๊ธฐ ์ํ ๋งค์ฐ ๋ค์ฌ์ฐ๊ธฐ๋ ์ฝ๋์ ๋๋ค.
์ถ๊ฐ State
๋ฐ Element
์ธ์คํด์ค๊ฐ ์์ผ๋ฏ๋ก ์ฝ๊ฐ์ ์ค๋ฒํค๋๊ฐ ์ถ๊ฐ๋ฉ๋๋ค.
์ฌ์ฉํ๊ธฐ๊ฐ ์ด๋ ต TextEditingController
์ธ๋ถ build
.
State
์๋ช
์ฃผ๊ธฐ๊ฐ ํด๋น ์ปจํธ๋กค๋ฌ์์ ์ผ๋ถ ์์
์ ์ํํ๋ ค๋ฉด ํด๋น ์ปจํธ๋กค๋ฌ์ ์ก์ธ์คํ๊ธฐ ์ํด GlobalKey
๊ฐ ํ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด:
class Example extends StatefulWidget {
<strong i="43">@override</strong>
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
final textEditingControllerKey =
GlobalKey<_TextEditingControllerBuilderState>();
<strong i="44">@override</strong>
void didUpdateWidget(Example oldWidget) {
super.didUpdateWidget(oldWidget);
if (something) {
textEditingControllerKey.currentState.textEditingController.clear();
}
}
<strong i="45">@override</strong>
Widget build(BuildContext context) {
return TextEditingControllerBuilder(
key: textEditingControllerKey,
builder: (context, controller) {
return TextField(controller: controller);
},
);
}
}
cc @dnfield @Hixie
์์ฒญํ ๋๋ก ํํฌ์ ์ํด ํด๊ฒฐ๋ ๋ฌธ์ ์ ๋ํ ์์ธํ ๋ด์ฉ์
๋๋ค.
ํ๋ ์์ํฌ ๋ด์์ ์ด ์์ ์ ๋ ์ฝ๊ฒ ๋ง๋ค๋ ค๋ ์๋๊ฐ ์ค์ ๋ก ์ฌ์ฉ์๊ฐ ์๊ฐํด์ผ ํ๋ ๋ณต์ก์ฑ์ ์จ๊ธธ๊น๋ด ๊ฑฑ์ ๋ฉ๋๋ค.
์ผ์ข
์ abstract class Disposable
๋ก ์ฒ๋ฆฌํด์ผ ํ๋ ๊ฐ๋ ฅํ ํ์์ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์์๊ฒ ์ด ์ค ์ผ๋ถ๊ฐ ๋ ์ข์ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฌํ ๊ฒฝ์ฐ์ ๋ค์๊ณผ ๊ฐ์ด ๋ ๊ฐ๋จํ ํด๋์ค๋ฅผ ๋ ์ฝ๊ฒ ์์ฑํ ์ ์์ด์ผ ํฉ๋๋ค.
class AutomaticDisposingState<T> extends State<T> {
List<Disposable> _disposables;
void addDisposable(Disposable disposable) {
assert(!_disposables.contains(disposable));
_disposables.add(disposable);
}
<strong i="8">@override</strong>
void dispose() {
for (final Disposable disposable in _disposables)
disposable.dispose();
super.dispose();
}
}
๋ฐ๋ณต๋๋ ๋ช ์ค์ ์ฝ๋๋ฅผ ์ ๊ฑฐํฉ๋๋ค. ๋๋ฒ๊ทธ ์์ฑ์ ๋ํด ์ ์ฌํ ์ถ์ ํด๋์ค๋ฅผ ์์ฑํ ์ ์์ผ๋ฉฐ ๋ ๋ชจ๋๋ฅผ ๊ฒฐํฉํ๋ ํด๋์ค๋ ์์ฑํ ์ ์์ต๋๋ค. ์ด๊ธฐํ ์ํ๋ ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค.
<strong i="12">@override</strong>
void initState() {
super.initState();
controller = TextEditingController(text: 'Hello world');
addDisposable(controller);
addProperty('controller', controller);
}
์ผํ์ฉ ํด๋์ค์ ๋ํ ์ด๋ฌํ ์ ๋ ฅ ์ ๋ณด๋ฅผ ์ ๊ณตํ์ง ๋ชปํ๊ณ ์์ต๋๊น?
ํ๋ ์์ํฌ ๋ด์์ ์ด ์์ ์ ๋ ์ฝ๊ฒ ๋ง๋ค๋ ค๋ ์๋๊ฐ ์ค์ ๋ก ์ฌ์ฉ์๊ฐ ์๊ฐํด์ผ ํ๋ ๋ณต์ก์ฑ์ ์จ๊ธธ๊น๋ด ๊ฑฑ์ ๋ฉ๋๋ค.
์์ ฏ์ ์ฌ์ฉ์๊ฐ ์๊ฐํด์ผ ํ๋ ๋ณต์ก์ฑ์ ์จ๊น๋๋ค.
๊ทธ๊ฒ ์ ๋ง ๋ฌธ์ ์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๊ฒฐ๊ตญ ์ฌ์ฉ์๊ฐ ์ํ๋ ๋๋ก ์ธ์๋ถํดํ๋ ๊ฒ์ ์ฌ์ฉ์์ ๋ชซ์ ๋๋ค.
๋ฌธ์ ๋ ์ผํ์ฉํ๋ง์ ๋ฌธ์ ๊ฐ ์๋๋ค.
์ด๊ฒ์ ๋ฌธ์ ์ ์ ๋ฐ์ดํธ ๋ถ๋ถ์ ์์ด๋ฒ๋ฆฝ๋๋ค. ์คํ ์ด์ง ๋ก์ง์ didChangeDependencies ๋ฐ didUpdateWidget๊ณผ ๊ฐ์ ์๋ช ์ฃผ๊ธฐ์ ์์กดํ ์๋ ์์ต๋๋ค.
๋ช ๊ฐ์ง ๊ตฌ์ฒด์ ์ธ ์:
didChangeDependencies
๋ด๋ถ์ ๋
ผ๋ฆฌ๊ฐ ์๋ SingleTickerProviderStateMixin .super.build(context)
์ ์์กดํ๋ AutomaticKeepAliveClientMixin์ํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ค๋ ํ๋ ์์ํฌ์ ๋ง์ ์๊ฐ ์์ต๋๋ค.
์ด๊ฒ๋ค์ ์ ๋ฐ์ดํธ ๋ฉ์ปค๋์ฆ์ผ๋ก ์ํ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ผ ๋ฟ์ ๋๋ค.
๊ทธ๋ฌ๋ ๊ทธ๋ค์ "๋น๋"๋ถ๋ถ์์ ์ธ๊ธ ํ ๊ฒ๊ณผ ๋์ผํ ๋ฌธ์ ๋ฅผ ๊ฒช๊ณ ์์ต๋๋ค.
๋ง์ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
์๋ฅผ ๋ค์ด Stackoverflow์์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋ฌธ์ ์ค ํ๋๋ "๋ณ๊ฒฝ ์ ๊ฒฝ๋ก ํธ์"์ ๊ฐ์ ๋ถ์์ฉ์ ๋ํด StreamBuilder
๋ฅผ ์ฌ์ฉํ๋ ค๋ ์ฌ๋๋ค์
๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ถ๊ทน์ ์ผ๋ก ๊ทธ๋ค์ ์ ์ผํ ํด๊ฒฐ์ฑ
์ StreamBuilder๋ฅผ "๊บผ๋ด๋" ๊ฒ์
๋๋ค.
์ฌ๊ธฐ์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค.
๊ทธ๊ฒ์ _๋ง์ ์์ _์ด๋ฉฐ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ฌธ์
์ฌ๋ฌ
StatefulWidget
์์State
๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ ํด๋น ๋ ผ๋ฆฌ๊ฐ ์ฌ๋ฌ ์๋ช ์ฃผ๊ธฐ์ ์์กดํ๊ธฐ ๋๋ฌธ์ ๋งค์ฐ ์ด๋ ต์ต๋๋ค.์ผ๋ฐ์ ์ธ ์๋
TextEditingController
(AnimationController
, ์์์ ์ ๋๋ฉ์ด์ ๋ฑ)์ ๋ง๋๋ ๋ ผ๋ฆฌ์ ๋๋ค. ํด๋น ๋ ผ๋ฆฌ๋ ์ฌ๋ฌ ๋จ๊ณ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
State
์ ๋ณ์๋ฅผ ์ ์ํฉ๋๋ค.
dart TextEditingController controller;
- ์ ์ฌ์ ์ผ๋ก ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ์ฌ ์ปจํธ๋กค๋ฌ(์ผ๋ฐ์ ์ผ๋ก initState ๋ด๋ถ) ์์ฑ:
dart <strong i="19">@override</strong> void initState() { super.initState(); controller = TextEditingController(text: 'Hello world'); }
State
๊ฐ ํ๊ธฐ๋ ๋ ์ปจํธ๋กค๋ฌ๋ฅผ ํ๊ธฐํ์ต๋๋ค.
dart <strong i="24">@override</strong> void dispose() { controller.dispose(); super.dispose(); }
build
๋ด๋ถ์ ํด๋น ๋ณ์๋ก ์ํ๋ ๋ชจ๋ ์์ ์ ์ํํฉ๋๋ค.- (์ ํ ์ฌํญ)
debugFillProperties
์ ํด๋น ์์ฑ์ ๋ ธ์ถํฉ๋๋ค.
dart void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties.add(DiagnosticsProperty('controller', controller)); }
์ด๊ฒ์ ๊ทธ ์์ฒด๋ก ๋ณต์กํ์ง ์์ต๋๋ค. ๋ฌธ์ ๋ ํด๋น ์ ๊ทผ ๋ฐฉ์์ ํ์ฅํ ๋ ์์๋ฉ๋๋ค.
์ผ๋ฐ์ ์ธ Flutter ์ฑ์๋ ์์ญ ๊ฐ์ ํ ์คํธ ํ๋๊ฐ ์์ ์ ์์ต๋๋ค. ์ฆ, ์ด ๋ ผ๋ฆฌ๊ฐ ์ฌ๋ฌ ๋ฒ ๋ณต์ ๋ฉ๋๋ค.์ด ๋ ผ๋ฆฌ๋ฅผ ๋ชจ๋ ๊ณณ์ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ผ๋ฉด "์๋"ํ์ง๋ง ์ฝ๋์ ์ฝ์ ์ด ์๊น๋๋ค.
- ๋จ๊ณ ์ค ํ๋๋ฅผ ๋ค์ ์์ฑํ๋ ๊ฒ์ ์์ด๋ฒ๋ฆฌ๊ธฐ ์ฝ์ต๋๋ค(์
dispose
ํธ์ถํ๋ ๊ฒ์ ์์)- ์ฝ๋์ ๋ง์ ๋ ธ์ด์ฆ๋ฅผ ์ถ๊ฐํฉ๋๋ค.
์ด๊ฒ์ด ์ ๋ฌธ์ ์ธ์ง ์ดํดํ๊ธฐ๊ฐ ์ ๋ง ์ด๋ ต์ต๋๋ค. ์ ๋ Flutter ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง์ด ์์ฑํ์ง๋ง ์ค์ ๋ก ๊ทธ๋ ๊ฒ ํฐ ๋ฌธ์ ๊ฐ ๋์ง ์๋ ๊ฒ ๊ฐ์ต๋๊น? ์ต์ ์ ๊ฒฝ์ฐ์๋ ์์ฑ์ ์ ์ธํ๊ณ , ์ด๊ธฐํํ๊ณ , ํ๊ธฐํ๊ณ , ๋๋ฒ๊ทธ ๋ฐ์ดํฐ์ ๋ณด๊ณ ํ๋ ๋ฐ 4์ค์ด ์์๋ฉ๋๋ค(์ค์ ๋ก๋ ์ผ๋ฐ์ ์ผ๋ก ์ด๊ธฐํํ ๋์ ๋์ผํ ์ค์์ ์ ์ธํ ์ ์๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ์ ์ผ๋ก ๋ ์ ์ต๋๋ค. ์ฑ์ ์ผ๋ฐ์ ์ผ๋ก ๋๋ฒ๊ทธ ์์ฑ์ ์ํ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๋ํด ๊ฑฑ์ ํ ํ์๊ฐ ์์ผ๋ฉฐ ์ด๋ฌํ ๊ฐ์ฒด ์ค ๋ค์๋ ํ๊ธฐํด์ผ ํ๋ ์ํ๊ฐ ์์ต๋๋ค.
์์ฑ ์ ํ๋ณ ๋ฏน์ค์ธ์ด ์๋ํ์ง ์๋๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. ๋น๋ ํจํด์ด ์ข์ง ์๋ค๋ ๋ฐ ๋์ํฉ๋๋ค(๋ง ๊ทธ๋๋ก ์์์ ์ค๋ช ํ ์ต์ ์ ์๋๋ฆฌ์ค์ ๋์ผํ ์์ ๋ผ์ธ์ ์ฌ์ฉํฉ๋๋ค).
NNBD(ํนํ late final
ํ์ฌ ์ด๊ธฐํ์๊ฐ this
์ฐธ์กฐํ ์ ์๋๋ก )๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํ ์ ์์ต๋๋ค.
typedef Initializer<T> = T Function();
typedef Disposer<T> = void Function(T value);
mixin StateHelper<T extends StatefulWidget> on State<T> {
bool _active = false;
List<Property<Object>> _properties = <Property<Object>>[];
<strong i="8">@protected</strong>
void registerProperty<T>(Property<T> property) {
assert(T != Object);
assert(T != dynamic);
assert(!_properties.contains(property));
_properties.add(property);
if (_active)
property._initState();
}
<strong i="9">@override</strong>
void initState() {
_active = true;
super.initState();
for (Property<Object> property in _properties)
property._initState();
}
<strong i="10">@override</strong>
void dispose() {
for (Property<Object> property in _properties)
property._dispose();
super.dispose();
_active = false;
}
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
for (Property<Object> property in _properties)
property._debugFillProperties(properties);
}
}
class Property<T> {
Property(this.owner, this.initializer, this.disposer, [ this.debugName ]) {
owner.registerProperty(this);
}
final StateHelper<StatefulWidget> owner;
final Initializer<T> initializer;
final Disposer<T> disposer;
final String debugName;
T value;
void _initState() {
if (initializer != null)
value = initializer();
}
void _dispose() {
if (disposer != null)
disposer(value);
value = null;
}
void _debugFillProperties(DiagnosticPropertiesBuilder properties) {
properties.add(DiagnosticsProperty(debugName ?? '$T property', value));
}
}
๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํฉ๋๋ค.
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
<strong i="14">@override</strong>
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with StateHelper<MyHomePage> {
late final Property<int> _counter = Property<int>(this, null, null);
late final Property<TextEditingController> _text = Property<TextEditingController>(this,
() => TextEditingController(text: 'button'),
(TextEditingController value) => value.dispose(),
);
void _incrementCounter() {
setState(() {
_counter.value += 1;
});
}
<strong i="15">@override</strong>
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the ${_text.value.text} this many times:',
),
Text(
'${_counter.value}',
style: Theme.of(context).textTheme.headline4,
),
TextField(
controller: _text.value,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
์ ๋ง ์ํฉ์ด ๋์์ง๋ ๊ฒ ๊ฐ์ง ์์ต๋๋ค. ์์ง 4์ค์ ๋๋ค.
์์ ฏ์ ์ฌ์ฉ์๊ฐ ์๊ฐํด์ผ ํ๋ ๋ณต์ก์ฑ์ ์จ๊น๋๋ค.
๊ทธ๋ค์ ๋ฌด์์ ์จ๊ธฐ๊ณ ์์ต๋๊น?
๋ฌธ์ ๋ ์ค์ ์๊ฐ ์๋๋ผ ์ด ์ค์ด ๋ฌด์์ธ์ง์ ๋๋ค.
StreamBuilder
๋ stream.listen
+ setState
+ subscription.close
์์ต๋๋ค.
๊ทธ๋ฌ๋ StreamBuilder
์์ฑ์ ๋ฐ์ ์์ด ์ํํ ์ ์์ต๋๋ค.
๊ทธ ๊ณผ์ ์์ ์ค์๊ฐ ์์ ์ ์์ต๋๋ค. ๊ทธ๊ฒ์ ๋จ์ง "์คํธ๋ฆผ์ ์ ๋ฌํ๊ณ ๊ทธ๊ฒ์ผ๋ก๋ถํฐ ์์ ฏ์ ๊ตฌ์ถํ๋ ๊ฒ"์
๋๋ค.
์๋์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐ๋ ํจ์ฌ ๋ ๋ง์ ์๊ฐ์ด ํ์ํฉ๋๋ค.
StreamBuilder
๋ฅผ ์ฌ์ฉํ๋ฉด ์คํธ๋ฆผ์ ์์ ํ๊ธฐ ์ํ ๋จ์ ํ
์คํธ๋ฅผ ์์ฑํ ํ์๊ฐ ์์ผ๋ฏ๋ก ์ค๋ณต๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๊ฐ ํญ์ ์๋์ผ๋ก ์์ฑํ๋ฉด ์ค์๋ฅผ ๋ฒํ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค.๊ทธ๋ค์ ๋ฌด์์ ์จ๊ธฐ๊ณ ์์ต๋๊น?
Future
์๋์ ๊ณ ๋ คํ์ฌ๋ ๋งค์ฐ ๋ณต์ก subscription.close()
.์ฑ์ ์ผ๋ฐ์ ์ผ๋ก ๋๋ฒ๊ทธ ์์ฑ์ ์ํ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๋ํด ๊ฑฑ์ ํ ํ์๊ฐ ์์ต๋๋ค.
๊ทธ๋ค์ debugFillProperties ๋ฉ์๋๋ฅผ ์ ์ง ๊ด๋ฆฌํ๋ ๋ณต์ก์ฑ์ ์ฒ๋ฆฌํ๊ณ ์ถ์ง ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋ ๊ฒ ํ์ง ์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๊ฐ ๊ฐ๋ฐ์๋ค์๊ฒ "๋ชจ๋ ๋งค๊ฐ๋ณ์์ ์ํ ์์ฑ์ Flutter์ devtool์์ ์ฌ์ฉํ ์ ์๊ฒ ํ๊ณ ์ถ์ต๋๊น?"๋ผ๊ณ ๋งํ์ต๋๋ค. ๋๋ ๊ทธ๋ค์ด ์๋ผ๊ณ ๋งํ ๊ฒ์ด๋ผ๊ณ ํ์ ํฉ๋๋ค
๋ง์ ์ฌ๋๋ค์ด React์ devtool๊ณผ ๊ฐ์ ์ง์ ํ ๋๋ฑ๋ฌผ์ ๋ํ ์ด๋ง์ ๋์๊ฒ ํํํ์ต๋๋ค. Flutter์ devtool์ ์์ง ์์ต๋๋ค.
React์์ ์ฐ๋ฆฌ๋ ์์ ฏ์ ๋ชจ๋ ์ํ์ ๊ทธ ๋งค๊ฐ๋ณ์๋ฅผ ๋ณผ ์ ์๊ณ ์๋ฌด ๊ฒ๋ ํ์ง ์๊ณ ํธ์งํ ์ ์์ต๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ์ฌ๋๋ค์ provider
+ ๋ด ๋ค๋ฅธ ํจํค์ง๋ฅผ ์ฌ์ฉํ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ฒด ์์ฉ ํ๋ก๊ทธ๋จ ์ํ๊ฐ ์๋ฌด ๊ฒ๋ ํ์ง ์๊ณ ๋ ๋ณผ ์ ์๋ค๊ณ ๋งํ์ ๋ ๋งค์ฐ ๋๋์ต๋๋ค( ์ด ์ฑ๊ฐ์ devtool ๋ฒ๊ทธ ๋ชจ๋๋ก ).
๋๋ FutureBuilder์ ์ด๋ ฌํ ํฌ์ด ์๋๋ผ๋ ๊ฒ์ ์ธ์ ํด์ผ ํฉ๋๋ค. ์ฌ๋๋ค์ด Future๋ฅผ ํธ๋ฆฌ๊ฑฐํ ๋๋ฅผ ์๊ฐํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ง์ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด์ ๋ํ ์ง์์ ์ค๋จํ๋ ๊ฒ์ ๋ฌด๋ฆฌ๊ฐ ์๋๋ผ๊ณ ์๊ฐํฉ๋๋ค. StreamBuilder๋ ๊ด์ฐฎ๋ค๊ณ ์๊ฐํ์ง๋ง ์คํธ๋ฆผ ์์ฒด๊ฐ ๋๋ฌด ๋ณต์กํ๋ค๊ณ ์๊ฐํฉ๋๋ค(์์ ์ฃผ์์์ ์ธ๊ธํ๋ฏ์ด).
Tween ์์ฑ์ ๋ณต์ก์ฑ์ ๋ํด ์๊ฐํด์ผ ํ๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
ListView๋ ์์ ฏ์ด ํ์๋๋ ๋๋ก ํ์ฌํ๋ ๋ ผ๋ฆฌ๋ฅผ ์ค์ ๋ก ์จ๊ธฐ์ง ์์ต๋๋ค. API์ ํฐ ๋ถ๋ถ์ ๋๋ค.
๋ฌธ์ ๋ ์ค์ ์๊ฐ ์๋๋ผ ์ด ์ค์ด ๋ฌด์์ธ์ง์ ๋๋ค.
๋๋ ์ฌ๊ธฐ์ ์ฐ๋ ค๋ฅผ ์ ๋ง๋ก ์ดํดํ์ง ๋ชปํ๋ค. ๋ผ์ธ์ ๋จ์ํ ์์ฉ๊ตฌ์ฒ๋ผ ๋ณด์ ๋๋ค. ์ฌ๋ฌผ์ ์ ์ธํ๊ณ ์ด๊ธฐํํ๊ณ ์ฌ๋ฌผ์ ํ๊ธฐํฉ๋๋ค. ํ์ ์๊ฐ ์๋๋ผ๋ฉด ๋ฌด์์ด ๋ฌธ์ ์ธ๊ฐ?
FutureBuilder๊ฐ ๋ฌธ์ ๊ฐ ์๋ค๋ ๋ฐ ๋์ํฉ๋๋ค.
์ฃผ์ ์์ ์กฐ๊ธ ๋ฒ์ด๋๊ธด ํ์ง๋ง ๊ฐ๋ฐ ์ค์ Flutter๊ฐ ๋ช ์ด๋ง๋ค ๊ฐ์ง ํซ ๋ฆฌ๋ก๋๋ฅผ ํธ๋ฆฌ๊ฑฐํด์ผ ํ๋ค๊ณ ์ ์ํฉ๋๋ค. ์ด๊ฒ์ FutureBuilder, ํค ๋ฑ์ ์ค์ฉ์ ๊ฐ์กฐํฉ๋๋ค.
Tween ์์ฑ์ ๋ณต์ก์ฑ์ ๋ํด ์๊ฐํด์ผ ํ๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
ListView๋ ์์ ฏ์ด ํ์๋๋ ๋๋ก ํ์ฌํ๋ ๋ ผ๋ฆฌ๋ฅผ ์ค์ ๋ก ์จ๊ธฐ์ง ์์ต๋๋ค. API์ ํฐ ๋ถ๋ถ์ ๋๋ค.
์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ๋์ํฉ๋๋ค. ๋ด ์์ ์ ํํฌ๊ฐ ํ๋ ์ผ์ TweenAnimationBuilder
/ AnimatedContainer
/... ํ๋ ๊ฒ๊ณผ ์์ ํ ๋์ผํ๊ธฐ ๋๋ฌธ์ "๋
ผ๋ฆฌ๋ฅผ ์จ๊น๋๋ค"๋ก ํํฌ์ ๊ฐ์ ๊ฒ์ ๋นํํ ์ ์๋ค๋ ๊ฒ์
๋๋ค.
๋
ผ๋ฆฌ๋ ์จ๊ฒจ์ ธ ์์ง ์๋ค
๊ฒฐ๊ตญ ์ ๋๋ฉ์ด์
์ ์ข์ ๋น๊ต๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ ๋๋ฉ์ด์
์๋ ์์์ ๋ ๋ช
์์ ๊ฐ๋
์ด ์์ต๋๋ค.
์์์ ์ ๋๋ฉ์ด์
์ ๋จ์์ฑ, ๊ตฌ์ฑ ๊ฐ๋ฅ์ฑ ๋ฐ ๊ฐ๋
์ฑ ๋๋ฌธ์ ์ฌ๋๋ฐ๊ณ ์์ต๋๋ค.
๋ช
์์ ์ ๋๋ฉ์ด์
์ ๋ ์ ์ฐํ์ง๋ง ๋ ๋ณต์กํฉ๋๋ค.
์ด ๊ฐ๋
์ ์คํธ๋ฆผ ์์ ์ผ๋ก ๋ณํํ ๋ StreamBuilder
๋ _์์์ ์์ _์ธ ๋ฐ๋ฉด stream.listen
๋ _๋ช
์์ _์
๋๋ค.
๋ ๊ตฌ์ฒด์ ์ผ๋ก ๋งํ๋ฉด StreamBuilder
๋ฅผ ์ฌ์ฉํ๋ฉด ์คํธ๋ฆผ์ด ๋ณ๊ฒฝ๋๋ ์๋๋ฆฌ์ค๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ _cannot_ ์๊ฑฐ๋ ๊ตฌ๋
์ ์ข
๋ฃํ๋ ๊ฒ์ ์์ต๋๋ค.
์ฌ๋ฌ StreamBuilder
ํจ๊ป ๊ฒฐํฉํ ์๋ ์์ต๋๋ค.
stream.listen
๋ ์ฝ๊ฐ ๊ณ ๊ธ์ค๋ฝ๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ์ต๋๋ค.
๋น๋๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๋จ์ํํ๋ ๋ฐ ๊ฐ๋ ฅํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ด์ ์ ๋์ํ ๊ฒ์ฒ๋ผ Builder ํจํด์ ์ด์์ ์ด์ง ์์ต๋๋ค. ์ฐ๊ธฐ์ ์ฌ์ฉ ๋ชจ๋ ์ฅํฉํฉ๋๋ค.
์ด ๋ฌธ์ ์ ํํฌ๊ฐ ํด๊ฒฐํ๋ ๊ฒ์ *Builders์ ๋์ฒด ๊ตฌ๋ฌธ์ ๋ํ ๊ฒ์
๋๋ค.
์๋ฅผ ๋ค์ด flutter_hooks
๋ FutureBuilder
๋ฐ StreamBuilder
์ ์์ ํ ๋์ผํฉ๋๋ค.
Widget build(context) {
final AsyncSnapshot<T> snapshot = useStream(stream);
}
๊ณ์ํด์ AnimatedContainer
& ์ ์ฌ๋ useAnimatedSize
/ useAnimatedDecoractedBox
/ ...๋ก ๋ํ๋ผ ์ ์์ต๋๋ค.
double opacity;
Widget build(context) {
final double animatedOpacity = useAnimatedDouble(opacity, duration: Duration(milliseconds: 200));
return Opacity(
opacity: animatedOpacity,
child: ...,
);
}
๋ด ์์ ์ ํํฌ์ ๊ฐ์ ๊ฒ์ "๋ ผ๋ฆฌ๋ฅผ ์จ๊น๋๋ค"๋ก ๋นํํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค.
๊ทธ๊ฒ์ ์ฃผ์ฅ์ด ์๋๋๋ค. ์ฃผ์ฅ์ " ๊ฐ๋ฐ์๊ฐ ์๊ฐํด์ผ ํ ๋ ผ๋ฆฌ ๋ ๊ฒ์ด๋ค .
๊ฐ๋ฐ์๋ค์ด ์๊ฐํด์ผ ํ ๊ทธ๋ฌํ ๋ ผ๋ฆฌ์ ์๊ฐ ์์ต๋๊น?
๋๊ฐ TextEditingController๋ฅผ ์์ ํ๊ณ ์๋์ง(๋๊ฐ ์์ฑํ๊ณ ๋๊ฐ ํ๊ธฐํ๋์ง)์ ๊ฐ์ต๋๋ค.
์ด ์ฝ๋์ฒ๋ผ?
Widget build(context) {
final controller = useTextEditingController();
final focusNode = useFocusNode();
}
ํํฌ๊ฐ ์์ฑํ๊ณ ํ๊ธฐํฉ๋๋ค.
์ด๊ฒ์ ๋ํด ๋ช ํํ์ง ์์ ๊ฒ์ด ๋ฌด์์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๋ค, ๋ง์ต๋๋ค. ๊ทธ ์ฝ๋์ ํจ๊ป ์ปจํธ๋กค๋ฌ์ ์๋ช ์ฃผ๊ธฐ๊ฐ ๋ฌด์์ธ์ง ์ ํ ๋ชจ๋ฆ ๋๋ค. ์ดํ ๋ฒ์๊ฐ ๋๋ ๋๊น์ง ์ง์๋ฉ๋๊น? ๊ตญ๊ฐ์ ์๋ช ? ๋ค๋ฅธ ๊ฒ? ๋๊ฐ ๊ทธ๊ฒ์ ์์ ํฉ๋๊น? ๋ค๋ฅธ ์ฌ๋์๊ฒ ์๋ํ๋ฉด ์์ ๊ถ์ ๊ฐ์ง ์ ์์ต๋๊น? ์ด ์ค ์ด๋ ๊ฒ๋ ์ฝ๋ ์์ฒด์์ ๋ช ํํ์ง ์์ต๋๋ค.
๊ทํ์ ์ฃผ์ฅ์ ์ค์ ๋ฌธ์ ๋ณด๋ค ํํฌ๊ฐ ์ํํ๋ ์์
์ ๋ํ ์ดํด ๋ถ์กฑ์ผ๋ก ์ธํด ๋ฐ์ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ด๋ฌํ ์ง๋ฌธ์๋ ๋ชจ๋ ํํฌ์ ์ผ์นํ๋ ๋ช
ํํ๊ฒ ์ ์๋ ๋ต๋ณ์ด ์์ต๋๋ค.
์ปจํธ๋กค๋ฌ์ ์๋ช ์ฃผ๊ธฐ๊ฐ ํด๋น ์ฝ๋์ ํจ๊ป ๋ฌด์์ธ์ง ์ ํ ๋ชจ๋ฆ ๋๋ค.
๋ํ ๊ทธ๊ฒ์ ๋ํด ์๊ฐํ ํ์๋ ์์ต๋๋ค. ๋ ์ด์ ๊ฐ๋ฐ์์ ์ฑ ์์ด ์๋๋๋ค.
์ดํ ๋ฒ์๊ฐ ๋๋ ๋๊น์ง ์ง์๋ฉ๋๊น? ๊ตญ๊ฐ์ ์๋ช
๊ตญ๊ฐ์ ์๋ช
๋๊ฐ ๊ทธ๊ฒ์ ์์ ํฉ๋๊น?
ํํฌ๋ ์ปจํธ๋กค๋ฌ๋ฅผ ์์ ํฉ๋๋ค. ์ปจํธ๋กค๋ฌ๋ฅผ ์์ ํ๋ useTextEditingController
API์ ์ผ๋ถ์
๋๋ค.
useFocusNode
, useScrollController
, useAnimationController
, ...
์ด๋ค ๋ฉด์์ ์ด๋ฌํ ์ง๋ฌธ์ StreamBuilder
์ ์ฉ๋ฉ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ๋ค์์ ์๊ฐํ ์ ์์ต๋๋ค.
final value = useX(argument);
๋ค์๊ณผ ์์ ํ ๋๋ฑํฉ๋๋ค.
XBuilder(
argument: argument,
builder: (context, value) {
},
);
๊ทธ๋ค์ ๊ฐ์ ๊ท์น๊ณผ ๊ฐ์ ํ๋์ ํฉ๋๋ค.
๋ ์ด์ ๊ฐ๋ฐ์์ ์ฑ ์์ด ์๋๋๋ค.
๋๋ ๊ทผ๋ณธ์ ์ผ๋ก ๊ทธ๊ฒ์ด ์ฌ๊ธฐ์์ ์๊ฒฌ ๋ถ์ผ์น๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋ช ํํ์ง ์์ ์ ์๋ ์๋ช ์ด ์๋ ๊ฐ์ ๋ฐํํ๋ ํจ์์ ๊ฐ์ API๋ฅผ ๊ฐ๋ ๊ฒ์ IMHO์์ ํด๋น ๊ฐ์ ํด๋ก์ ์ ์ ๋ฌํ๋ ๊ฒ์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ API์ ๊ทผ๋ณธ์ ์ผ๋ก ๋งค์ฐ ๋ค๋ฆ ๋๋ค.
์ด ์คํ์ผ์ ์ฌ์ฉํ๋ ํจํค์ง๋ฅผ ๋ง๋๋ ์ฌ๋์๊ฒ๋ ๋ฌธ์ ๊ฐ ์์ง๋ง ํต์ฌ flutter API์ ํฌํจํ๊ณ ์ถ์ ์ข ๋ฅ์ ๋ฐ๋๋๋ ์คํ์ผ์ ๋๋ค.
@Hixie
@rrousselGit ์ด ๋งํ ๊ฒ์ ๊ทธ๋ค์ด ๊ฐ์ ๊ฒ์ด์ง๋ง ๋ผ์ดํ ์ฌ์ดํด๊ณผ ๊ด๋ จํ์ฌ "๋์ผํ ๊ท์น๊ณผ ๋์ผํ ํ๋"์ด ์๋ค๋ ๊ฒ์
๋๋ค. ์ณ์?
๊ทธ๋ฌ๋ ๊ทธ๋ค์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ์์ต๋๋ค.
๋ด๊ฐ ์ฌ๊ธฐ์์ ํ๋ ธ์ ์๋ ์์ง๋ง ์ง๋ ๊ฐ์์ flutter๋ฅผ ์๋ํ ๋ ํ ์์ ฏ์ ์ธ ๊ฐ์ ๋น๋๊ฐ ํ์ํ๋ค๋ฉด ๋ง์ ์ค์ฒฉ์ด ๋์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ํํฌ 3๊ฐ(์ 3๊ฐ)์ ๋นํด.
๋ํ. ํํฌ๋ ๊ตฌ์ฑ ๊ฐ๋ฅํ๋ฏ๋ก ์ฌ๋ฌ ํํฌ๋ก ๊ตฌ์ฑ๋ ์ํ ๋
ผ๋ฆฌ๋ฅผ ๊ณต์ ํด์ผ ํ๋ ๊ฒฝ์ฐ ๋ค๋ฅธ ํํฌ์ ๋ช ๊ฐ์ง ์ถ๊ฐ ๋
ผ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ์ ํํฌ๋ฅผ ๋ง๋ค๊ณ ํ๋์ ์ ํํฌ๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค.
์์ ฏ ๊ฐ์ ์ํ ๋ก์ง์ ์ฝ๊ฒ ๊ณต์ ํ๋ ๊ฒ๊ณผ ๊ฐ์ ๊ฒ์ 2019๋ ํ๋ฌํฐ ๊ฐ์์ ์๋ํ ๋ ๋ด๊ฐ ๋์น ๊ฒ์ด์์ต๋๋ค.
๋ฌผ๋ก ๋ค๋ฅธ ๊ฐ๋ฅํ ์๋ฃจ์
์ด ๋ง์ด ์์ ์ ์์ต๋๋ค. ์๋ง๋ ๊ทธ๊ฒ์ ์ด๋ฏธ ํด๊ฒฐ๋์๊ณ ๋๋ ๋ฌธ์์์ ๊ทธ๊ฒ์ ์ฐพ์ง ๋ชปํ์ต๋๋ค.
๊ทธ๋ฌ๋ ๊ทธ๋ ์ง ์๋ค๋ฉด ์ผ๋ฑ ์๋ฏผ์ผ๋ก์ ์ด์ฉํ ์ ์๋ ๋์ผํ ๋ฌธ์ ์ ๋ํ ํํฌ ๋๋ ๋ค๋ฅธ ์๋ฃจ์
๊ณผ ๊ฐ์ ๊ฒ์ด ๊ฐ๋ฐ ์๋๋ฅผ ํฌ๊ฒ ๋์ด๊ธฐ ์ํด ํ ์ ์๋ ์ผ์ด ๋ง์ด ์์ต๋๋ค.
OP๊ฐ ์ธ๊ธํ๋ฏ์ด ๋ชจ๋ ์ข ๋ฅ์ ๋ฌธ์ ๊ฐ ์๋ ๋น๋ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ ๊ฒ์ ์ ์ํ๋ ๊ฒ์ ์๋๋๋ค. ๋ด๊ฐ ์ ์ํ๋ ๊ฒ์ initState/dispose๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๊ฒ ์ ๋ฌธ์ ์ธ์ง ์ ์ดํด๊ฐ ์๋ฉ๋๋ค.
์ฌ๋๋ค์ด https://github.com/flutter/flutter/issues/51752#issuecomment -664787791์ ์ฝ๋์ ๋ํด ์ด๋ป๊ฒ ๋๋ผ๋์ง ๊ถ๊ธํฉ๋๋ค. ๋๋ ๊ทธ๊ฒ์ด initState/dispose๋ณด๋ค ๋ซ๋ค๊ณ ์๊ฐํ์ง ์์ง๋ง ์ฌ๋๋ค์ด ํํฌ๋ฅผ ์ข์ํ๋ค๋ฉด ๊ทธ๊ฒ๋ ์ข์ํฉ๋๊น? ํํฌ๊ฐ ๋ ๋์๊ฐ์? ๋ ๋์?
@Hixie Hooks๋ ์๋ช
์ฃผ๊ธฐ๋ฅผ ๋จ์ผ ํจ์ ํธ์ถ๋ก ๊ตฌ๋ถํ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํ๊ธฐ ์ข์ต๋๋ค. ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด useAnimationController
์ ๊ฐ์ด initState์ ๋ํด ์๊ฐํ๊ณ ๋ ์ด์ ํ๊ธฐํ ํ์๊ฐ ์์ต๋๋ค. ๊ฐ๋ฐ์์ ์ฑ
์์ ์ ๊ฑฐํฉ๋๋ค. ๋ด๊ฐ ๋ง๋ ๋ชจ๋ ๋จ์ผ ์ ๋๋ฉ์ด์
์ปจํธ๋กค๋ฌ๋ฅผ ํ๊ธฐํ๋์ง ๊ฑฑ์ ํ ํ์๊ฐ ์์ต๋๋ค.
initState
๋ฐ dispose
๋ ๋จ์ผ ํญ๋ชฉ์๋ ์ ํฉํ์ง๋ง ์ฌ๋ฌ ์ด์ง ์ ํ์ ์ํ๋ฅผ ์ถ์ ํด์ผ ํ๋ค๊ณ ์์ํด ๋ณด์ญ์์ค. ํํฌ๋ ํด๋์ค์ ์๋ช
์ฃผ๊ธฐ์ ๋ถ์ฐ๋๋ ๋์ ๋
ผ๋ฆฌ์ ์ถ์ํ ๋จ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
๋๋ ๋น์ ์ด ๋ฌป๋ ๊ฒ์ด ๋งค๋ฒ ์๋์ผ๋ก ํจ๊ณผ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋๋ฐ ์ ํจ์๊ฐ ์๋์ง ๋ฌป๋ ๊ฒ๊ณผ ๊ฐ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์์ ํ ๊ฐ์ง๋ ์์ง๋ง ๋์ฒด๋ก ๋น์ทํ ๋๋์ด ๋ ๋ค๋ ์ ์๋ ๋์ํฉ๋๋ค. ์ด์ ์ ํํฌ๋ฅผ ์ฌ์ฉํ์ง ์์๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๊ฐ ๋๋ฌด ๋ช
ํํ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค. ๋ฐ๋ผ์ flutter_hooks
ํจํค์ง์ ํจ๊ป ํํฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ค์ ๊ท๋ชจ์ ํ๋ก์ ํธ๋ฅผ ์ํํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ด๋ค ๋๋์ธ๊ฐ์. ์ ๋ Flutter ์ฌ์ฉ์๋ก์ ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ํํฌ๊ฐ ์๋ฃจ์
์ ์ ๊ณตํ๋ ์ด๋ฌํ ๋ฌธ์ ์ ๋ถ๋ช์ณค์ต๋๋ค. ์ด๋ฌํ ๋ฌธ์ ๊ฐ ์ค์ ๋ก ์ฐ๋ฆฌ์๊ฒ ์กด์ฌํ๋ค๋ ๊ฒ์ ์ด๋ป๊ฒ ํ์ ํ ์ ์๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๋ ๋์ ๋ฐฉ๋ฒ์ด ์์ผ๋ฉด ์๋ ค์ฃผ์ญ์์ค.
React ๊ด์ ์์ ๋ช ๊ฐ์ง ์๊ฐ์ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
๊ทธ๊ฒ๋ค์ด ๊ด๋ จ์ด ์๋ค๋ฉด ์ฉ์ํ์ง๋ง Hooks์ ๋ํด ์ฐ๋ฆฌ๊ฐ ์ด๋ป๊ฒ ์๊ฐํ๋์ง ๊ฐ๋ตํ๊ฒ ์ค๋ช
ํ๊ณ ์ถ์์ต๋๋ค.
ํํฌ๋ ํ์คํ "์จ๊ธฐ๊ธฐ"์ ๋๋ค. ๋๋ ์ด๋ป๊ฒ ๋ณด๋๋์ ๋ฐ๋ผ ์บก์ํํ์ญ์์ค. ํนํ, ๊ทธ๊ฒ๋ค์ ์ง์ญ ์ํ์ ํจ๊ณผ๋ฅผ ์บก์ํํฉ๋๋ค(์ ๋ ์ฐ๋ฆฌ์ "ํจ๊ณผ"๊ฐ "์ผํ์ฉ"๊ณผ ๊ฐ์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค). "์์์ฑ"์ ํธ์ถ๋๋ ๊ตฌ์ฑ ์์์ ์๋ช ์ ์๋์ผ๋ก ์ฒจ๋ถํ๋ค๋ ์ ์ ๋๋ค.
์ด๋ฌํ ๋ด์ฌ์ฑ์ ๋ชจ๋ธ์ ๋ด์ฌ๋์ด ์์ง ์์ต๋๋ค. ๋ชจ๋ ํธ์ถ์ ํตํด ์ธ์๊ฐ ๋ช
์์ ์ผ๋ก ์ค๋ ๋๋๋ ๊ฒ์ ์์ํ ์ ์์ต๋๋ค. ๊ตฌ์ฑ ์์ ์์ฒด์์ ์ฌ์ฉ์ ์ ์ Hook, ๊ฐ ๊ธฐ๋ณธ Hook์ ์ด๋ฅด๊ธฐ๊น์ง ๋ง์
๋๋ค. ๊ทธ๋ฌ๋ ์ค์ ๋ก ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ด ์๋๋ฝ๊ณ ์ค์ ๋ก ์ ์ฉํ์ง ์๋ค๋ ๊ฒ์ ๋ฐ๊ฒฌํ์ต๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ํ์ฌ ์คํ ์ค์ธ Component๋ฅผ ์์์ ์ ์ญ ์ํ๋ก ๋ง๋ค์์ต๋๋ค. ์ด๊ฒ์ VM์ throw
errorHandlerFrame
๊ฐ ์ฝ๋์์ catch
๋ธ๋ก์ ์์ชฝ์ผ๋ก ๊ฒ์ํ๋ ๊ฒ๊ณผ ์ ์ฌํฉ๋๋ค.
์ข์ต๋๋ค. ๋ด๋ถ์ ์์์ ์๋ ์ํ๊ฐ ์๋ ํจ์์ ๋๋ค. ์ข์ง ์์ ๊ฒ ๊ฐ์ต๋๊น? ๊ทธ๋ฌ๋ React์์๋ ์ผ๋ฐ์ ์ผ๋ก ๊ตฌ์ฑ ์์๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค. ์ด๊ฒ์ด ์ปดํฌ๋ํธ์ ์์ ์ ๋๋ค. ๊ทธ๊ฒ๋ค์ (UI ํธ๋ฆฌ์ ์์น์ ํด๋นํ๋) ์๋ช ์ด ์ฐ๊ฒฐ๋ ํจ์์ ๋๋ค. ๊ตฌ์ฑ ์์ ์์ฒด๊ฐ ์ํ์ ๊ด๋ จํ์ฌ ๋ฐํ์ด ์๋ ์ด์ ๋ ์์์ ์ฝ๋์์ ๊ตฌ์ฑ ์์๋ฅผ ํธ์ถํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ค๋ฅธ ๊ตฌ์ฑ ์์์์ ํธ์ถํฉ๋๋ค. ๋ฐ๋ผ์ UI ์ฝ๋์ ์ปจํ ์คํธ์ ๋จ์ ์๊ธฐ ๋๋ฌธ์ ์๋ช ์ด ์๋ฏธ๊ฐ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๋ชจ๋ ๋ฌธ์ ๊ฐ ๊ตฌ์ฑ ์์ ํํ์ธ ๊ฒ์ ์๋๋๋ค. ๊ตฌ์ฑ ์์๋ ์ํ+ํจ๊ณผ์ ๋๋ฌด ์์น์ ์ฐ๊ฒฐ๋ ์๋ช ์ด๋ผ๋ ๋ ๊ฐ์ง ๋ฅ๋ ฅ์ ๊ฒฐํฉํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ์ฒซ ๋ฒ์งธ ๋ฅ๋ ฅ์ด ๊ทธ ์์ฒด๋ก ์ ์ฉํ๋ค๋ ๊ฒ์ ๋ฐ๊ฒฌํ์ต๋๋ค. ํจ์๊ฐ ์ฝ๋๋ฅผ ์บก์ํํ ์ ์๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ์ ์ผ๋ก ์ ์ฉํ๋ฏ์ด ํธ๋ฆฌ์ ์ ๋ ธ๋๋ฅผ ์์ฑํ์ง ์๊ณ ๋ ์ํ+ํจ๊ณผ ๋ฒ๋ค์ ์บก์ํ(๋ฐ ์ฌ์ฌ์ฉ)ํ ์ ์๋ ๊ธฐ๋ณธ ์์๊ฐ ๋ถ์กฑํ์ต๋๋ค. ๊ทธ๊ฒ์ด ๋ฐ๋ก Hooks์ ๋๋ค. ๊ตฌ์ฑ ์์ = ํํฌ + ๋ฐํ๋ UI.
๋ด๊ฐ ์ธ๊ธํ๋ฏ์ด ์ปจํ ์คํธ ์ํ๋ฅผ ์จ๊ธฐ๋ ์์์ ํจ์๋ ๋ฌด์ญ์ต๋๋ค. ์ด๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ๋ฆฐํฐ๋ฅผ ํตํด ๊ท์น์ ์ํํ๋ ์ด์ ์ ๋๋ค. Hook์๋ "์์" ์ด ์์ต๋๋ค. Hook์ ์ฌ์ฉํ๋ฉด ํจ์๋ Hook์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฆฐํฐ๋ ์ปดํฌ๋ํธ๋ ๋ค๋ฅธ Hooks๋ง์ด Hooks๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ๊ฐ์ ํฉ๋๋ค. ์ด๊ฒ์ ์ด์ ๊ตฌ์ฑ ์์ ์์ฒด๋ณด๋ค ๋ ์์์ ์ด์ง ์๊ธฐ ๋๋ฌธ์ ์ปจํ ์คํธ UI ์ํ๋ฅผ ์จ๊ธฐ๋ ์์ ํจ์์ ๋ฌธ์ ๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
๊ฐ๋
์ ์ผ๋ก ์ฐ๋ฆฌ๋ Hook ํธ์ถ์ ์ผ๋ฐ ํจ์ ํธ์ถ๋ก ๋ณด์ง ์์ต๋๋ค. useState()
๋ ๊ตฌ๋ฌธ์ด ์๋ ๊ฒฝ์ฐ use State()
์
๋๋ค. ๊ทธ๊ฒ์ ์ธ์ด ๊ธฐ๋ฅ์ด ๋ ๊ฒ์
๋๋ค. ํจ๊ณผ ์ถ์ ๊ธฐ๋ฅ์ด ์๋ ์ธ์ด์์ ๋์ ํจ๊ณผ๊ฐ ์๋ Hooks์ ๊ฐ์ ๊ฒ์ ๋ชจ๋ธ๋งํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ์๋ฏธ์์ ๊ทธ๊ฒ๋ค ์ ์ผ๋ฐ ํจ์์ด์ง๋ง State๋ฅผ "์ฌ์ฉ"ํ๋ค๋ ์ฌ์ค์ ํ์
์๋ช
์ ์ผ๋ถ๊ฐ ๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฐ ๋ค์ React ์์ฒด๋ฅผ ์ด ํจ๊ณผ์ ๋ํ "์ฒ๋ฆฌ์"๋ก ์๊ฐํ ์ ์์ต๋๋ค. ์ด์จ๋ ์ด๊ฒ์ ๋งค์ฐ ์ด๋ก ์ ์ด์ง๋ง ํ๋ก๊ทธ๋๋ฐ ๋ชจ๋ธ์ ๊ด์ ์์ ์ ํ ๊ธฐ์ ์ ์ง์ ํ๊ณ ์ถ์์ต๋๋ค.
์ค์ฉ์ ์ธ ์ธก๋ฉด์์ ์ฌ๊ธฐ์๋ ๋ช ๊ฐ์ง๊ฐ ์์ต๋๋ค. ์ฒซ์งธ, Hooks๊ฐ React์ "์ถ๊ฐ" API๊ฐ ์๋๋ผ๋ ์ ์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ๊ทธ๋ค์์ด ์์ ์์ ๊ตฌ์ฑ ์์๋ฅผ ์์ฑํ๊ธฐ์ํ API ๋ฐ์์ ๋๋ค. ๋๋ ๊ทธ๋ค์ด ์ถ๊ฐ ๊ธฐ๋ฅ์ผ๋ก์ ๊ทธ๋ค์ง ๋งค๋ ฅ์ ์ด์ง ์์ ๊ฒ์ด๋ผ๋ ๋ฐ ๋์ํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋ฐ๋ผ์ ํ๋ฆผ์์ด ๋ค๋ฅธ ์ ์ฒด ํจ๋ฌ๋ค์์ ๊ฐ์ง Flutter์ ๋ํด ๊ทธ๋ค์ด ์ ๋ง๋ก ์๋ฏธ๊ฐ ์๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๊ทธ๊ฒ๋ค์ด ํ์ฉํ๋ ๊ฒ์ ๊ดํด์๋, ํต์ฌ ๊ธฐ๋ฅ์ ์ํ+์ ํจ ๋ก์ง์ ์บก์ํํ ๋ค์ ์ผ๋ฐ ํจ์ ๊ตฌ์ฑ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ํจ๊ป ์ฐ๊ฒฐํ๋ ๊ธฐ๋ฅ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ํ๋ฆฌ๋ฏธํฐ๋ธ๋ ๊ตฌ์ฑํ๋๋ก ์ค๊ณ๋์๊ธฐ ๋๋ฌธ์ useState()
์ ๊ฐ์ ์ผ๋ถ ํํฌ ์ถ๋ ฅ์ ๊ฐ์ ธ์์ ์ฌ์ฉ์ ์ ์ useGesture(state)
์ ๋ํ ์
๋ ฅ์ผ๋ก ์ ๋ฌํ ๋ค์ ์ด๋ฅผ ์ฌ๋ฌ ์ฌ์ฉ์ ์ ์ useSpring(gesture)
์
๋ ฅ์ผ๋ก ์ ๋ฌํ ์ ์์ต๋๋ค. ์์ฐจ ๊ฐ์ ์ ๊ณตํ๋ ๋ฐ๋ชจ ์ Hooks๊ฐ ๋ฌด์์ธ์ง ๊ฐ๋ตํ๊ฒ ์์ฝํ ๊ธฐ์ฌ ์
๋๋ค.
๋๋ ์ด๊ฒ์ด ์์ฉ๊ตฌ๋ฅผ ์ค์ด๋ ๊ฒ์ด ์๋๋ผ ์ํ ์ ์ฅ ์บก์ํ๋ ๋ก์ง์ ํ์ดํ๋ผ์ธ์ ๋์ ์ผ๋ก ๊ตฌ์ฑํ๋ ๋ฅ๋ ฅ์ ๊ดํ
์ด๊ฒ์ด ์กฐ๊ธ์ด๋ผ๋ ๋์์ด ๋์๋์ง๋ ๋ชจ๋ฅด๊ฒ ์ง๋ง ํ๋ก๊ทธ๋๋ฐ ๋ชจ๋ธ์ ๋ํ ๊ด์ ์ ์กฐ๊ธ์ด๋ผ๋ ๋ฒ์ด๋๊ธธ ๋ฐ๋๋๋ค.
๋ค๋ฅธ ์ง๋ฌธ์ ๋๋ตํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค.
OP๊ฐ ์ธ๊ธํ๋ฏ์ด ๋ชจ๋ ์ข ๋ฅ์ ๋ฌธ์ ๊ฐ ์๋ ๋น๋ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ ๊ฒ์ ์ ์ํ๋ ๊ฒ์ ์๋๋๋ค. ๋ด๊ฐ ์ ์ํ๋ ๊ฒ์ initState/dispose๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๊ฒ ์ ๋ฌธ์ ์ธ์ง ์ ์ดํด๊ฐ ์๋ฉ๋๋ค.
์ฌ๋๋ค์ด #51752 (comment) ์ ์ฝ๋์ ๋ํด ์ด๋ป๊ฒ ๋๋ผ๋์ง ๊ถ๊ธํฉ๋๋ค. ๋๋ ๊ทธ๊ฒ์ด initState/dispose๋ณด๋ค ๋ซ๋ค๊ณ ์๊ฐํ์ง ์์ง๋ง ์ฌ๋๋ค์ด ํํฌ๋ฅผ ์ข์ํ๋ค๋ฉด ๊ทธ๊ฒ๋ ์ข์ํฉ๋๊น? ํํฌ๊ฐ ๋ ๋์๊ฐ์? ๋ ๋์?
late
ํค์๋๋ ์ํฉ์ ๊ฐ์ ํ์ง๋ง ์ฌ์ ํ ๋ช ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
์ด๋ฌํ Property
๋ ๋
๋ฆฝ์ ์ด๊ฑฐ๋ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋ ์ ์๋ ๋งค๊ฐ๋ณ์์ ์์กดํ์ง ์๋ ์ํ์ ์ ์ฉํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ค๋ฅธ ์ํฉ์์๋ ์ฌ์ฉํ๊ธฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค.
๋ ์ ํํ๊ฒ๋ "์
๋ฐ์ดํธ" ๋ถ๋ถ์ด ๋ถ์กฑํฉ๋๋ค.
์๋ฅผ ๋ค์ด StreamBuilder
ํ๋ฉด ์์ ๋๋ ์คํธ๋ฆผ์ด ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ฐ์ฒด๊ฐ ํ ๋ฒ๋ง ์ด๊ธฐํ๋๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์ ๊ทธ๋ฌํ ๊ฒ์ ๊ตฌํํ๋ ์ฌ์ด ์๋ฃจ์
์ด ์์ต๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ํํฌ์๋ ์์ ฏ์ Key
์ ๋์ผํ ๊ธฐ๋ฅ์ด ์์ต๋๋ค. ์ด๋ ํด๋น ํค๊ฐ ๋ณ๊ฒฝ๋ ๋ ์ํ ์กฐ๊ฐ์ด ์๋ฉธ๋๊ณ ๋ค์ ์์ฑ๋๋๋ก ํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด useMemo
๋ ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ์บ์ํ๋ ํํฌ์
๋๋ค.
ํค์ ๊ฒฐํฉํ์ฌ useMemo
๋ฅผ ์ฌ์ฉํ์ฌ ์์์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์ํํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์์ ฏ์ ๋ฉ์์ง ID๋ฅผ ์์ ํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋ฉ์์ง ์ธ๋ถ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐ ์ฌ์ฉํฉ๋๋ค. ๊ทธ๋ฌ๋ ํด๋น ๋ฉ์์ง ID๋ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋ ์ ์์ผ๋ฏ๋ก ์ธ๋ถ์ ๋ณด๋ฅผ ๋ค์ ๊ฐ์ ธ์์ผ ํ ์๋ ์์ต๋๋ค.
useMemo
๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ผ ์ ์์ต๋๋ค.
String messageId;
Widget build(context) {
final Future<Message> message = useMemo(() => fetchMessage(messageId), [messageId]);
}
์ด ์ํ์์ ๋ค์ ๋น๋ ๋ฉ์๋๋ฅผ 10๋ฒ ํธ์ถํด๋ messageId
๊ฐ ๋ณํ์ง ์๋ ํ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๋ ๋ค์ ์ํ๋์ง ์๋๋ค.
๊ทธ๋ฌ๋ messageId
๋ณ๊ฒฝ๋๋ฉด ์๋ก์ด Future
๊ฐ ์์ฑ๋ฉ๋๋ค.
ํ์ฌ ์ํ์ flutter_hooks
๊ฐ Dart์ ๋ํด ์ ์ ๋์ง ์์๋ค๋ ์ ์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ๋ด ๊ตฌํ์ ๋ณธ๊ฒฉ์ ์ธ ์ํคํ
์ฒ๋ณด๋ค POC์ ๊ฐ๊น์ต๋๋ค.
ํ์ง๋ง StatefulWidgets์ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๋ฌธ์ ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์ด๋ ์๋์ง ๊ธฐ์ต๋์ง ์์์ง๋ง ์ด์์ ์ธ ์ธ๊ณ์ ํํฌ๋ async*
& sync*
์์ ์๋ ์ฌ์ฉ์ ์ ์ ํจ์ ์์ฑ๊ธฐ๊ฐ ๋ ๊ฒ์ด๋ผ๊ณ ์ ์ํ ๊ฒ์ ๊ธฐ์ตํฉ๋๋ค. ์ด๋ Dan์ด use State
์ ์ํ ๊ฒ๊ณผ ์ ์ฌํ ์ ์์ต๋๋ค. useState
@gaearon
์ด๊ฒ์ ์์ฉ๊ตฌ๋ฅผ ์ค์ด๋ ๊ฒ์ด ์๋๋ผ ์ํ ์ ์ฅ ์บก์ํ๋ ๋ ผ๋ฆฌ์ ํ์ดํ๋ผ์ธ์ ๋์ ์ผ๋ก ๊ตฌ์ฑํ๋ ๋ฅ๋ ฅ์ ๊ดํ ๊ฒ์์ ๊ฐ์กฐํ๊ณ ์ถ์ต๋๋ค.
์ฌ๊ธฐ์ ๋ ผ์๋๋ ๋ฌธ์ ๋ ๊ทธ๊ฒ์ด ์๋๋๋ค. ๋๋ ๋น์ ์ด ์ค๋ช ํ๋ ๊ฒ์ ํ ์ ์๋ค๋ ๊ฒ์ ๋ํด ์ด์ผ๊ธฐํ๊ธฐ ์ํด ๋ณ๋์ ๋ฒ๊ทธ๋ฅผ ์ ์ถํ๋ ๊ฒ์ด ์ข์ต๋๋ค. (๊ทธ๊ฒ์ ๋งค์ฐ ๋ค๋ฅธ ๋ฌธ์ ์ฒ๋ผ ๋ค๋ฆฌ๊ณ ์์งํ ์ฌ๊ธฐ์ ์ค๋ช ๋ ๋ฌธ์ ๋ณด๋ค ๋ ์ค๋๋ ฅ์ด ์์ต๋๋ค.) ์ด ๋ฒ๊ทธ๋ ํนํ ์ผ๋ถ ๋ ผ๋ฆฌ๊ฐ ๋๋ฌด ์ฅํฉํ ๋ฐฉ๋ฒ์ ๊ดํ ๊ฒ์ ๋๋ค.
์๋์, ๊ทธ๊ฐ ์ณ์์ต๋๋ค. ํผ๋ ์ค๋ฌ์ธ ์ ์์ต๋๋ค.
์์ ์ธ๊ธํ๋ฏ์ด ์ด๊ฒ์ ์ฝ๋ ์ค ์๊ฐ ์๋๋ผ ์ฝ๋ ์ค ์์ฒด์ ๊ดํ ๊ฒ์
๋๋ค.
์ด๊ฒ์ ์ํ๋ฅผ ์ธ์๋ถํดํ๋ ๊ฒ์ ๋๋ค.
์ด ๋ฒ๊ทธ๋ "์ํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ๋๋ฌด ์ฅํฉํ๊ณ /์ด๋ ต์ต๋๋ค"๋ผ๋ ๋ฌธ์ ์ initState์์ ์ ์ธํ ์ฝ๋๊ฐ ํ์ํ ์์ฑ์ด ์์ ๋ ์ํ์ ๋๋ฌด ๋ง์ ์ฝ๋๊ฐ ์๋ค๋ ๋ฌธ์ ์ ๋ํด ๋งค์ฐ ๋ช ํํฉ๋๋ค. dispose ๋ฐ debugFillProperties์์. ๊ด์ฌ ์๋ ๋ฌธ์ ๊ฐ ๋ค๋ฅธ ๋ฌธ์ ์ธ ๊ฒฝ์ฐ ํด๋น ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๋ ์ ๋ฒ๊ทธ๋ฅผ ์ ์ถํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
ํ๊ณ ์ ํ๋ ๋ฌธ์ ๋ฅผ ์์ ํ ์ดํดํ ๋๊น์ง ํํฌ(๋๋ ๋ชจ๋ ์๋ฃจ์ )๋ฅผ ์์ด๋ฒ๋ฆฌ๊ธฐ๋ฅผ ์ ๋ง, ์ ๋ง ๊ฐ๋ ฅํ๊ฒ ๊ถ์ฅํฉ๋๋ค. ๋ฌธ์ ๋ฅผ ๋ช ํํ๊ฒ ์ดํดํด์ผ๋ง ์๋ก์ด ๊ธฐ๋ฅ์ ๋ํด ์ค๋๋ ฅ ์๋ ์ฃผ์ฅ์ ํ ์ ์์ต๋๋ค. ๊ธฐ๋ฅ์ด ํด๊ฒฐํ๋ ๋ฌธ์ ์ ๋ํด ๊ธฐ๋ฅ์ ํ๊ฐํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋๋ ๋น์ ์ด ๊ทธ ๋ฌธ์ ์์ ๋ด๊ฐ ๋งํ ๊ฒ์ ์คํดํ๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ฌธ์ ๋ ์์ฉ๊ตฌ๊ฐ ์๋๋ผ ์ฌ์ฌ์ฉ ๊ฐ๋ฅ์ฑ์ ์์ต๋๋ค.
์์ฉ๊ตฌ๋ ์์ธ์ด ์๋๋ผ ์ฌ์ฌ์ฉ์ฑ ๋ฌธ์ ์ ๊ฒฐ๊ณผ์ ๋๋ค.
์ด ๋ฌธ์ ์์ ์ค๋ช ํ๋ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉ/๊ตฌ์ฑํ๊ณ ์ถ์ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ์ฉ ๊ฐ๋ฅํ ์ต์ ์ ๋ฏน์ค์ธ, ๋น๋ ๋๋ ์ฌ์ฌ์ฉํ์ง ์๋ ๊ฒ์ ๋๋ค. ๋ชจ๋ ๊ณ ์ ํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
๊ธฐ์กด ์ต์
์ ๋ฌธ์ ๋ ์์ฉ๊ตฌ์ ๊ด๋ จ์ด ์์ ์ ์์ง๋ง ์ฐ๋ฆฌ๊ฐ ํด๊ฒฐํ๋ ค๋ ๋ฌธ์ ๋ ๊ทธ๋ ์ง ์์ต๋๋ค.
๋น๋์ ์์ฉ๊ตฌ๋ฅผ ์ค์ด๋ ๊ฒ์ ํ๋์ ๊ฒฝ๋ก(ํํฌ๊ฐ ํ๋ ์ผ)์ด์ง๋ง ๋ค๋ฅธ ๊ฒฝ๋ก๊ฐ ์์ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์ ์ ๋์ ์ ์ํ๊ณ ์ถ์ ๊ฒ์ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ ์ถ๊ฐํ๋ ๊ฒ์ ๋๋ค.
context.onDidChangeDependencies(() {
});
context.onDispose(() {
});
๊ทธ๋ฌ๋ ์ด๊ฒ๋ค์ ๊ทธ๋ค๋ง์ ๋ฌธ์ ๊ฐ ์๊ณ ๋ฌธ์ ๋ฅผ ์์ ํ ํด๊ฒฐํ์ง ๋ชปํฉ๋๋ค. ๊ทธ๋์ ์ ๋ ํ์ง ์์์ต๋๋ค.
@rrousselGit , ๋ฌธ์ ๋ฅผ ๋ ์ ๋ฐ์ํ๊ธฐ ์ํด ์ฌ๊ธฐ ๋งจ ์์ ์๋ ์๋ ๋ฌธ์ ์ค๋ช ์ ์์ ๋กญ๊ฒ ํธ์งํ์ธ์. : ๋ํ ์ค๊ณ ๋ฌธ์ ์์ฑ ์ฃผ์๊ธฐ https://flutter.dev/docs/resources/design-docs ๋ฌธ์ ๋ฌธ์ ์๊ฐ ๊ฐ๋ฅ ๋ฐ๋ํ์ ์ง๊ธ ์ด์ ์ @Hixie์์ ์ ์ ์๋ฏ์ด ์ฐ๋ฆฌ๊ฐ ๋ค์ ํจ๊ป (์ ๋ฐ๋ณต ํ ์ ์์์ ). ์ ๋ ์ฌ๋ฌ๋ถ์ด ๋ค๋ฅธ Flutter ์์ง๋์ด์ฒ๋ผ ํ์ ์ป์์ผ๋ฉด ํฉ๋๋ค. ์ฌ๋ฌ๋ถ์ ํ์ ์ผ์์ด๋ฏ๋ก ํจ๊ป ๋ฐ๋ณตํฉ์๋ค!
๋๋ ๊ทธ ๋ฌธ์ ๋ฅผ ๋ช ๋ฒ์ด๊ณ ๋ค์ ์ดํด๋ณด์๋ค. ์์งํ ์ด๋์๋ถํฐ ์คํด๊ฐ ์๊ธฐ๋์ง ์ดํด๊ฐ ์๊ฐ์ ์ด๋ป๊ฒ ๊ฐ์ ํด์ผ ํ ์ง ๊ฐ์ด ์์กํ๋ค์.
์๋ ์ฃผ์์ ์ฌ์ฌ์ฉ์ฑ/์ธ์๋ถํด์ ๋ํ ์๊ตฌ๋ฅผ ๋ฐ๋ณตํด์ ์ธ๊ธํฉ๋๋ค. ์์ฉ๊ตฌ์ ๋ํ ์ธ๊ธ์ "Flutter๋ ์ฅํฉํฉ๋๋ค"๊ฐ ์๋๋ผ "์ผ๋ถ ๋
ผ๋ฆฌ๋ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค"์
๋๋ค.
๋์์ธ ๋ฌธ์ ์ ์์ด ๊ณต์ ํ์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฐ ๋ฌธ์๋ฅผ ์์ฑํ๋ ๋ฐ ์๋นํ ์๊ฐ์ด ์์๋๋ฉฐ, ์ ๋ ์ฌ๊ฐ ์๊ฐ์ ์ด ์์
์ ์ํํ๊ณ ์์ต๋๋ค.
์ ๋ ๊ฐ์ธ์ ์ผ๋ก ํํฌ์ ๋ง์กฑํฉ๋๋ค. ๋๋ ๋ด ๊ด์ฌ์ฌ๋ฅผ ์ํด ์ด ๋ฌธ์ ๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ ๋ง์ ์ฌ๋๋ค์๊ฒ ์ํฅ์ ๋ฏธ์น๋ ๋ฌธ์ ์ ๋ํ ์ธ์์ ๋์ด๊ธฐ ์ํด ์์ฑํฉ๋๋ค.
๋ช ์ฃผ ์ ์ ์ ๋ ๊ธฐ์กด Flutter ์ฑ์ ๋ํ ์ํคํ ์ฒ์ ๋ํด ๋ ผ์ํ๊ธฐ ์ํด ๊ณ ์ฉ๋์์ต๋๋ค. ์๋ง๋ ์ฌ๊ธฐ์ ์ธ๊ธ๋ ๋ด์ฉ์ด ์ ํํ ์ผ์นํ์ ๊ฒ์ ๋๋ค.
stream
์ธ์คํด์ค๊ฐ ๋ณ๊ฒฝ๋๋ ์๋๋ฆฌ์ค๋ฅผ ์ฒ๋ฆฌํ์ง ์์์ต๋๋ค.
- ์ผ๋ถ ์์ ฏ์ด ํ์๋ ๋ "๋ฉ์์ง"๋ฅผ ์ฝ์ ๊ฒ์ผ๋ก ํ์
๋ด ์ฑ ์ค ํ๋์์ ๊ฒช์๋ ๋ฌธ์ ์ ์ ์ฌํ๊ธฐ ๋๋ฌธ์ ํฅ๋ฏธ๋ก์ด ์ฌ๋ก์ ๋๋ค. ๊ทธ๋์ ๊ฑฐ๊ธฐ์์ ์ฝ๋๋ฅผ ๊ตฌํํ ๋ฐฉ๋ฒ์ ์ดํด๋ณด์์ง๋ง ์ด ๋ฒ๊ทธ๊ฐ ์ค๋ช ํ๋ ๋ฌธ์ ๋ ๊ทธ๋ค์ง ๋ง์ง ์์ต๋๋ค. ๋ฌธ์ ๋ฅผ ์ดํดํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์๋ ์ด์ ์ ๋๋ค. ๋ฌธ์ ์ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
https://github.com/jocosocial/rainbowmonkey/blob/master/lib/src/views/forums.dart
์ค์ ๋ฌธ์ ๋ฅผ ๋ณด๊ธฐ ์ํด ์ฐ๊ตฌํ ์ ์๋ ์ค์ ์ฑ์ ์๊ฐ ์์ต๋๊น?
(BTW, ์ผ๋ฐ์ ์ผ๋ก Streams๋ฅผ ์ ํ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ํฉ์ ์ ํ์ํค๋ ๊ฒ ๊ฐ์ต๋๋ค.)
(BTW, ์ผ๋ฐ์ ์ผ๋ก Streams๋ฅผ ์ ํ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ํฉ์ ์ ํ์ํค๋ ๊ฒ ๊ฐ์ต๋๋ค.)
(์ ์ฌ์ผ๋ก ๋์ํฉ๋๋ค. ํ์ง๋ง ์ปค๋ฎค๋ํฐ๋ ํ์ฌ ๋ฐ๋ ๋ฐ์์ ๋ณด์ด๊ณ ์์ต๋๋ค. Flutter์์ ๊ณต์ ํจํค์ง๋ก ChangeNotifier/Listenable/ValueNotifier๋ฅผ ์ถ์ถํ๋ ๊ฒ์ด ๋์์ด ๋ ์ ์์ต๋๋ค)
์ค์ ๋ฌธ์ ๋ฅผ ๋ณด๊ธฐ ์ํด ์ฐ๊ตฌํ ์ ์๋ ์ค์ ์ฑ์ ์๊ฐ ์์ต๋๊น?
์ฌํ๊ฒ๋ ์๋. ๋ค๋ฅธ ์ฌ๋์ ๋์ฐ๋ฉด์ ๊ฒช์ ๊ฒฝํ์ ๋๋ ์ ์์ ๋ฟ์ ๋๋ค. ์์ ๋ ์ฑ์ด ์์ต๋๋ค.
๋ด ์ฑ ์ค ํ๋์์ ๊ฒช์๋ ๋ฌธ์ ์ ์ ์ฌํ๊ธฐ ๋๋ฌธ์ ํฅ๋ฏธ๋ก์ด ์ฌ๋ก์ ๋๋ค. ๊ทธ๋์ ๊ฑฐ๊ธฐ์์ ์ฝ๋๋ฅผ ๊ตฌํํ ๋ฐฉ๋ฒ์ ์ดํด๋ณด์์ง๋ง ์ด ๋ฒ๊ทธ๊ฐ ์ค๋ช ํ๋ ๋ฌธ์ ๋ ๊ทธ๋ค์ง ๋ง์ง ์์ต๋๋ค. ๋ฌธ์ ๋ฅผ ์ดํดํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์๋ ์ด์ ์ ๋๋ค. ๋ฌธ์ ์ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๊ตฌํ์์ ๋
ผ๋ฆฌ๋ ์๋ช
์ฃผ๊ธฐ์ ์ฐ๊ฒฐ๋์ง ์๊ณ _build_ ๋ด๋ถ์ ๋ฐฐ์น๋๋ฏ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ์์ผ๋ก ์๋ํฉ๋๋ค.
ํน์ ํ ๊ฒฝ์ฐ์ ์๋ฏธ๊ฐ ์์ ์ ์์ต๋๋ค. ๊ทธ ์๊ฐ ์ข์ ๊ฒ์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๋ ๋์ ์๋ pull-to-refresh์ผ ์ ์์ต๋๋ค.
์ผ๋ฐ์ ์ธ pull-to-refresh์์ ์ฐ๋ฆฌ๋ ๋ค์์ ์ํ ๊ฒ์ ๋๋ค:
๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๋ ๋ชจ๋ ๋ฆฌ์์ค์ ์ฌ๋ฌ ํ๋ฉด์ ๋ํด ์ด๋ฌํ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ๋ฅผ ์ํ ๊ฒ์ ๋๋ค. ๋ํ ์ผ๋ถ ํ๋ฉด์์๋ ํ ๋ฒ์ ์ฌ๋ฌ ๋ฆฌ์์ค๋ฅผ ์๋ก ๊ณ ์น ์ ์์ต๋๋ค.
ChangeNotifier + provider
+ StatefulWidget์ ์ด ๋
ผ๋ฆฌ๋ฅผ ์ธ์๋ถํดํ๋ ๋ฐ ์๋นํ ์ด๋ ค์์ ๊ฒช์ ๊ฒ์
๋๋ค.
๋ด ์ต์ ์คํ(๋ถ๋ณ์ฑ ๊ธฐ๋ฐ ๋ฐ flutter_hooks
์์กด)์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ฒด ์คํํธ๋ผ์ ์ง์ํฉ๋๋ค.
final productsProvider = FutureProvider<List<Product>>.autoDispose((ref) async {
final cancelToken = CancelToken();
ref.onDispose(cancelToken.cancel);
return await repository.fetchProducts(cancelToken: cancelToken);
});
// ...
Widget build(context) {
// Listens to the Future created by productsProvider and handles all the refresh logic
AsyncValue<List<Product>> products = useRefreshProvider(
productsProvider,
// TODO consider making a custom hook to encaplusate the snackbar logic
onErrorAfterRefresh: (err, stack) => Scaffold.of(context).showSnackBar(...),
);
return RefreshIndicator(
onRefresh: () => context.refresh(productsProvider),
child: products.when(
loading: () {
return const SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
child: CircularProgressIndicator(),
);
},
error: (err, stack) {
return SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Text('Oops, something unexpected happened\n$err'),
);
},
data: (products) {
return ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
return ProductItem(products[index]);
},
);
},
),
);
}
์ด ๋ ผ๋ฆฌ๋ ์์ ํ ๋ ๋ฆฝ์ ์ ๋๋ค. ๋ชจ๋ ํ๋ฉด ๋ด์ ๋ชจ๋ ๋ฆฌ์์ค์ ํจ๊ป ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํ ํ๋ฉด์์ ์ฌ๋ฌ ๋ฆฌ์์ค๋ฅผ ํ ๋ฒ์ ์๋ก ๊ณ ์น๋ ค๋ฉด ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
AsyncValue<First> first = useRefreshProvider(
firstProvider,
onErrorAfterRefresh: ...
);
AsyncValue<Second> second = useRefreshProvider(
secondProvider,
onErrorAfterRefresh: ...
);
return RefreshIndicator(
onRefresh: () {
return Future.wait([context.refesh(firstProvider), context.refresh(secondProvider)]);
}
...
)
์์ ฏ ์ธ๋ถ์ ์ฑ ์ํ์ ํด๋น ๋ ผ๋ฆฌ๋ฅผ ๋ชจ๋ ๋ฃ๊ณ ์ฑ ์ํ๊ฐ ํ์ฌ ์ฑ ์ํ๋ฅผ ๋ฐ์ํ๋๋ก ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋์ด์ ์๋ก ๊ณ ์นจ์ ์์ ฏ ๋ด์์ ์ํ๊ฐ ํ์ํ์ง ์์ผ๋ฉฐ, ์ฃผ๋ณ ์ํ์ ์๋ก ๊ณ ์นจ์ด ๋ณด๋ฅ ์ค์์ ์๋ฆฌ๊ณ ํฅํ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํฉ๋๋ค.
์ค๋ฅ๋ฅผ ๋ ๋๋งํ๋ ๋ฐฉ๋ฒ๊ณผ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ ๊ฒฐ์ ํ๋ ๊ฒ์ ์ฃผ๋ณ ์ํ์ ์ฑ ์์ด ์๋๋๋ค.
์ด ๋ก์ง์ ์ฐ๋น์ธํธ ์ํ๋ก ๋์ด๋ UI์์ ๋ชจ๋ ๋ก์ง์ด ์ ๊ฑฐ๋๋ ๊ฒ์ ์๋๋๋ค.
UI๋ ์ฌ์ ํ ์ค๋ฅ๋ฅผ ์ ์ฒด ํ๋ฉด์ผ๋ก ํ์ํ ์ง ์ค๋ต๋ฐ์ ํ์ํ ์ง ๊ฒฐ์ ํด์ผ ํฉ๋๋ค.
ํ์ด์ง๋ฅผ ๋ค์ ๋ก๋ํ ๋ ์ค๋ฅ๋ฅผ ๊ฐ์ ๋ก ์๋ก ๊ณ ์ณ์ผ ํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ ์ฌ์ฌ์ฉ์ด ์ ์ต๋๋ค.
๋ ๋๋ง ๋ก์ง์ด ์ฐ๋น์ธํธ ์ํ๊ฐ ์๋ ์์ ฏ์ ์์ ํ ์ ์๋์ด ์์ผ๋ฉด _any_ Future์ ํจ๊ป ์๋ํฉ๋๋ค.
๋๋ ๋น์ ์ด ๋น์ ์ ๋ง์ง๋ง ์๊ฒฌ์์ ์นํธํ๋ ๊ฒ์ ์ ๋ง๋ก ์ดํดํ์ง ๋ชปํฉ๋๋ค. ์์ ์ ์์ ์ธ์ฉํ ์ฝ๋์์ ์ ์ ์๋ฏ์ด ์์ ์๋ก ๊ณ ์นจ ํ์๊ธฐ ์ฝ๋์ฒ๋ผ ๊ฐ๋จํ ์์ ์ ์ํํ๊ธฐ ์ํด ํ๋ ์์ํฌ๋ฅผ ๋ณ๊ฒฝํ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค.
์๋ก ๊ณ ์นจ ํ์๊ธฐ๋ฟ๋ง ์๋๋ผ ์ ๋๋ฉ์ด์ ๋ฑ์ ๊ฒฝ์ฐ ์ด๋ฌํ ์ ํ์ ์ํธ ์์ฉ์ด ๋ง์ ๊ฒฝ์ฐ ์ฑ ์ํ์ ๋๋ ๊ฒ๋ณด๋ค ํ์ํ ๊ณณ์ ๊ฐ์ฅ ๊ฐ๊น์ด ๊ณณ์ ์บก์ํํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ฑ์ ์ฌ๋ฌ ์์น์์ ํ์ํ์ง ์์ ๊ฒฝ์ฐ ์ฑ์ ๋ชจ๋ ๋จ์ผ ์ํธ ์์ฉ์ ๋ํ ์ธ๋ถ ์ฌํญ์ ์ ํ์๊ฐ ์์ต๋๋ค.
๊ธฐ๋ฅ์ ๋ณต์ก์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ์ ๋์ํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ทธ๋ฌํ ๊ธฐ๋ฅ์ด ์ฝ๋ค๋ ๊ฒ์ ๋ณด์ฌ์ฃผ๋ ์๊ฐ ์์ต๋๊น?
์์ ์ ๊ฐ ์์ฑํ ํ ์ฑ์ ์์ค๋ฅผ ๋งํฌํ์ต๋๋ค. ํ์คํ ์๋ฒฝํ ์ฝ๋๋ ์๋๋ฉฐ ๋ค์ ๋ฆด๋ฆฌ์ค๋ฅผ ์ํด ์ผ๋ถ๋ฅผ ๋ค์ ์์ฑํ ๊ณํ์ด์ง๋ง ์ด ํธ์์ ์ค๋ช ํ๋ ๋ฌธ์ ๋ ๊ฒฝํํ์ง ๋ชปํ์ต๋๋ค.
ํ์ง๋ง ๋น์ ์ Flutter์ ๊ธฐ์ ๋ฆฌ๋ ์ค ํ ๋ช
์
๋๋ค.
๋ฌธ์ ์ ์ง๋ฉดํ๋๋ผ๋ ์ฆ์ ํด๊ฒฐ์ฑ
์ ์ ์ํ ์ ์๋ ์ถฉ๋ถํ ๊ธฐ์ ์ด ์์ด์ผ ํฉ๋๋ค.
๊ทธ๋ฌ๋ ๋ค๋ฅธ ํํธ์ผ๋ก ์๋น์์ ์ฌ๋๋ค์ด ๋ค์ ์ฝ๋์ ๋ฌธ์ ์ ์ ์ดํดํ์ง ๋ชปํฉ๋๋ค.
FutureBuilder<User>(
future: fetchUser(),
builder: ...,
)
์ด ์ฌ์ค์ StackOverflow์์ ๋ง๋ Q/AI ๊ฐ ์ผ๋ง๋ ์ธ๊ธฐ๊ฐ ์๋์ง์ ์ํด ์ ์ฆ๋ฉ๋๋ค.
๋ฌธ์ ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๊ณ ๊ฐ๋ ฅํ ๋ฐฉ์์ผ๋ก ์ํ ๋
ผ๋ฆฌ๋ฅผ ์ถ์ํํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ด ์๋๋๋ค(๊ทธ๋ ์ง ์์ผ๋ฉด ์ด ๋ฌธ์ ๋ฅผ ๋ง๋ค ์๋ฏธ๊ฐ ์์ต๋๋ค).
๋ฌธ์ ๋ ๊ทธ๋ ๊ฒ ํ๋ ค๋ฉด ์๊ฐ๊ณผ ๊ฒฝํ์ด ๋ชจ๋ ํ์ํ๋ค๋ ๊ฒ์
๋๋ค.
๊ณต์ ์๋ฃจ์
์ ์ ๊ณตํจ์ผ๋ก์จ ์ ํ๋ฆฌ์ผ์ด์
์ ์ ์ง ๊ด๋ฆฌํ ์ ์๊ฒ ๋ ๊ฐ๋ฅ์ฑ์ ์ค์ฌ ์ ๋ฐ์ ์ธ ์์ฐ์ฑ๊ณผ ๊ฐ๋ฐ์ ๊ฒฝํ์ ํฅ์์ํต๋๋ค.
๋ชจ๋ ์ฌ๋์ด ๊ทํ์ ๋ถ๋์ฐ ์ ์์ ์ ์ํ ์ ์๋ ๊ฒ์ ์๋๋๋ค. ๊ทธ๋ฌํ ๊ฒ์ด Flutter ๋ด๋ถ์ ๊ตฌ์ถ๋๋ค๋ฉด ๋ฌธ์ํ๋๊ณ ๊ฐ์์ฑ์ ์ป์ ์ ์์ผ๋ฉฐ ๊ถ๊ทน์ ์ผ๋ก ์ฒ์์๋ ๊ทธ๊ฒ์ ๋ํด ์๊ฐํ์ง ๋ชปํ ์ฌ๋๋ค์๊ฒ ๋์์ด ๋ ๊ฒ์
๋๋ค.
๋ฌธ์ ๋ ์ฑ์ด ๋ฌด์์ธ์ง, ์ํ๊ฐ ์ด๋ป๊ฒ ์๊ฒผ๋์ง ๋ฑ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค. ์ฌ๊ธฐ์ ์ง๋ฌธ์ด "์ฑ ์ํ๋ฅผ ์ด๋ป๊ฒ ๊ด๋ฆฌํฉ๋๊น?"๋ผ๋ฉด ๋๋ต์ ํํฌ์ ๊ฐ์ ๊ฒ์ด ์๋๋๋ค. ์ด๋ฅผ ์ํํ๋ ๋ค์ํ ๋ฐฉ๋ฒ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ๋ค์ํ ์ํฉ์ ๋ํด ๋ค๋ฅธ ๊ธฐ์ ์ ๊ถ์ฅํ๋ ๋ง์ ๋ฌธ์์ ๋๋ค... ๊ธฐ๋ณธ์ ์ผ๋ก ์ด ์ธํธ์ ๋ฌธ์: https://flutter.dev/docs/development/data-and-backend/state-mgmt
์์ ์ํ์ ์ฑ ์ํ๊ฐ ์์ง๋ง ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก๋ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋จ์ผ ์ ํ์ ์์ ฏ์๋ง ๊ด๋ จ๋์ง๋ง ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ํด๋น ์ ํ์ ์์ ฏ ๊ฐ์ ๊ณต์ ํ๋ ค๋ ์ํ์ ๋๋ค.
์๋ฅผ ๋ค์ด ScrollController
๋ ์ผ๋ถ ์ ํ์ ์ ๋๋ฉ์ด์
์ ํธ์ถํ ์ ์์ง๋ง ๋ชจ๋ ์ฑ์์ ์ฌ์ฉํด์ผ ํ๋ ๋ฐ์ดํฐ๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ์ ์ญ ์ฑ ์ํ์ ๋ฃ๋ ๊ฒ์ด ๋ฐ๋์ ์ ์ ํ์ง๋ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๋ฌ ScrollController
๊ฐ ๋์ผํ ๋
ผ๋ฆฌ๋ฅผ ๊ฐ์ง ์ ์์ผ๋ฉฐ ๊ฐ๊ฐ์ ๋ผ์ดํ ์ฌ์ดํด ๋
ผ๋ฆฌ๋ฅผ ๊ณต์ ํ๋ ค๊ณ ํฉ๋๋ค. ์ํ๋ ์ฌ์ ํ ScrollController
์ ์ฉ์ด๋ฏ๋ก ์ ์ญ ์ฑ ์ํ๋ ์๋์ง๋ง ๋
ผ๋ฆฌ๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ผ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ์ต๋๋ค.
๋ํ ์ด ๋ก์ง์ ํจํค์งํ์ฌ ํฅํ ํ๋ก์ ํธ๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ ํ๋ก์ ํธ์์๋ ๋ ์ฝ๊ฒ ๊ตฌ์ฑํ ์ ์๋๋ก ํ ์ ์์ต๋๋ค. useHooks ์ฌ์ดํธ๋ฅผ ๋ณด๋ฉด ํน์ ์ผ๋ฐ์ ์ธ ์์
์ ๊ตฌ๋ถํ๋ ๋ง์ ๋
ผ๋ฆฌ๋ฅผ ๋ณผ ์ ์์ต๋๋ค. useAuth
๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํ ๋ฒ ์์ฑํ๊ณ initState
๋๋ dispose
ํธ์ถ์ ๋์ณค๋์ง ๋๋ ๋น๋๊ธฐ ํจ์์ then
๊ฐ ์๋์ง ์ฌ๋ถ์ ๋ํด ๊ฑฑ์ ํ ํ์๊ฐ ์์ต๋๋ค. catch
. ํจ์๋ ํ ๋ฒ๋ง ์์ฑ๋๋ฏ๋ก ๊ธฐ๋ณธ์ ์ผ๋ก ์ค๋ฅ์ ์ฌ์ง๊ฐ ์ฌ๋ผ์ง๋๋ค. ๋ฐ๋ผ์ ์ด๋ฌํ ์ข
๋ฅ์ ์๋ฃจ์
์ ๋์ผํ ์ฑ์ ์ฌ๋ฌ ๋ถ๋ถ๊ณผ ์ฌ๋ฌ ์ฑ ๊ฐ์ ๊ตฌ์ฑํ ์ ์์ ๋ฟ๋ง ์๋๋ผ ์ต์ข
ํ๋ก๊ทธ๋๋จธ์๊ฒ๋ ๋ ์์ ํฉ๋๋ค.
๋๋ ์ฌ๋๋ค์ด ํํฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ฐ๋ํ์ง ์์ต๋๋ค. ๋ด๊ฐ ๋งํ ์ ์๋ ํ, ๊ทธ๊ฒ์ ๋ง๋ ๊ฒ์ ์๋ฌด๊ฒ๋ ์์ต๋๋ค. (๋ง์ฝ ๊ทธ๊ฒ์ ๋ฐฉํดํ๋ _is_ ๊ฒฝ์ฐ, ๊ทธ๊ฒ์ ๋ํ ๋ฒ๊ทธ๋ฅผ ์ ๊ณ ํ์ญ์์ค.)
์ด ๋ฒ๊ทธ๋ ํํฌ์ ๊ดํ ๊ฒ์ด ์๋๋ผ "์ํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ๋๋ฌด ์ฅํฉํ๊ณ /์ด๋ ต์ต๋๋ค"์ ๊ดํ ๊ฒ์ ๋๋ค. ์ ๋ ์ด๊ฒ์ด ์ Flutter๋ฅผ ๋ณ๊ฒฝํด์ผ ํ๋์ง ์ดํดํ๊ธฐ ์ํด ๊ณ ๊ตฐ๋ถํฌํ๊ณ ์์ต๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๋ค ์์ผ๋ก๋ ๊ตฌ์กฐํํ์ฌ ์ฅํฉํจ์ ํผํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๋ ๋ง์ ์์ (ํ ํฌํจ)๊ฐ ์์๊ณ ์ด๋ฏธ ์ด์ ๋ํ ๋ง์ ๋ฌธ์๊ฐ ์์ต๋๋ค.
์ด๋ฏธ Flutter๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ๋น๋๋ ํํฌ ํจํค์ง์ ๊ฐ์ ๊ฒ์ด ์กด์ฌํ๋ ๊ฒฝ์ฐ ํํฌ์ ๋ํ ์์ฌ ์๋ฃจ์ ์ด ํ์ํ ์ด์ ๊ฐ ๋ฌด์์ ๋๊น? @rrousselGit ์ด ์ด์ ๋ํด ๋ ์ ๋ต๋ณํ ์ ์๋ค๊ณ ์๊ฐํ์ง๋ง ๋ต๋ณ์๋ ๋ ๋์ ์ง์, ๋ ํตํฉ๋ ์ง์ ๋ฐ ๋ ๋ง์ ์ฌ๋๋ค์ด ์ฌ์ฉํ๋ ๊ฒ์ด ํฌํจ๋ฉ๋๋ค.
๊ทธ ์ธ์๋ ํ๋ฉด์ ์ผ๋ก flutter_hooks ํจํค์ง๊ฐ ์ด๋ฏธ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ํํฌ๋ฅผ ์ง์ํ๊ธฐ ์ํด Flutter๋ฅผ ๊ทผ๋ณธ์ ์ผ๋ก ๋ณ๊ฒฝํด์ผ ํ๋ ์ด์ ๊ฐ ๋ฌด์์ธ์ง ํผ๋์ค๋ฝ์ต๋๋ค.
Flutter๋ฅผ ๋ณ๊ฒฝํด์ผ ํ๋ ์ด์ ๋ฅผ ์ดํดํ๊ธฐ ์ํด ์ฌ์ ํ ๊ณ ์ฌํ๊ณ ์์ต๋๋ค.
์ปค๋ฎค๋ํฐ๊ฐ ํจํค์ง๋ฅผ ๋ง๋ค์๊ธฐ ๋๋ฌธ์ ์ด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์๋ค๊ณ ๋งํ๋ ๊ฒ์ ๋ด๊ฐ Freezed ๋ฅผ ๋ง๋ค์๊ธฐ ๋๋ฌธ์ Dart์ ๋ฐ์ดํฐ ํด๋์ค + ๊ณต์ฉ์ฒด ์ ํ์ด ํ์ํ์ง ์๋ค๊ณ ๋งํ๋ ๊ฒ๊ณผ
Freezed๋ ์ด ๋ ๊ฐ์ง ๋ฌธ์ ์ ๋ํ ์๋ฃจ์
์ผ๋ก ์ปค๋ฎค๋ํฐ์์ ์๋นํ ์ข์ํ ์ ์์ง๋ง ์ฌ์ ํ ๋ ์ํ ์ ์์ต๋๋ค.
Flutter ํ์ ์ปค๋ฎค๋ํฐ๋ณด๋ค ํจ์ฌ ๋ ๋ง์ ์ํฅ๋ ฅ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ ์ฒด ์คํ์ ์์ ํ ์ ์๋ ๊ธฐ๋ฅ์ด ๋ชจ๋ ์์ต๋๋ค. ๊ฐ ๋ถ๋ถ์ ์ ๋ฌธ๊ฐ์ธ ์ฌ๋๋ค; ๊ทธ๋ฆฌ๊ณ ํ์ํ ์ผ์ ํ์ํ๊ธฐ ์ํ ๊ธ์ฌ.
์ด ๋ฌธ์ ๋ ๊ทธ๊ฒ์ด ํ์ํฉ๋๋ค.
๊ธฐ์ตํ์ญ์์ค: React ํ์ ๋ชฉํ ์ค ํ๋๋ JSX์ ๊ฐ์ด ํํฌ๊ฐ ์ธ์ด์ ์ผ๋ถ๊ฐ ๋๋ ๊ฒ์
๋๋ค.
์ธ์ด ์ง์์ด ์๋๋ผ๋ ์ฌ์ ํ ๋ถ์๊ธฐ ์์ ์ด ํ์ํฉ๋๋ค. ๋คํธ ํจ๋; ํ๋ฌํฐ/๊ฐ๋ฐ๋๊ตฌ; Flutter๊ฐ ์ํํ๋ ๋ชจ๋ ๋ค์ํ ์์ (์: ์์์ ์ ๋๋ฉ์ด์ , ์์ ๋ฑ)์ ๋จ์ํํ๋ ๋ง์ ํํฌ.
๋น๋ก Flutter์ ์ผ๋ฐ์ ์ธ ์ฒ ํ์ด ์์ ํต์ฌ์ ๊ฐ๊ณ ์๊ธฐ๋ ํ์ง๋ง ์ข์ ์ฃผ์ฅ์ ๋๋ค. ์ด๋ฌํ ์ด์ ๋ก Google, cf ์บ๋ฆญํฐ ๋ฐ ์ ๋๋ฉ์ด์ ์ด ์ ๊ณต๋๋ ๊ฒฝ์ฐ์๋ ํจํค์ง๋ก ์๋ก์ด ๊ธฐ๋ฅ์ ์ ์ ๋ ์ถ๊ฐํ๊ณ ์์ต๋๋ค. ์ด๋ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ฐฐ์ฐ๊ณ ๋ณํํ ์ ์๋ ๋ ํฐ ์ ์ฐ์ฑ์ ์ ๊ณตํฉ๋๋ค. ํจํค์ง๊ฐ ์ถฉ๋ถํ์ง ์์ ๊ฐ๋ ฅํ ๊ธฐ์ ์ ์ด์ ๊ฐ ์๋ ํ(ํ์ฅ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ฉด ๊ทธ ์ด๋ ๋๋ณด๋ค ๊ฐ๋ฅ์ฑ์ด ๋ฎ์) ์ด ๊ณต๊ฐ์ ๋ํด์๋ ๋์ผํ ์์ ์ ์ํํฉ๋๋ค.
Flutter์ ํต์ฌ์ ๋ฌด์ธ๊ฐ๋ฅผ ๋ฃ๋ ๊ฒ์ ๊น๋ค๋กญ์ต๋๋ค. ํ ๊ฐ์ง ๋ฌธ์ ๋ ์ง์ ๊ฒฝํ์ ํตํด ์ ์๋ค์ํผ ์ํ๊ฐ ๋ฐ์ํ UI ์ํคํ ์ฒ์์ ์ ์๋ํ๋ ๊ฒ์ ๋ํด ๋ ๋ง์ด ๋ฐฐ์ฐ๋ฉด์ ์งํํ๋ ์์ญ์ด๋ผ๋ ๊ฒ์ ๋๋ค. 2๋ ์ ๋ง ํด๋ ์น์๋ฅผ ์ ํํด์ผ ํ๋ค๋ฉด BLoC๋ฅผ ์ ํํ์ ์๋ ์์ง๋ง ๋น์ฐํ ๊ณต๊ธ์ ํจํค์ง๊ฐ ์ธ์๋์ด ํ์ฌ ๊ธฐ๋ณธ ๊ถ์ฅ ์ฌํญ์ ๋๋ค.
flutter_hooks ๋๋ ๊ฒฌ์ธ๋ ฅ์ด ์๋ ์ ์ฌํ ํํฌ ํจํค์ง๋ฅผ ์ง์ํ๋ Google ๊ณ ์ฉ ๊ธฐ์ฌ์๋ฅผ ํธ์ํ๊ฒ ์๊ฐํ ์ ์์ต๋๋ค(๋ฌผ๋ก ์ฐ๋ฆฌ ์ ๊ด์ฌ์ ๋๊ธฐ ์ํด ๊ฒฝ์ํ๋ ๋ค๋ฅธ ์์ ์ด
ํฅ๋ฏธ๋ก์ด ์ฃผ์ฅ, @timsneath. Rust ์ปค๋ฎค๋ํฐ๋ ๋น์ทํ ์ผ์ ํฉ๋๋ค. ์ธ์ด๋ ํ๋ ์์ํฌ์ ํต์ฌ ๋๋ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ ๋ฒ ๋์ ๋๋ฉด ๊บผ๋ด๊ธฐ๊ฐ ๋งค์ฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ๋๋ค. Rust์ ๊ฒฝ์ฐ ์์ํ ์ด์ ๋ฒ์ ๊ณผ์ ํธํ์ฑ์ ์ ์งํ๊ธฐ๋ฅผ ์ํ๊ธฐ ๋๋ฌธ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค. ๋ฐ๋ผ์ ๊ทธ๋ค์ ํจํค์ง๊ฐ ๋์ฐฉํ ๋๊น์ง ๊ธฐ๋ค๋ ธ๋ค๊ฐ ์์์ ์น์๊ฐ ๋ํ๋ ๋๊น์ง ์๋ก ๊ฒฝ์ํ ๋ค์ ์ด๋ฅผ ์ธ์ด๋ก ์ ์ต๋๋ค.
์ด๊ฒ์ Flutter์ ๋น์ทํ ๊ฒฝ์ฐ์ผ ์ ์์ต๋๋ค. React๊ฐ ํด๋์ค์์ ํํฌ๋ก ์ด๋ํด์ผ ํ์ง๋ง ์ฌ์ ํ ํด๋์ค๋ฅผ ์ ์งํด์ผ ํ๊ณ ์ฌ๋๋ค์ด ๋ง์ด๊ทธ๋ ์ด์ ํด์ผ ํ๋ ๊ฒ์ฒ๋ผ ๋์ค์ ํํฌ๋ณด๋ค ๋ ๋์ ๊ฒ์ด ์์ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ฉด ์ฝ์ด์ ์ถ๊ฐ๋๊ธฐ ์ ์ ๊ฒฝ์ ์ํ ๊ด๋ฆฌ ์๋ฃจ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋์ ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์๋ง๋ ์ฐ๋ฆฌ ์ปค๋ฎค๋ํฐ๋ ํํฌ ์์์ ํ์ ํ๊ฑฐ๋ ๋ ๋์ ์๋ฃจ์ ์ ์ฐพ์์ผ ํ ๊ฒ์ ๋๋ค.
๋๋ ๊ทธ ์ฐ๋ ค๋ฅผ ์ดํดํ์ง๋ง ์ด๊ฒ์ ์ํ ๊ด๋ฆฌ ์๋ฃจ์ ์ ๊ดํ ๊ฒ์ด ์๋๋๋ค.
์ด๋ฌํ ๊ธฐ๋ฅ์ Inheritedwidget ๋ฐ StatefulWidget์ ๋ ๊ฐ๊น์ต๋๋ค. ์ด๋ ์ธ์ด ๊ธฐ๋ฅ๋งํผ ๋ฎ์ ์ ์๋ ๋ฎ์ ์์ค์ ๊ธฐ๋ณธ ์์์ ๋๋ค.
ํํฌ๋ ํ๋ ์์ํฌ์ ๋
๋ฆฝ์ ์ผ ์ ์์ง๋ง ์ด๋ ์ด์ ์ํด์๋ง ๊ฐ๋ฅํฉ๋๋ค.
์ด์ ์ ์ธ๊ธํ๋ฏ์ด ์ด ๋ฌธ์ ์ ๋ ๋ค๋ฅธ ๊ฒฝ๋ก๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
context.onDispose(() {
});
๊ทธ๋ฆฌ๊ณ ์ ์ฌํ ์ด๋ฒคํธ ๋ฆฌ์ค๋.
ํ์ง๋ง ํ๋ ์์ํฌ ๋ฐ์์ ๊ตฌํํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
์ด๋ค ํ์ด ๋์ฌ์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ๊ทธ๋ฌํ ์๋ฃจ์
์ด Element ๋ฐ๋ก ์์ ์์ด์ผ ํ ๊ฐ๋ฅ์ฑ์ ๋ฐฐ์ ํ ์ ์์ต๋๋ค.
ํ์ฅ ํ๋ก๊ทธ๋จ์ด ๋์์ด ๋ฉ๋๊น?
(ํ์ง๋ง ๋ค๋ฅธ ๋ฌธ์ ์์ ๊ทธ๊ฒ์ ๋ํด ์ด์ผ๊ธฐํด์ผ ํ ์๋ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ ์ฃผ์ ์์ ๋ฒ์ด๋ฌ์ต๋๋ค. ์ฌ๋๋ค์ด ๋ณด๊ณ ์๋ ๋ฌธ์ ๋น ํ๋์ ๋ฌธ์ ๋ฅผ ๊ฐ๊ณ ์ฌ๋ฐ๋ฅธ ์ฅ์์์ ์๋ฃจ์
์ ๋
ผ์ํ ์ ์๋ค๋ฉด ์ ๋ง ์ข๊ฒ ์ต๋๋ค. ๊ทธ๋ ์ง ์์ต๋๋ค. context.onDispose
๊ฐ ์์ธํ ์ ๋ณด ํ์์ ์ด๋ป๊ฒ ๋์์ด ๋๋์ง ๋ช
ํํ ํฉ๋๋ค.)
๋๋ ์ด๊ฒ๊ณผ ๊ด๋ จํ์ฌ ์ฐ๋ฆฌ๊ฐ ์๊ฐํด๋ผ ์ ์๋ ์ ๋ง ์ข์ ์ธ์ด ์ ์์ด ์๋ค๊ณ ๊ฐ๋ ฅํ ์์ฌํฉ๋๋ค.
ํน์ ์ํ ๊ด๋ฆฌ ๊ด์ฉ๊ตฌ๋ฅผ ํ์ฑํํ๋ ๋ฐฉ๋ฒ๋ณด๋ค ์ด์ ๋ํด ๋ ๊ตฌ์ฒด์ ์ผ๋ก ์ด์ผ๊ธฐํ๋ ๊ฒ์ด ๋์์ด ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ฐ๋ฆฌ๋ ๊ทธ๋ค์ด ๋ฌด์์ ๊ฐ๋ฅํ๊ฒ ํ๊ณ ์ด๋ค ์ ์ถฉ์ ์๋ฐํ ์ ์๋์ง ๋ ์ง์งํ๊ฒ ๊ณ ๋ คํ ์ ์์ต๋๋ค.
ํนํ VM ๋ฐ JS ๋ฐํ์ ๋ชจ๋์์ ์๋ํ ์ ์๋์ง ์ฌ๋ถ์ ๋ฐฉ๋ฒ์ ๊ณ ๋ คํ ์ ์์ต๋๋ค.
context.onDispose
๊ฐ ์ฅํฉํจ์ ์ด๋ป๊ฒ ๋์์ด ๋๋์ง ๋ช ํํ์ง ์์ต๋๋ค.)
์์ ์ธ๊ธํ๋ฏ์ด ์ด ๋ฌธ์ ๋ ์ฅํฉํจ๋ณด๋ค ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๊ดํ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ๋ ๋ง์ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๋ค๋ฉด ์์์ ์ผ๋ก ์ฅํฉํจ์ ์ค์ฌ์ผ ํฉ๋๋ค.
context.onDispose
๊ฐ ์ด ๋ฌธ์ ์ ๊ด๋ จ๋ ๋ฐฉ์์ ํ์ฌ ๊ตฌ๋ฌธ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
AnimationController controller;
<strong i="11">@override</strong>
void initState() {
controller = AnimationController(...);
}
<strong i="12">@override</strong>
void dispose() {
controller.dispose();
}
๋ฌธ์ ๋:
context.onDispose
๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
<strong i="21">@override</strong>
void initState() {
controller = AnimationController(...);
context.onDispose(controller.dispose);
}
ํฅ๋ฏธ๋ก์ด ๋ถ๋ถ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
@์ฐ์ธํ๋ค
๋ฌดํจ initState() {
์ปจํธ๋กค๋ฌ = someReusableLogic(์ปจํ
์คํธ);
}
```
controller
์ ๋
ผ๋ฆฌ๋ ์ฌ์ ํ ์ฝ๊ฒ ์ฝ์ ์ ์์ต๋๋ค.์ด ์ ๊ทผ ๋ฐฉ์์ ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
context.myLifecycle(() {...})
์(๋) ํซ ๋ฆฌ๋ก๋ํ ์ ์์ต๋๋ค.someReusableLogic
๊ฐ StatefulWidget
์์ ์์ฑ์ ์ฝ๋๋ก ํ๋ ๋ฐฉ๋ฒ์ ๋ถ๋ถ๋ช
ํฉ๋๋ค.AnimationController
์ Duration
๋ ์์ ฏ์ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ง์ ์๊ฐ์ด ๋ณ๊ฒฝ๋๋ ์๋๋ฆฌ์ค๋ฅผ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.ValueNotifier
์ ์์กดํ๊ณ ๋ฆฌ์ค๋๋ฅผ ๋ค๋ฃฐ ํ์ ์์ด ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋ ์ ์๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ด ๋ถ๋ถ๋ช
ํฉ๋๋ค.์ธ์ด ์ ์์ ๋ํด ์๊ฐํ๊ฒ ์ต๋๋ค. ๋ช ๊ฐ์ง ์์ด๋์ด๊ฐ ์์ง๋ง ์ง๊ธ ๋น์ฅ์ ์ด์ผ๊ธฐํ ๊ฐ์น๊ฐ ์์ต๋๋ค.
์์ ์ธ๊ธํ๋ฏ์ด ์ด ๋ฌธ์ ๋ ์ฅํฉํจ๋ณด๋ค ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๊ดํ ๊ฒ์ ๋๋ค.
ํ์ธ. ์ ๋ฒ๊ทธ๋ฅผ ์ ๊ณ ํ ๋ค์ ๊ตฌ์ฒด์ ์ผ๋ก ์ค๋ช ํ๋ ๋ฒ๊ทธ๋ฅผ ์ ์ถํด ์ฃผ์๊ฒ ์ต๋๊น? ์ด ๋ฒ๊ทธ๋ ๋ง ๊ทธ๋๋ก "์ํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ๋๋ฌด ์ฅํฉํ๊ณ /์ด๋ ต์ต๋๋ค"๋ผ๊ณ ํฉ๋๋ค. ์์ธํ ๋ด์ฉ์ด ๋ฌธ์ ๊ฐ ์๋ ๊ฒฝ์ฐ _this_๋ ๋ฌธ์ ๊ฐ ์๋๋๋ค.
context.onDispose
๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์์ ์ํํ ์ ์์ต๋๋ค.<strong i="11">@override</strong> void initState() { controller = AnimationController(...); context.onDispose(controller.dispose); }
์ context
๊ฐ ์ด๊ฒ๊ณผ ๊ด๋ จ์ด ์๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค( onDispose
๋ ์ฐ๋ฆฌ์ ๋ช
๋ช
๊ท์น์ ์๋ฐํฉ๋๋ค). ๊ทธ๋ฌ๋ ํ๊ธฐ ์ค์ ์คํํ ํญ๋ชฉ์ ๋ฑ๋กํ๋ ๋ฐฉ๋ฒ์ ์ํ๋ฉด ์ค๋ ์ฝ๊ฒ ํ ์ ์์ต๋๋ค.
mixin StateHelper<T extends StatefulWidget> on State<T> {
List<VoidCallback> _disposeQueue;
void queueDispose(VoidCallback callback) {
_disposeQueue ??= <VoidCallback>[];
_disposeQueue.add(callback);
}
<strong i="17">@override</strong>
void dispose() {
if (_disposeQueue != null) {
for (VoidCallback callback in _disposeQueue)
callback();
}
super.dispose();
}
}
๋ค์๊ณผ ๊ฐ์ด ํธ์ถํ์ญ์์ค.
class _MyHomePageState extends State<MyHomePage> with StateHelper<MyHomePage> {
TextEditingController controller;
<strong i="21">@override</strong>
void initState() {
super.initState();
controller = TextEditingController(text: 'button');
queueDispose(controller.dispose);
}
...
AnimationController someReusableLogic(BuildContext context) { final controller = AnimationController(...); controller.onDispose(controller.dispose); controller.forward(); void listener() {} controller.addListener(listener); context.onDispose(() => controller.removeListener(listener)); } ... <strong i="25">@override</strong> void initState() { controller = someReusableLogic(context); }
๋น์ ๋ ๊ทธ๋ ๊ฒ ํ ์ ์์ต๋๋ค:
AnimationController someReusableLogic<T extends StatefulWidget>(StateHelper<T> state) {
final controller = AnimationController(...);
state.queueDispose(controller.dispose);
controller.forward();
void listener() {}
controller.addListener(listener);
state.queueDispose(() => controller.removeListener(listener));
return controller;
}
...
<strong i="6">@override</strong>
void initState() {
controller = someReusableLogic(this);
}
์ด ์ ๊ทผ ๋ฐฉ์์ ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
context.myLifecycle(() {...})
์(๋) ํซ ๋ฆฌ๋ก๋ํ ์ ์์ต๋๋ค.
์ด ์ปจํ ์คํธ์์๋ initState์์ ํธ์ถ๋ ํญ๋ชฉ์๋ง ํด๋น๋๋ฏ๋ก ์ค์ํ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค. ๋ด๊ฐ ๋ญ๊ฐ๋ฅผ ๋์น๊ณ ์์ต๋๊น?
- ํจ์๋ฅผ ์์ ฏ ์ ์์ ๋ฐ์ ํ๊ฒ ์ฐ๊ฒฐํ์ง ์๊ณ
someReusableLogic
๊ฐStatefulWidget
์์ ์์ฑ์ ์ฝ๋๋ก ํ๋ ๋ฐฉ๋ฒ์ ๋ถ๋ถ๋ช ํฉ๋๋ค.
์๋ฅผ ๋ค์ดAnimationController
์Duration
๋ ์์ ฏ์ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ง์ ์๊ฐ์ด ๋ณ๊ฒฝ๋๋ ์๋๋ฆฌ์ค๋ฅผ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.
dispose ํ์ ๋ง์ฐฌ๊ฐ์ง๋ก didChangeWidget ํ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค.
mixin StateHelper<T extends StatefulWidget> on State<T> {
List<VoidCallback> _disposeQueue;
List<VoidCallback> _didUpdateWidgetQueue;
void queueDispose(VoidCallback callback) {
_disposeQueue ??= <VoidCallback>[];
_disposeQueue.add(callback);
}
void queueDidUpdateWidget(VoidCallback callback) {
_didUpdateWidgetQueue ??= <VoidCallback>[];
_didUpdateWidgetQueue.add(callback);
}
<strong i="24">@override</strong>
void didUpdateWidget(T oldWidget) {
super.didUpdateWidget(oldWidget);
if (_didUpdateWidgetQueue != null) {
for (VoidCallback callback in _didUpdateWidgetQueue)
callback();
}
}
<strong i="25">@override</strong>
void dispose() {
if (_disposeQueue != null) {
for (VoidCallback callback in _disposeQueue)
callback();
}
super.dispose();
}
}
AnimationController conditionalAnimator(StateHelper state, ValueGetter<bool> isAnimating, VoidCallback listener) {
final controller = AnimationController(vsync: state as TickerProvider, duration: const Duration(seconds: 1));
state.queueDispose(controller.dispose);
controller.addListener(listener);
state.queueDispose(() => controller.removeListener(listener));
if (isAnimating())
controller.repeat();
state.queueDidUpdateWidget(() {
if (isAnimating()) {
controller.repeat();
} else {
controller.stop();
}
});
return controller;
}
๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉ๋ฉ๋๋ค.
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
<strong i="6">@override</strong>
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(animating: false),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.animating}) : super(key: key);
final bool animating;
<strong i="7">@override</strong>
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with StateHelper<MyHomePage>, SingleTickerProviderStateMixin {
AnimationController controller;
<strong i="8">@override</strong>
void initState() {
super.initState();
controller = conditionalAnimator(this, () => widget.animating, () { print(controller.value); });
}
<strong i="9">@override</strong>
Widget build(BuildContext context) {
return Center(
child: FadeTransition(
opacity: controller,
child: Text('Hello', style: TextStyle(fontSize: 100.0, color: Colors.white)),
),
);
}
}
ValueNotifier
์ ์์กดํ์ง ์๊ณ ๋ฆฌ์ค๋๋ฅผ ์ฒ๋ฆฌํ์ง ์๊ณ ๋ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋ ์ ์๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ด ๋ถ๋ถ๋ช ํฉ๋๋ค.
- ์ด๊ฒ์ ๊ณ์ฐ๋ ์ํ์ ํนํ ์ค์ํฉ๋๋ค.
์ด๊ฒ์ด ์ฌ๊ธฐ์ ์๋ฏธํ๋ ๋ฐ๊ฐ ํ์คํ์ง ์์ต๋๋ค. ValueNotifier์ ValueListenableBuilder์ ๋ฌด์์ด ๋ฌธ์ ์ ๋๊น?
์์ ์ธ๊ธํ๋ฏ์ด ์ด ๋ฌธ์ ๋ ์ฅํฉํจ๋ณด๋ค ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๊ดํ ๊ฒ์ ๋๋ค.
ํ์ธ. ์ ๋ฒ๊ทธ๋ฅผ ์ ๊ณ ํ ๋ค์ ๊ตฌ์ฒด์ ์ผ๋ก ์ค๋ช ํ๋ ๋ฒ๊ทธ๋ฅผ ์ ์ถํด ์ฃผ์๊ฒ ์ต๋๊น? ์ด ๋ฒ๊ทธ๋ ๋ง ๊ทธ๋๋ก "์ํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ๋๋ฌด ์ฅํฉํ๊ณ /์ด๋ ต์ต๋๋ค"๋ผ๊ณ ํฉ๋๋ค. ์์ธํ ์ ๋ณด๊ฐ ๋ฌธ์ ๊ฐ ์๋๋ผ๋ฉด ์ด๊ฒ์ ๋ฌธ์ ๊ฐ ์๋๋๋ค.
์ ๋ ์ด ํ ๋ก ์ด ์๋นํ ๋ถํธํด์ง๊ธฐ ์์ํ์ต๋๋ค. ๋๋ ์ด๋ฏธ ์ด ์ ์ ๋ํด ๋ค์๊ณผ ๊ฐ์ด ๋๋ตํ์ต๋๋ค.
์ด ๋ฌธ์ ์ ์ฃผ์ ๋ ์ฌ์ฌ์ฉ์ฑ์ด๋ฉฐ ์์ธํ ๋ด์ฉ์ ์ฌ์ฌ์ฉ์ฑ ๋ฌธ์ ์ ๊ฒฐ๊ณผ๋ก ๋
ผ์๋ฉ๋๋ค. ์ฃผ์ ์ฃผ์ ๊ฐ ์๋๋๋ค.
์์ธํ ๋ด์ฉ์ ์ธ๊ธํ๋ ๋งจ ์ ๋๊ธ์๋ ๋จ ํ๋์ ๊ธ๋จธ๋ฆฌ ๊ธฐํธ๋ง ์์ผ๋ฉฐ, ์ด๋ ์ฃผ๋ก 2๊ฐ์ง ์์ค์ ๋ค์ฌ์ฐ๊ธฐ๋ฅผ ๋์์ผ๋ก ํ๋ StreamBuilder์ ๋๋ค.
์ปจํ ์คํธ๊ฐ ์ด [...]์ ๊ด๋ จ์ด ์๋ ์ด์ ๋ฅผ ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๊ทธ๋ฌ๋ ํ๊ธฐ ์ค์ ์คํํ ํญ๋ชฉ์ ๋ฑ๋กํ๋ ๋ฐฉ๋ฒ์ ์ํ๋ฉด ์ค๋ ์ฝ๊ฒ ํ ์ ์์ต๋๋ค.
context.onDispose
์ ๊ธฐํ์ ๋ ๋๋ ๊ทธ๊ฒ์ด ์ข์ ํด๊ฒฐ์ฑ
์ด๋ผ๊ณ ์๊ฐํ์ง ์๋๋ค๊ณ ๋ช
์์ ์ผ๋ก ์ธ๊ธํ์ต๋๋ค.
ํ ๋ก ๊ณผ ์ด๋ค ๊ด๋ จ์ด ์๋์ง ๋ฌผ์ด๋ณด์
จ๊ธฐ ๋๋ฌธ์ ์ค๋ช
ํ์ต๋๋ค.
context
๋์ StateHelper
์ธ ์ด์ ๋ ์ด๊ฒ์ด ๋ ์ ์ฐํ๊ธฐ ๋๋ฌธ์
๋๋ค(StatelessWidget ์์
๊ณผ ๊ฐ์ด)
context.myLifecycle(() {...})์ ํซ ๋ฆฌ๋ก๋๊ฐ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
์ด ์ปจํ ์คํธ์์๋ initState์์ ํธ์ถ๋ ํญ๋ชฉ์๋ง ํด๋น๋๋ฏ๋ก ์ค์ํ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค. ๋ด๊ฐ ๋ญ๊ฐ๋ฅผ ๋์น๊ณ ์์ต๋๊น?
์ฐ๋ฆฌ๋ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค:
initState() {
context.myLifecycle(() => print('hello'));
}
์์ผ๋ก:
initState() {
context.myLifecycle(() => print('world'));
}
myLifecycle
์ฝ๋ฐฑ์๋ ๋ณ๊ฒฝ ์ฌํญ์ด ์ ์ฉ๋์ง ์์ต๋๋ค.
๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ ๊ฒฝ์ฐ:
myLifecycle() {
super.myLifecycle();
print('hello');
}
๊ทธ๋ฌ๋ฉด ํซ ๋ฆฌ๋ก๋๊ฐ ์๋ํฉ๋๋ค.
์ด๊ฒ์ด ์ฌ๊ธฐ์ ์๋ฏธํ๋ ๋ฐ๊ฐ ํ์คํ์ง ์์ต๋๋ค. ValueNotifier์ ValueListenableBuilder์ ๋ฌด์์ด ๋ฌธ์ ์ ๋๊น?
์ด ๊ตฌ๋ฌธ์ Builders๋ฅผ ์ฌ์ฉํ์ง ์์๋ ๋๋๋ก ์ค๊ณ๋์์ผ๋ฏ๋ก ์๋ ๋ฌธ์ ๋ก ๋ค์ ๋์๊ฐ์ต๋๋ค.
๋ํ ValueGetter
+ queueDidUpdateWidget
์ ์ ๋์ ํจ์๋ฅผ ๊ตฌ์ฑ ๊ฐ๋ฅํ๊ฒ ๋ง๋ค๊ณ ์ถ๋ค๋ฉด ํจ์๋ ๋งค๊ฐ๋ณ์๋ก ValueNotifier
๋ฅผ ์ทจํด์ผ ํฉ๋๋ค.
AnimationController conditionalAnimator(StateHelper state, ValueListenable<bool> isAnimating, VoidCallback listener) {
...
}
์ด๋ค ์์ ฏ์ด ์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋์ง์ ๋ฐ๋ผ didUpdateWidget
์๋ ๋ค๋ฅธ ๊ณณ์์ isAnimating
๋ฅผ ์ป๊ณ ์ถ์ ์๋ ์์ต๋๋ค.
ํ ๊ณณ์์๋ didUpdateWidget์ผ ์ ์์ต๋๋ค. ๋ค๋ฅธ ๊ฒฝ์ฐ์๋ didChangeDependencies์ผ ์ ์์ต๋๋ค. ๋ ๋ค๋ฅธ ๊ณณ์์๋ stream.listen
์ฝ๋ฐฑ ๋ด๋ถ์ ์์ ์ ์์ต๋๋ค.
ํ์ง๋ง ๊ทธ๋ฐ ๋ค์ ์ด๋ฌํ ์๋๋ฆฌ์ค๋ฅผ ValueNotifier
์ฝ๊ฒ ๋ณํํ๊ณ ํจ์๊ฐ ์ด๋ฌํ ์๋ฆผ์ ์์ ํ๋๋ก ํ๋ ๋ฐฉ๋ฒ์ด ํ์ํฉ๋๋ค.
๊ทธ๋์ ์ฐ๋ฆฌ๋ ์ถ์ ํจ์ฌ ๋ ์ด๋ ต๊ฒ ๋ง๋ค๊ณ ์์ต๋๋ค.
์ด ํจํด๋ณด๋ค ConditionalAnimatorBuilder
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ํ์ค์ ์ด๊ณ ์ฝ์ต๋๋ค.
์ด์ ์ ๋ํด์๋
context
๋์StateHelper
์ด (StatelessWidget ์์ ์ฒ๋ผ) ๋ ์ ์ฐ ๋๋ฌธ์ ๋๋ค
StatelessWidget์ ์ํ ๋น์ ์ฅ ์์ ฏ์ ์ํ ๊ฒ์ ๋๋ค. ์์ ์ ๊ทธ๋ค์ด ์ํ๋ฅผ ์์ฑํ๊ณ , ๋ฌผ๊ฑด์ ํ๊ธฐํ๊ณ , didUpdateWidget ๋ฑ์ ๋ฐ์ํ์ง ์๋๋ค๋ ๊ฒ์ ๋๋ค.
ํซ ๋ฆฌ๋ก๋๋ฅผ ๋ค์ ์์ํ์ญ์์ค. ์ด๊ฒ์ด ์ฐ๋ฆฌ๊ฐ initState์ ํด๋ก์ ๋ฅผ ๋๋ ๋์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ์ด์ ์ ๋๋ค.
๊ณ์ ์ด๋ฐ ๋ง์ ํด์ ๋ฏธ์ํ๊ณ , ๋ต๋ตํ ํ ๋ฐ๋ ์ฐ๋ฆฌ๊ฐ ์ฌ๊ธฐ์ ํด๊ฒฐํ๋ ค๋ ๋ฌธ์ ๊ฐ ๋ฌด์์ธ์ง ์์ง๋ ์ดํด๊ฐ ๋์ง ์์ต๋๋ค. ์๋ ๋ฒ๊ทธ ์์ฝ๊ณผ ์๋ ์ค๋ช ์ ํฐ ๋ถ๋ถ์ ๋ฐ๋ผ ์ฅํฉํ๋ค๊ณ ์๊ฐํ์ง๋ง ๊ทธ๊ฒ ์๋๋ผ๋ ๊ฒ์ ์ดํดํฉ๋๋ค. ๊ทธ๋์ ๋ฌธ์ ๊ฐ ๋ฌด์์ ๋๊น? ์ฌ๊ธฐ์๋ ์ํธ ๋ฐฐํ์ ์ธ ์๋ง์ด ๋ง์ด ์๋ ๊ฒ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค. ์ด ๋ฒ๊ทธ์ ๋ง์ ๋๊ธ์ ํผ์ ธ ์์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ฌ๊ธฐ์ ์ฐธ์ฌํ๋ ์ด ๋ฐ๋ณต์ ์ธ ์ถค์ ์ผ์ ๋๋ด๋ ์์ฐ์ ์ธ ๋ฐฉ๋ฒ์ด ์๋๋๋ค. ๋ด๊ฐ ์ ์ ๋งํ๋ ค๊ณ ํ๋ ๊ฒ์ฒ๋ผ ์ฌ๊ธฐ์์ ๋ฌด์ธ๊ฐ๋ฅผ ์ป๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ์ฐ๋ฆฌ๊ฐ ์ดํดํ ์ ์๋ ๋ฐฉ์์ผ๋ก ์ง๋ฉดํ ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๋ ๊ฒ์ ๋๋ค. ๋ชจ๋ ์๊ตฌ ์ฌํญ์ ํ ๊ณณ์์ ์ค๋ช ๋๊ณ ์ฌ์ฉ ์ฌ๋ก์ ํจ๊ป ์ค๋ช ๋ฉ๋๋ค. ์๋ฃจ์ ์ ๋์ดํ์ง ์๋ ๊ฒ์ด ์ข์ต๋๋ค. ํนํ ๊ทํ์ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ์ง ์๋ ๊ฒ์ผ๋ก ์๊ณ ์๋ ์๋ฃจ์ ์ ๋์ดํ์ง ์๋ ๊ฒ์ด ์ข์ต๋๋ค. ํด๋น ์๋ฃจ์ ์ ๋ถ์ ์ ํ๊ฒ ๋ง๋๋ ํ์์ฑ์ด ์ค๋ช ์ ๋์ด๋์ด ์๋์ง ํ์ธํ์ญ์์ค.
์์งํ ๋งํด์ ๊ทผ๋ณธ์ ์ผ๋ก ์์ ํ ๋ค๋ฅธ ํ๋ ์์ํฌ ๋์์ธ์ ์๊ตฌํ๋ ๊ฒ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค. ๊ทธ๊ฒ์ ์๋ฒฝํ์ง๋ง Flutter๋ ์๋๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ค๋ฅธ ํ๋ ์์ํฌ๋ฅผ ๋ง๋ ๋ค๋ฉด ๊ทธ๊ฒ์ ๋ค๋ฅธ ํ๋ ์์ํฌ๊ฐ ๋ ๊ฒ์ด๊ณ , ์ฐ๋ฆฌ๋ ์ฌ์ ํ _this_ ํ๋ ์์ํฌ์์ ํด์ผ ํ ์ผ์ด ๋ง์ต๋๋ค. ์ฌ์ค, ๋น์ ์ด ์ค๋ช ํ๋ ๋ง์ ๋ถ๋ถ์ด Jetpack Compose๊ฐ ์ค๊ณ๋ ๋ฐฉ์๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ๋๋ ์ปดํ์ผ๋ฌ ๋ง๋ฒ์ด ํ์ํ๊ธฐ ๋๋ฌธ์ ๊ทธ ๋์์ธ์ ์ด๋ ฌํ ํฌ์ด ์๋๋๋ค. ๊ทธ๋์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ๋๋ฒ๊น ํ๋ ๊ฒ์ ์ ๋ง ์ด๋ ต์ง๋ง ์๋ง๋ ๋น์ ์ ๊ณจ๋ชฉ์ ๋ ๊ฐ๊น์ต๋๊น?
์ฌ๊ธฐ์๋ ์ํธ ๋ฐฐํ์ ์ธ ์๋ง์ด ๋ง์ด ์๋ ๊ฒ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค. ์ด ๋ฒ๊ทธ์ ๋ง์ ๋๊ธ์ ํผ์ ธ ์์ต๋๋ค.
๊ทธ๊ฒ๋ค์ ์ํธ ๋ฐฐํ์ ์ด์ง ์์ต๋๋ค. ํํฌ๋ ์ด ๋ชจ๋ ์์ ์ ์ํํฉ๋๋ค. ์๋ฃจ์ ์ ์ด์ ์ ๋ง์ถ๊ณ ์ถ์ง ์๊ธฐ ๋๋ฌธ์ ์ธ๋ถ ์ฌํญ์ ๋ํด ์ค๋ช ํ์ง ์๊ฒ ์ง๋ง ๋ชจ๋ ํ์ธ๋์ ์ ํํฉ๋๋ค.
๋ด๊ฐ ์ ์ ๋งํ๋ ค๊ณ ํ๋ ๊ฒ์ฒ๋ผ ์ฌ๊ธฐ์์ ๋ฌด์ธ๊ฐ๋ฅผ ์ป๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ์ฐ๋ฆฌ๊ฐ ์ดํดํ ์ ์๋ ๋ฐฉ์์ผ๋ก ์ง๋ฉดํ ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๋ ๊ฒ์ ๋๋ค. ๋ชจ๋ ์๊ตฌ ์ฌํญ์ ํ ๊ณณ์์ ์ค๋ช ๋๊ณ ์ฌ์ฉ ์ฌ๋ก์ ํจ๊ป ์ค๋ช ๋ฉ๋๋ค.
๋๋ ์์ง๋ ๊ทธ ์ต๊ณ ๋๊ธ์ด ์ด๋ป๊ฒ ๊ทธ๋ ๊ฒ ํ์ง ๋ชปํ๋์ง ์ดํดํ์ง ๋ชปํฉ๋๋ค.
๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ๋ ๋ช
ํํ์ง ์์ ๊ฒ์ด ๋์๊ฒ๋ ๋ช
ํํ์ง ์์ต๋๋ค.
์ฌ์ค, ๋น์ ์ด ์ค๋ช ํ๋ ๋ง์ ๋ถ๋ถ์ด Jetpack Compose๊ฐ ์ค๊ณ๋ ๋ฐฉ์๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ๋๋ ์ปดํ์ผ๋ฌ ๋ง๋ฒ์ด ํ์ํ๊ธฐ ๋๋ฌธ์ ๊ทธ ๋์์ธ์ ์ด๋ ฌํ ํฌ์ด ์๋๋๋ค. ๊ทธ๋์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ๋๋ฒ๊น ํ๋ ๊ฒ์ ์ ๋ง ์ด๋ ต์ง๋ง ์๋ง๋ ๋น์ ์ ๊ณจ๋ชฉ์ ๋ ๊ฐ๊น์ต๋๊น?
๋๋ ๊ทธ๊ฒ์ ์ต์ํ์ง ์์ง๋ง ๋น ๋ฅธ ๊ฒ์์ผ๋ก ๋๋ _yes_๋ผ๊ณ ๋งํ ๊ฒ์ ๋๋ค.
๊ทธ๊ฒ๋ค์ ์ํธ ๋ฐฐํ์ ์ด์ง ์์ต๋๋ค.
์์ ๋์ดํ ๋ชจ๋ ๊ธ๋จธ๋ฆฌ ๊ธฐํธ๊ฐ ์ฌ๊ธฐ์์ ํด๊ฒฐํ๋ ค๋ ๋ฌธ์ ์ ์ผ๋ถ์ ๋๊น?
ํ์ง๋ง ๊ทธ๋ค์ ๋ชจ๋ ์์๋ฅผ ํ์ธํฉ๋๋ค
์์๋ฅผ ๋์ดํ ์ ์์ต๋๊น?
๋๋ ์์ง๋ ๊ทธ ์ต๊ณ ๋๊ธ์ด ์ด๋ป๊ฒ ๊ทธ๋ ๊ฒ ํ์ง ๋ชปํ๋์ง ์ดํดํ์ง ๋ชปํฉ๋๋ค.
์๋ฅผ ๋ค์ด OP๋ ๋ฌธ์ ๊ฐ StatefulWidgets์ ๊ดํ ๊ฒ์ด๋ผ๊ณ ๋ช ์์ ์ผ๋ก ๋ฐํ์ง๋ง ์ด ๋ฌธ์ ์ ๋ํ ์ต๊ทผ ์๊ฒฌ ์ค ํ๋๋ ํน์ ์ ์์ด StatelessWidgets์์ ์๋ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ข์ง ์๋ค๊ณ ๋งํ์ต๋๋ค.
OP์์ ๋น์ ์ ๋งํฉ๋๋ค :
State
๋ก์ง์ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ ์ด๋ ต์ต๋๋ค. ๋ณต์กํ๊ณ ๊น์ด ์ค์ฒฉ๋build
๋ฉ์๋๋ก ๋๋๊ฑฐ๋ ์ฌ๋ฌ ์์ ฏ์ ๋ ผ๋ฆฌ๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ด์ผ ํฉ๋๋ค.
๋ฐ๋ผ์ ์๊ตฌ ์ฌํญ์๋ ๋ค์์ด ํฌํจ๋๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
์ฒซ ๋ฒ์งธ ์์ (์ค์ฒฉ์ ๋ํ)์ ๊ด์ฐฎ์ ๋ณด์ ๋๋ค. ๊น์ด ๋ดํฌ๋ ์ผ์ ํด์ผ ํ๋ค๊ณ ์ ์ํ๋ ค๋ ๊ฒ์ ์ ๋ ์๋๋๋ค. (์ฆ, ์ฐ๋ฆฌ๋ ๊น์ด ์ค์ฒฉ๋ ํญ๋ชฉ์ ๋ํด ๋์ํ์ง ์์ ์ ์์ต๋๋ค. ์ด๋ ์ฌ๊ธฐ์ ์ ์๋์ด ์์ง ์์ต๋๋ค. ๋์ค์ ๋ค๋ฅธ ์ฃผ์์ ๋น๋๊ฐ ๊น์ด ์ค์ฒฉ๋ ์ฝ๋๋ฅผ ์ ๋ฐํ๋ค๋ ๊ฒ์ ์์ํ์ง๋ง, ์ด์ ์ ์ธ์ฉํ ์ฝ๋์์ ๋ณผ ์ ์๋ฏ์ด ์ ๊ฒฝํ์ ๋น๋๋ ๊ฝค ์ข์ต๋๋ค.)
๋ ๋ฒ์งธ ์์ ์ ์ฐ๋ฆฌ๊ฐ ์ฅํฉํ์ง ์์์ผ ํ๋ค๋ ์๊ตฌ ์ฌํญ์ ๋๋ฐ๋ก ๋ณด์ฌ์ฃผ๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋น์ ์ ์ด๊ฒ์ด ์ฅํฉํ ๊ฒ์ ๊ดํ ๊ฒ์ด ์๋๋ผ๊ณ ์ฌ๋ฌ ๋ฒ ์ค๋ช ํ์ต๋๋ค.
OP๊ฐ ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๋ ๋ค์ ์ง์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ฌ๋ฌ
StatefulWidget
์์State
๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ ํด๋น ๋ ผ๋ฆฌ๊ฐ ์ฌ๋ฌ ์๋ช ์ฃผ๊ธฐ์ ์์กดํ๋ ํ ๋งค์ฐ ์ด๋ ต์ต๋๋ค.
์์งํ ์ด๊ฒ ๋ฌด์จ ๋ป์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๋์๊ฒ "์ด๋ ค์"์ ์ผ๋ฐ์ ์ผ๋ก ์ดํดํ๊ธฐ ์ด๋ ค์ด ๋ณต์กํ ๋ ผ๋ฆฌ๊ฐ ๋ง์ด ํฌํจ๋์ด ์์ง๋ง ์๋ช ์ฃผ๊ธฐ ์ด๋ฒคํธ๋ฅผ ํ ๋น, ์ฒ๋ฆฌ ๋ฐ ๋์ํ๋ ๊ฒ์ ๋งค์ฐ ๊ฐ๋จํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๋ฌธ์ ๋ฅผ ์ ๊ณตํ๋ ๋ค์ ๋ฌธ์ฅ(์ฌ๊ธฐ์๋ "๋ณต์กํ์ง ์์"์ผ๋ก ๋ช ์์ ์ผ๋ก ์ค๋ช ๋์ด ์์ผ๋ฏ๋ก ๋ฌธ์ ์ ๋ํ ์ค๋ช ์ด ์๋ ์ ์์)์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ฌธ์ ๋ ํด๋น ์ ๊ทผ ๋ฐฉ์์ ํ์ฅํ ๋ ์์๋ฉ๋๋ค.
์ด๊ฒ์ "๋งค์ฐ ์ด๋ ต๋ค"๋ ๊ฒ์ด "๋งค์ฐ ์ฅํฉํ๋ค"๋ฅผ ์๋ฏธํ๊ณ ์ ์ฌํ ์ฝ๋๊ฐ ๋ง์ด ๋ฐ์ํ๋ ๋ฐ์ ์ด๋ ค์์ด ์๊ธด๋ค๋ ๊ฒ์ ์์ํ์ต๋๋ค. " ์์ ๋ฅผ ํ์ฅํ ๊ฒฐ๊ณผ๋ ๋ง ๊ทธ๋๋ก ๋์ผํ ์ฝ๋๊ฐ ์ฌ๋ฌ ๋ฒ ๋ฐ์ํ๋ค๋ ๊ฒ์ ๋๋ค(์: ์ฅํฉํจ, ์์ฉ๊ตฌ ์ฝ๋).
์ด๊ฒ์ ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๋ ๋ค์ ๋ฌธ์ฅ์ ์ํด ๋์ฑ ๋ท๋ฐ์นจ๋ฉ๋๋ค.
์ด ๋ ผ๋ฆฌ๋ฅผ ๋ชจ๋ ๊ณณ์ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ผ๋ฉด "์๋"ํ์ง๋ง ์ฝ๋์ ์ฝ์ ์ด ์๊น๋๋ค.
- ๋จ๊ณ ์ค ํ๋๋ฅผ ๋ค์ ์์ฑํ๋ ๊ฒ์ ์์ด๋ฒ๋ฆฌ๊ธฐ ์ฝ์ต๋๋ค(์
dispose
ํธ์ถํ๋ ๊ฒ์ ์์)
์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ ๋ ์ฅํฉํ ํํ์ผ๋ก ์ธํด ์ค์๋ฅผ ํ๊ธฐ ์ฝ๊ธฐ ๋๋ฌธ์ ์๋ง๋ ๋งค์ฐ ์ด๋ ค์ธ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ๋ค์ ๋งํ์ง๋ง, ๋ด๊ฐ "์ฅํฉํจ"์ผ๋ก ์ค๋ช ํ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ํ์ ๋, ๋น์ ์ ๋ฌธ์ ๊ฐ ์ฅํฉํ ๊ฒ์ด ์๋๋ผ๊ณ ๋งํ์ต๋๋ค.
- ์ฝ๋์ ๋ง์ ๋ ธ์ด์ฆ๋ฅผ ์ถ๊ฐํฉ๋๋ค.
๋ค์ ์ด๊ฒ์ ๋์๊ฒ ์ฅํฉํจ/๋ณด์ผ๋ฌํ๋ ์ดํธ๋ฅผ ๋งํ๋ ๊ฒ์ฒ๋ผ ๋ค๋ฆฌ์ง๋ง, ๋ค์ ๋น์ ์ ๊ทธ๊ฒ์ด ์๋๋ผ๊ณ ์ค๋ช ํ์ต๋๋ค.
๋๋จธ์ง OP๋ ๋น์ ์ด ์ข์ํ์ง ์๋ ์๋ฃจ์ ์ ์ค๋ช ํ ๋ฟ์ด๋ฏ๋ก ๋ฌธ์ ๋ฅผ ์ค๋ช ํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ด๊ฒ์ OP๊ฐ ๋ฌธ์ ๋ฅผ ์ค๋ช ํ์ง ๋ชปํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํฉ๋๊น? ์ค์ ๋ก ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๋ OP์ ๋ชจ๋ ํญ๋ชฉ์ ์์ธํ ๋ด์ฉ์ ์ค๋ช ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง ๊ทธ๊ฒ์ด ๋ฌธ์ ๋ผ๊ณ ์ ์ํ ๋๋ง๋ค ๋น์ ์ ๊ทธ๋ ์ง ์๊ณ ๋ ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ์๋ค๊ณ ๋งํฉ๋๋ค.
๋๋ ๊ทธ ์คํด๊ฐ ๋จ์ด์ ์๋ฏธ๋ก ๊ท๊ฒฐ๋๋ค๊ณ ์๊ฐํ๋ค.
์๋ฅผ ๋ค์ด:
์ฝ๋์ ๋ง์ ๋ ธ์ด์ฆ๋ฅผ ์ถ๊ฐํฉ๋๋ค.
๋ค์ ์ด๊ฒ์ ๋์๊ฒ ์ฅํฉํจ/๋ณด์ผ๋ฌํ๋ ์ดํธ๋ฅผ ๋งํ๋ ๊ฒ์ฒ๋ผ ๋ค๋ฆฌ์ง๋ง, ๋ค์ ๋น์ ์ ๊ทธ๊ฒ์ด ์๋๋ผ๊ณ ์ค๋ช ํ์ต๋๋ค.
์ด ์์ ์ controller.dispose()
์ ์ซ์๊ฐ ์๋๋ผ ์ด๋ฌํ ์ฝ๋ ํ์ด ๋
์์๊ฒ ์ ๊ณตํ๋ ๊ฐ์น์
๋๋ค.
๊ทธ ์ ์ ํญ์ ์์ด์ผ ํ๋ฉฐ ํญ์ ๋์ผํฉ๋๋ค. ๋ฐ๋ผ์ ๋
์์ ๋ํ ๊ฐ์ ๊ฑฐ์ null์
๋๋ค.
์ค์ํ ๊ฒ์ ์ด ์ ์ ์กด์ฌ๊ฐ ์๋๋ผ ๊ทธ๊ฒ์ ๋ถ์ฌ์ด๋ค.
๋ฌธ์ ๋ ์ด๋ฌํ controller.dispose()
๊ฐ ๋ง์์๋ก dispose ๋ฉ์๋์์ ์ค์ ๋ฌธ์ ๋ฅผ ๋์น ๊ฐ๋ฅ์ฑ์ด ๋ ๋๋ค๋ ๊ฒ์
๋๋ค.
1๊ฐ์ ์ปจํธ๋กค๋ฌ์ 0๊ฐ์ Dispose๊ฐ ์์ผ๋ฉด ์ฝ๊ฒ ์ก์ ์ ์์ต๋๋ค.
100๊ฐ์ ์ปจํธ๋กค๋ฌ์ 99๊ฐ์ ์ฒ๋ถ์ด ์๋ ๊ฒฝ์ฐ ๋๋ฝ๋ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฐพ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.
๊ทธ๋ฐ ๋ค์ ์ฐ๋ฆฌ๋ ๋ค์์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ ๋ ์ฅํฉํ ํํ์ผ๋ก ์ธํด ์ค์๋ฅผ ํ๊ธฐ ์ฝ๊ธฐ ๋๋ฌธ์ ์๋ง๋ ๋งค์ฐ ์ด๋ ค์ธ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ๋ค์ ๋งํ์ง๋ง, ๋ด๊ฐ "์ฅํฉํจ"์ผ๋ก ์ค๋ช ํ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ํ์ ๋, ๋น์ ์ ๋ฌธ์ ๊ฐ ์ฅํฉํ ๊ฒ์ด ์๋๋ผ๊ณ ๋งํ์ต๋๋ค.
์ด์ ์์ ์์ ์ธ๊ธํ๋ฏ์ด ๋ชจ๋ ์ฝ๋ ํ์ด ๋์ผํ ๊ฒ์ ์๋๋๋ค.
์ฐ๋ฆฌ๊ฐ ๋น๊ตํ๋ค๋ฉด :
+ T state;
<strong i="24">@override</strong>
void initState() {
super.initState();
+ state = widget.valueNotifier.value;
+ widget.valueNotifier.addListener(_listener);
}
+ void _listener() => seState(() => state = widget.valueNotifier.value);
void dispose() {
+ widget.valueNotifier.removeListener(_listener);
super.dispose();
}
๋:
+ ValueListenableBuilder<T>(
+ valueListenable: widget.valueNotifier,
+ builder: (context, value, child) {
+ },
+ );
๊ทธ๋ฐ ๋ค์ ์ด ๋ ์กฐ๊ฐ์ ๋ชจ๋ ๊ฐ์ ์์ ์ค์ ๊ฐ์ง๋ฉฐ ๋์ผํ ์์
์ ์ํํฉ๋๋ค.
๊ทธ๋ฌ๋ ValueListenableBuilder
๊ฐ ๋ ์ข์ต๋๋ค.
๊ทธ ์ด์ ๋ ์ค์ํ ๊ฒ์ ์ค์ ์๊ฐ ์๋๋ผ ์ด ์ค์ด ๋ฌด์์ธ์ง์ ๋๋ค.
์ฒซ ๋ฒ์งธ ์ค๋ํซ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ ๋ฒ์งธ ์ค๋ํซ์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค.
์ด๋ ValueListenableBuilder๋ฅผ _๊ฐ๋จํ๊ฒ_ ๋ง๋ญ๋๋ค.
์ด ํ์๋ ๋ค์๊ณผ ๊ฐ์ ๋ด์ฉ์ด ์์ต๋๋ค.
ValueListenableBuilder๋ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋๋ valueListenable
์ฒ๋ฆฌํฉ๋๋ค.
widget.valueNotifier
๊ฐ ์๊ฐ์ด ์ง๋๋ ๋ณํ์ง ์๋ ์๋๋ฆฌ์ค์์๋ ์ฐ๋ฆฌ๊ฐ ๋งํ๋ ๊ฒ์ฒ๋ผ ์ํ์ง ์์ต๋๋ค.
์ธ์ ๊ฐ๋ ๊ทธ ๋ง์ด ๋ฐ๋ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ValueListenableBuilder๋ ์ ๋์์ ์ ์์ ์ผ๋ก ์ฒ๋ฆฌํ์ง๋ง ์ฒซ ๋ฒ์งธ ์ค๋ํซ์๋ ์ด์ ๋ฒ๊ทธ๊ฐ ์์ต๋๋ค.
๋ฐ๋ผ์ ValueListenableBuilder๋ ๋ ๊ฐ๋จํ ๋ฟ๋ง ์๋๋ผ ์ ํํ ๊ฐ์ ์์ ๋ผ์ธ์ ๋ํด ์ฝ๋ ๋ณ๊ฒฝ์ ๋ ํ๋ ฅ์ ์ ๋๋ค.
์ด๋ฅผ ํตํด ValueListenableBuilder๊ฐ ๋ ๋ซ๋ค๋ ๋ฐ ๋ ๋ค ๋์ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ทธ๋ฐ ๋ค์ ์ง๋ฌธ์ "๋ชจ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ํ ๋
ผ๋ฆฌ์ ๋ํด ValueListenableBuilder์ ํด๋นํ๋ ๊ฒ์ด ์๋ ์ด์ ๋ ๋ฌด์์
๋๊น?"์
๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์ ๋์ :
final controller = TextEditingController(text: 'hello world');
...
controller.dispose();
์ฐ๋ฆฌ๋ํด์ผ:
TextEditingControllerBuilder(
initialText: 'hello world',
builder: (context, controller) {
},
);
initialText
๋ณ๊ฒฝํ๋ฉด ํซ ๋ฆฌ๋ก๋๊ฐ ๊ฐ๋ฅํ๋ค๋ ์ถ๊ฐ ์ด์ ์ด ์์ต๋๋ค.
์ด ์์ ๋ ์ฝ๊ฐ ์ฌ์ํ ์ ์์ง๋ง ์ฝ๊ฐ ๋ ๊ณ ๊ธ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ํ ๋
ผ๋ฆฌ(์: ModeratorBuilder
)์ ์ด ์์น์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด๊ฒ์ ์์ ์กฐ๊ฐ์์ "์ ์"์ ๋๋ค. ๊ทธ๋ฌ๋ ์ ๊ทผ ๋ฐฉ์์ ํ์ฅํ๋ ค๊ณ ํ ๋ ๋ช ๊ฐ์ง ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
์๋ฅผ ๋ค์ด, ์ด๋ค ์ฌ๋๋ค์ด ๋ค์๊ณผ ๊ฐ์ด ๋ชจ๋ธ์ ๊ด๋ฆฌํ๋ ๊ฒ์ ๋ณด์์ต๋๋ค.
class User {
final ValueNotifier<String> name;
final ValueNotifier<int> age;
final ValueNotifier<Gender> gender;
}
๊ทธ๋ฌ๋ ์์ ฏ์ name
, age
๋ฐ gender
๋ชจ๋๋ฅผ ํ ๋ฒ์ ๋ชจ๋ ์์ ํ๋ ค๊ณ ํ ์ ์์ต๋๋ค.
์ฆ, ๋ค์์ ์ํํด์ผ ํฉ๋๋ค.
return ValueListenableBuilder<String>(
valueListenable: user.name,
builder: (context, userName, _) {
return ValueListenableBuilder<int>(
valueListenable: user.age,
builder: (context, userAge, _) {
return ValueListenableBuilder<Gender>(
valueListenable: user.gender,
builder: (context, userGender, _) {
return Text('$userGender. $userName ($userAge)');
},
);
},
);
},
);
์ด๊ฒ์ ๋ถ๋ช
ํ ์ด์์ ์ด์ง ์์ต๋๋ค. build
๋ฉ์๋๋ฅผ ์ค์ผ์ํค๊ธฐ ์ํด initState
/ dispose
๋ด๋ถ์ ์ค์ผ์ ์ ๊ฑฐํ์ต๋๋ค.
(์์๋ฅผ ์ํด Listenable.merge
๋ ๋ฌด์ํฉ์๋ค. ์ฌ๊ธฐ์๋ ์ค์ํ์ง ์์ต๋๋ค. ๊ตฌ์ฑ์ ๊ดํ ๊ฒ์
๋๋ค.)
Builders๋ฅผ ๊ด๋ฒ์ํ๊ฒ ์ฌ์ฉํ๋ค๋ฉด ์ด ์ ํํ ์๋๋ฆฌ์ค์์ ์ฐ๋ฆฌ ์์ ์ ์ฝ๊ฒ ๋ณผ ์ ์์ต๋๋ค. Listenable.merge
ํด๋นํ๋ ๊ฒ์ ์์ต๋๋ค.
์ฌ์ฉ์ ์ ์ ๋น๋๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ง๋ฃจํฉ๋๋ค.
๋น๋๋ฅผ ๋ง๋๋ ์ฌ์ด ์๋ฃจ์
์ ์์ต๋๋ค. ๋ฆฌํฉํ ๋ง ๋๊ตฌ๋ ์ฌ๊ธฐ์์ ์ฐ๋ฆฌ๋ฅผ ๋์ธ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ "๋น๋๋ก ์ถ์ถ"ํ ์ ์์ต๋๋ค.
๋ํ, ๋ฐ๋์ ์ง๊ด์ ์ผ ํ์๋ ์์ต๋๋ค. ์ฌ์ฉ์ ์ ์ ๋น๋๋ฅผ ๋ง๋๋ ๊ฒ์ ์ฌ๋๋ค์ด ๊ฐ์ฅ ๋จผ์ ์๊ฐํ ์ผ์ด ์๋๋๋ค. ํนํ ๋ง์ ์ฌ๋๋ค์ด ์์ฉ๊ตฌ์ ๋ฐ๋ํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์(์ ๋ ์๋๋๋ค).
์ฌ๋๋ค์ ๋ง์ถคํ ์ํ ๊ด๋ฆฌ ์๋ฃจ์ ์ ๋ง๋ค๊ณ ์ ์ฌ์ ์ผ๋ก ์๋ชป๋ ์ฝ๋๋ก ๋๋ ๊ฐ๋ฅ์ฑ์ด ๋ ํฝ๋๋ค.
Builders์ ํธ๋ฆฌ๋ฅผ ์กฐ์ํ๋ ๊ฒ์ ์ง๋ฃจํฉ๋๋ค.
์ด์ ์์์ ValueListenableBuilder
๋ฅผ ์ ๊ฑฐํ๊ฑฐ๋ ์ ๊ฒ์ ์ถ๊ฐํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ์ด๋ ์ฝ์ง ์์ต๋๋ค.
์ฐ๋ฆฌ ์ฝ๋๊ฐ ์ปดํ์ผ๋์ง ์๋ ์ด์ ๋ฅผ ์ดํดํ๊ธฐ ์ํด ๋ช ๋ถ ๋์ () ๋ฐ {}๋ฅผ ์ธ๋ ๋ฐ ์๊ฐ์ ํ ์ ํ ์ ์์ต๋๋ค.
ํํฌ๋ ๋ฐฉ๊ธ ์ธ๊ธํ ๋น๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค.
์ด์ ์์ ๋ฅผ ํํฌ๋ก ๋ฆฌํฉํ ๋งํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ฉ๋๋ค.
final userName = useValueListenable(user.name);
final useAge = useValueListenable(user.age);
final useGender = useValueListenable(user.gender);
return Text('$userGender. $userName ($userAge)');
์ด์ ๋์ ๊ณผ ๋์ผ ํ์ง๋ง ์ด์ ์ฝ๋์ ์ ํ ๋ค์ฌ์ฐ๊ธฐ๊ฐ ์์ต๋๋ค.
์ด๋ ๋ค์์ ์๋ฏธํฉ๋๋ค.
provider
์ด(๊ฐ) ์ข์ํ๋ ์ฃผ์ ์ค ํ๋์
๋๋ค. MultiProvider
๋ฅผ ๋์
ํ์ฌ ๋ง์ ์ค์ฒฉ์ ์ ๊ฑฐํ์ต๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก initState
/ dispose
์ ๊ทผ ๋ฐฉ์๊ณผ ๋ฌ๋ฆฌ ํซ ๋ฆฌ๋ก๋์ ์ด์ ์ด ์์ต๋๋ค.
์๋ก์ด useValueListenable
๋ฅผ ์ถ๊ฐํ๋ฉด ๋ณ๊ฒฝ ์ฌํญ์ด ์ฆ์ ์ ์ฉ๋ฉ๋๋ค.
๋ฌผ๋ก ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ํ๋ฆฌ๋ฏธํฐ๋ธ๋ฅผ ์ถ์ถํ๋ ๊ธฐ๋ฅ์ ์ฌ์ ํ โโ์์ต๋๋ค.
String useUserLabel(User user) {
final userName = useValueListenable(user.name);
final useAge = useValueListenable(user.age);
final useGender = useValueListenable(user.gender);
return '$userGender. $userName ($userAge)';
}
Widget build(context) {
final label = useUserLabel(user);
return Text(label);
}
์ด๋ฌํ ๋ณ๊ฒฝ์ ๋๋ถ๋ถ์ ์๋๋ฆฌ์ค์์ ์๋ํ๋ extract as function
๋ก ์๋ํํ ์ ์์ต๋๋ค.
๊ทธ๊ฒ์ด ๋น์ ์ ์ง๋ฌธ์ ๋๋ตํฉ๋๊น?
ํ์ ํ๋. ํ์ง๋ง ์ด์ ๊ฐ์ ๋ฌธ์ ์ ๋ฌธ์ ๋ ์ค์ ๋ก ์ฌ๋ฐ๋ฅธ ์ผ์ ํ๊ธฐ์ ์ถฉ๋ถํ ์ ๋ณด๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด:
Widget build(context) {
if (random.nextBool())
final title = useLabel(title);
final label = useLabel(name);
return Text(label);
}
...์ ๋ง ํผ๋์ค๋ฌ์ด ๋ฐฉ์์ผ๋ก ๋ฒ๊ทธ๊ฐ ๋ฐ์ํฉ๋๋ค.
์ปดํ์ผ๋ฌ ๋ง๋ฒ(Compose๊ฐ ์ํํ๋ ๋ฐฉ์)์ผ๋ก ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ง๋ง Flutter์ ๊ฒฝ์ฐ ๊ธฐ๋ณธ ์ค๊ณ ๊ฒฐ์ ์ค ์ผ๋ถ๋ฅผ ์๋ฐํฉ๋๋ค. ํค๋ก ํด๊ฒฐํ ์ ์์ง๋ง ์ฑ๋ฅ์ด ํฌ๊ฒ ์ ํ๋ฉ๋๋ค(๋ณ์ ์กฐํ๊ฐ ๋งต ์กฐํ, ํด์ ๋ฑ์ ํฌํจํ๊ธฐ ๋๋ฌธ์). ์ด๋ Flutter์ ๊ธฐ๋ณธ ์ค๊ณ ๋ชฉํ ์ค ์ผ๋ถ๋ฅผ ์๋ฐํฉ๋๋ค.
์์ ์ ์ํ Property ์๋ฃจ์ ๋๋ ๊ทธ์์ ํ์๋ ์๋ฃจ์ ์ ๋ชจ๋ ์ฝ๋๋ฅผ ํ ๊ณณ์์ ์ ์งํ๋ ๊ฒ์ ๋ํด ์ค๋ช ํ ๋ชฉํ๋ฅผ ๊ณ์ ๋ฌ์ฑํ๋ฉด์ ์ปดํ์ผ๋ฌ์ ๋ง๋ฒ์ ํผํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ ๋๋ค. ๋๋ ์ด๊ฒ์ด ์ ์๋ํ์ง ์๋์ง ์ ๋ง๋ก ์ดํดํ์ง ๋ชปํฉ๋๋ค. (๋ถ๋ช ํ ๊ทธ๊ฒ์ ์์ ํ ์๋ฃจ์ ์ด ๋๋๋ก didChangeDependencies ๋ฑ์ ์ฐ๊ฒฐํ๋๋ก ํ์ฅ๋ ๊ฒ์ ๋๋ค.) (์ฐ๋ฆฌ๋ ์ด๊ฒ์ด ์ฐ๋ฆฌ์ ์ฑ๋ฅ ์๊ตฌ ์ฌํญ์ ์๋ฐํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๊ธฐ๋ณธ ํ๋ ์์ํฌ์ ๋ฃ์ง ์์ ๊ฒ์ ๋๋ค.)
๋ฐ๋ก ๋น์ ์ด ๋งํ๋ฏ์ด ๋ฐ์ํ ์ ์๋ ๋ฒ๊ทธ๋ก ์ธํด ํํฌ๊ฐ ์กฐ๊ฑด๋ถ๋ก ํธ์ถ๋์ง ์์์ผ ํ๋ ์ด์ ์
๋๋ค. ์์ธํ ๋ด์ฉ์ ReactJS์ Rules of Hooks ๋ฌธ์๋ฅผ ์ฐธ์กฐํ์ธ์. ๊ธฐ๋ณธ ์์ ์ ๊ตฌํ ์ ํธ์ถ ์์๋ก ์ถ์ ๋๊ธฐ ๋๋ฌธ์ ์กฐ๊ฑด๋ถ๋ก ์ฌ์ฉํ๋ฉด ํธ์ถ ์์๊ฐ ๊นจ์ ธ ์ฌ๋ฐ๋ฅด๊ฒ ์ถ์ ํ ์ ์๋ค๋ ๊ฒ์
๋๋ค. ํํฌ๋ฅผ ์ ๋๋ก ์ฌ์ฉํ๋ ค๋ฉด ์กฐ๊ฑด ๋
ผ๋ฆฌ ์์ด build
์ ์ต์์ ์์ค์์ ํธ์ถํฉ๋๋ค. JS ๋ฒ์ ์์๋ ๋ค์
const [title, setTitle] = useLabel("title");
Dart๋ ๋น์ทํ ์ ์์ง๋ง JS์ฒ๋ผ ์์ถ์ ํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ ๊ธธ ์ ์์ต๋๋ค.
var titleHook = useLabel("title");
String title = titleHook.property;
Function setTitle = titleHook.setter;
์กฐ๊ฑด๋ถ ๋
ผ๋ฆฌ๋ฅผ ์ํ๋ฉด _์ต์์ ์์ค์์ ํธ์ถํ ํ ๋น๋ ๋ฉ์๋์์ title
๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ ์ ์์ต๋๋ค. ์ด์ ํธ์ถ ์์๊ฐ ์ฌ์ ํ ์ ์ง๋๊ธฐ ๋๋ฌธ์
๋๋ค. ๊ทํ๊ฐ ์ ๊ธฐํ ์ด๋ฌํ ๋ฌธ์ ์ค ๋ง์ ๋ถ๋ถ์ด ์์ ๋งํฌ๋ ํํฌ ๋ฌธ์์ ์ค๋ช
๋์ด ์์ต๋๋ค.
ํ์ ํ๋. ๊ทธ๋ฆฌ๊ณ ๋น์ ์ ํจํค์ง์์ ๊ทธ๊ฒ์ ํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ์ข ๋ฅ์ ์๊ตฌ ์ฌํญ์ ์ฐ๋ฆฌ์ ๋์์ธ ์ฒ ํ์ ์๋ฐํ ๊ฒ์ด๋ฏ๋ก Flutter ํ๋ ์์ํฌ์ ์ถ๊ฐํ์ง ์์ ๊ฒ์ ๋๋ค. (ํนํ, ์ฐ๋ฆฌ๋ ๊ฐ๋ ์ฑ๊ณผ ๋๋ฒ๊น ๊ฐ๋ฅ์ฑ์ ์ํด ์ต์ ํํฉ๋๋ค. ์๋ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง ์กฐ๊ฑด๋ถ(์ฝ๋์์ ๋ช ํํ์ง ์์ ์ ์์) ๋๋ฌธ์ ๋๋๋ก ์๋ํ์ง ์๋ ์ฝ๋๋ฅผ ๊ฐ๋ ๊ฒ์ ๊ถ์ฅํ๊ฑฐ๋ ํ์ฑํํ๋ ค๋ ๊ฒ์ด ์๋๋๋ค. ํต์ฌ ํ๋ ์์ํฌ.)
๋๋ฒ๊น /์กฐ๊ฑด๋ถ ๋์์ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค. ๊ทธ๋์ ๋ถ์๊ธฐ ํ๋ฌ๊ทธ์ธ์ด ์ค์ํฉ๋๋ค. ์ด๋ฌํ ํ๋ฌ๊ทธ์ธ์ ๋ค์์ ์ํํฉ๋๋ค.
useMyFunction
๋ผ๋ ์ด๋ฆ ์์ด ํํฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๊ฒฝ๊ณ ์ด๊ฒ์ ๋ชจ๋ ์ ์ฌ์ ์ธ ์ค์๋ฅผ ๋ค๋ฃน๋๋ค. React๋ ์ด๊ฒ์ด ๊ฐ๋ฅํ ์ผ์์ ์ฆ๋ช ํ์ต๋๋ค.
๊ทธ๋ฌ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ด์ ์ด ์์ต๋๋ค.
๊ณ์ฐ๋ ์ํ์ ๋ํด ํํฌ๋ ๊ฐ์ฒด์ ์ธ์คํด์ค๋ฅผ ์บ์ํ๋ ๋ฐ ๋งค์ฐ ๊ฐ๋ ฅํฉ๋๋ค. ๋งค๊ฐ๋ณ์๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ์์ ฏ์ ๋ค์ ๋น๋ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด ํ ์ ์์ต๋๋ค.
class Example extends HookWidget {
final int userId;
Widget build(context) {
// Calls fetchUser whenever userId changes
// It is the equivalent to both initState and didUpdateWidget
final future = useMemo1(() => fetchUser(userId), userId);
final snapshot = useFuture(future);
if (!snapshot.hasData)
return Text('loading');
return Text(snapshot.data.name);
}
}
์ด๋ฌํ useMemo
ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ์ ์ฝ๊ฒ ์ต์ ํํ๊ณ init + update๋ฅผ ์ ์ธ์ ์ผ๋ก ์ฒ๋ฆฌํ์ฌ ๋ฒ๊ทธ๋ ํผํ ์ ์์ต๋๋ค.
์ด๊ฒ์ Property
/ context.onDispose
์ ์์์ ๋์น๋ ๊ฒ์
๋๋ค.
๋ก์ง์ ๋ผ์ดํ ์ฌ์ดํด์ ๋ฐ์ ํ๊ฒ ์ฐ๊ฒฐํ๊ฑฐ๋ ValueNotifier
์ฝ๋๋ฅผ ๋ณต์กํ๊ฒ ํ์ง ์์ผ๋ฉด ์ ์ธ์ ์ํ์ ์ฌ์ฉํ๊ธฐ ์ด๋ ต์ต๋๋ค.
ValueGetter
์ ์์ด ์ค์ฉ์ ์ด์ง ์์ ์ด์ ์ ๋ํด ์์ธํ ์์๋ณด๊ธฐ:
์ฐ๋ฆฌ๋ ๋ฆฌํฉํ ๋ง์ ์ํ ์ ์์ต๋๋ค:
final int userId;
Widget build(context) {
final future = useMemo1(() => fetchUser(userId), userId);
์์ผ๋ก:
Widget build(context) {
final userId = Model.of(context).userId;
final future = useMemo1(() => fetchUser(userId), userId);
ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด useMemo
๊ฐ ์๋ช
์ฃผ๊ธฐ์ ์ฐ๊ฒฐ๋์ง ์์ผ๋ฏ๋ก ์ด ๋ณ๊ฒฝ์ด ์๋ฒฝํ๊ฒ ์๋ํฉ๋๋ค.
๊ทธ๋ฌ๋ Property
+ ValueGetter
Property
๋ฅผ ์ฌ์ฉํ๋ฉด ์ด ์์
์ ์ํํ๋ ค๋ฉด Property
์ฝ๋๊ฐ ๋ค์๊ณผ ๊ฐ์ ์ ์์ผ๋ฏ๋ก ๋ฐ๋์งํ์ง ์์ต๋๋ค. ์ฌ๋ฌ ๊ณณ์์ ์ฌ์ฌ์ฉ๋ฉ๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ๋ค์ ํ๋ฒ ์ฌ์ฌ์ฉ์ฑ์ ์์์ต๋๋ค.
FWIW ์ด ์ค๋ํซ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
class Example extends StatefulWidget {
final int userId;
<strong i="45">@override</strong>
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
Future<User> future;
<strong i="46">@override</strong>
void initState() {
super.initState();
future = fetchUser(widget.userId);
}
<strong i="47">@override</strong>
void didUpdateWidget(Example oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.userId != widget.userId) {
future = fetchUser(widget.userId);
}
}
<strong i="48">@override</strong>
Widget build(BuildContext context) {
return FutureBuilder<User>(
future: future,
builder: (context, snapshot) {
if (!snapshot.hasData)
return Text('loading');
return Text(snapshot.data.name);
},
);
}
}
@rrousselGit์ด ์ธ๊ธํ ๊ฒ๊ณผ ๋์ผํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง๋ง ๊ฐ๋ ์ฑ๊ณผ ๋๋ฒ๊น ๊ฐ๋ฅ์ฑ๋ ์ผ๋์ ๋ ์๋ฃจ์ ์ ์ฐพ์์ผ ํ๋ค๊ณ ๊ฐ์ ํฉ๋๋ค. Vue์๋ ์กฐ๊ฑด๋ถ ๋๋ ํธ์ถ ์์๊ฐ React์ ๊ฐ์ ๋ฒ๊ทธ๋ฅผ ์ผ์ผํค์ง ์๋ ๊ณณ์์ ์ฐพ๊ณ ์๋ ๊ฒ๊ณผ ๋ ์ผ์นํ ์ ์๋ ์์ฒด ๊ตฌํ์ด ์์ต๋๋ค.
์๋ง๋ ๋ค์ ๋จ๊ณ๋ Vue๊ฐ Vue์ ์ ์ฝ ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ฒ์ ์ ๋ง๋ ๊ฒ์ฒ๋ผ Flutter์ ์ ์ฝ ์กฐ๊ฑด์ด ์ฃผ์ด์ง๋ฉด ์ด ํ๋ ์์ํฌ์ ํํฌ ๋ฒ์ ์ธ Flutter ๊ณ ์ ์ ์๋ฃจ์ ์ ๋ง๋๋ ๊ฒ์ ๋๋ค. ๋๋ React์ ํํฌ๋ฅผ ์ ๊ธฐ์ ์ผ๋ก ์ฌ์ฉํ๋ฉฐ ๋๋๋ก ๋ถ์๊ธฐ ํ๋ฌ๊ทธ์ธ์ ๊ฐ๋ ๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ ์ ์์ต๋๋ค. ์๋ง๋ ์ธ์ด์ ๋ ํตํฉ๋์ด์ผ ํ ๊ฒ์ ๋๋ค.
์ด์จ๋ , ๋๋ ์ฐ๋ฆฌ๊ฐ ํฉ์์ ๋๋ฌํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ์ฝ์ ์ ์๋ ๊ฒ์๋ ๋์ํ์ง ์๋ ๊ฒ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค.
๋ค์ ๋ง์๋๋ฆฌ์ง๋ง ์ปค๋ฎค๋ํฐ์ ์ด ๋ฌธ์ ์ ๊ด๋ จ๋ ๋ฌธ์ ๊ฐ ์๋ค๋ ๊ฒ์ ์๊ณ ์๊ธฐ ๋๋ฌธ์ ๊ณต์ ํฉ๋๋ค. ์ ๋ ๊ฐ์ธ์ ์ผ๋ก Flutter๊ฐ ์ด๊ฒ์ ๋ํด ์๋ฌด ๊ฒ๋ ํ์ง ์์๋ ์๊ด์์ต๋๋ค.
๋ด๊ฐ ๊ฐ๋ ฅํ๊ฒ ๊ถ์ฅํ๋ ํํฌ ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ๊ณ ์ถ์ง๋ง ๋ช ๊ฐ์ง ๋ฌธ์ ๊ฐ ์๋ ๊ฒฝ์ฐ ํด๋น ๋ฌธ์ ์ ๋ํ ๋ฌธ์ ๋ฅผ ์ ์ถํ๊ณ ํด๋น ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด PR์ ์ ์ถํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ฐ๋ฆฌ๋ ๋น์ ๊ณผ ํจ๊ป ์ผํ๊ฒ ๋ ๊ฒ์ ๊ธฐ์๊ฒ ์๊ฐํฉ๋๋ค.
์ฌ๊ธฐ์ ์ด์ Property
์์ด๋์ด์ ์ ๋ฒ์ ์ด ์์ต๋๋ค. ๊ทธ๊ฒ์ didUpdateWidget ๋ฐ ํ๊ธฐ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค(๊ทธ๋ฆฌ๊ณ didChangeDependencies์ ๊ฐ์ ๋ค๋ฅธ ๊ฒ๋ค์ ์ฝ๊ฒ ์ฒ๋ฆฌํ๋๋ก ๋ง๋ค ์ ์์ต๋๋ค). ํซ ๋ฆฌ๋ก๋๋ฅผ ์ง์ํฉ๋๋ค(์์ฑ ๋ฐ ํซ ๋ฆฌ๋ก๋๋ฅผ ๋ฑ๋กํ๋ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ์ ์์ผ๋ฉฐ ์ฌ๋ฐ๋ฅธ ์์
์ ์ํํฉ๋๋ค). ๋ช
์์ ์ ํ์ด ํ์ํ์ง ์๊ณ ์ ํ์ด ์์ ํฉ๋๋ค(์ถ๋ก ์ ์์กด). ์์ฑ ์ ์ธ๊ณผ ์ฌ์ฉ๋ฒ์ ์ ์ธํ๊ณ ๋ชจ๋ ๊ฒ์ด ํ ๊ณณ์ ์์ผ๋ฉฐ ์ฑ๋ฅ์ ํฉ๋ฆฌ์ ์ผ๋ก ์ข์์ผ ํฉ๋๋ค(๋ ์์ธํ ์์
๋ฐฉ์๋งํผ ์ข์ง๋ ์์ง๋ง).
์์ฑ/์์ฑ ๊ด๋ฆฌ์:
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
typedef InitStateCallback<T> = T Function(T oldValue);
typedef DidUpdateWidgetCallback<T, W extends StatefulWidget> = T Function(W oldWidget);
class Property<T, W extends StatefulWidget> {
Property({
T value,
this.initState,
this.didUpdateWidget,
this.dispose,
}) : _value = value;
T get value {
assert(_value != null);
return _value;
}
T _value;
final InitStateCallback<T> initState;
void _initState(Property<T, W> oldProperty) {
if (initState != null)
_value = initState(oldProperty?.value);
assert(_value != null);
}
final DidUpdateWidgetCallback<T, W> didUpdateWidget;
void _didUpdateWidget(StatefulWidget oldWidget) {
if (didUpdateWidget != null) {
final T newValue = didUpdateWidget(oldWidget);
if (newValue != null)
_value = newValue;
}
}
final ValueSetter<T> dispose;
void _dispose() {
if (dispose != null)
dispose(value);
}
}
mixin PropertyManager<W extends StatefulWidget> on State<W> {
final Set<Property<Object, W>> _properties = <Property<Object, W>>{};
bool _ready = false;
Property<T, W> register<T>(Property<T, W> oldProperty, Property<T, W> property) {
assert(_ready);
if (oldProperty != null) {
assert(_properties.contains(oldProperty));
_properties.remove(oldProperty);
}
assert(property._value == null);
property._initState(oldProperty);
_properties.add(property);
return property;
}
<strong i="9">@override</strong>
void initState() {
super.initState();
_ready = true;
initProperties();
}
<strong i="10">@override</strong>
void reassemble() {
super.reassemble();
initProperties();
}
<strong i="11">@protected</strong>
<strong i="12">@mustCallSuper</strong>
void initProperties() { }
<strong i="13">@override</strong>
void didUpdateWidget(W oldWidget) {
super.didUpdateWidget(oldWidget);
for (Property<Object, W> property in _properties)
property._didUpdateWidget(oldWidget);
}
<strong i="14">@override</strong>
void dispose() {
_ready = false;
for (Property<Object, W> property in _properties)
property._dispose();
super.dispose();
}
}
์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'properties.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
<strong i="18">@override</strong>
Widget build(BuildContext context) {
return MaterialApp(
home: Example(userId: 1),
);
}
}
class User {
User(this.name);
final String name;
}
Future<User> fetchUser(int userId) async {
await Future.delayed(const Duration(seconds: 2));
return User('user$userId');
}
class Example extends StatefulWidget {
Example({ Key key, this.userId }): super(key: key);
final int userId;
<strong i="19">@override</strong>
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> with PropertyManager {
Property future;
<strong i="20">@override</strong>
void initProperties() {
super.initProperties();
future = register(future, Property(
initState: (_) => fetchUser(widget.userId),
didUpdateWidget: (oldWidget) {
if (oldWidget.userId != widget.userId)
return fetchUser(widget.userId);
}
));
}
<strong i="21">@override</strong>
Widget build(BuildContext context) {
return FutureBuilder<User>(
future: future.value,
builder: (context, snapshot) {
if (!snapshot.hasData) return Text('loading');
return Text(snapshot.data.name);
},
);
}
}
ํธ์๋ฅผ ์ํด AnimationController ๋ฑ๊ณผ ๊ฐ์ ๊ฒ์ ๋ํด ์ค๋น๋ Property ํ์ ํด๋์ค๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
State.build ๋ฉ์๋์์๋ ์๋ํ๋ ๋ฒ์ ์ ๋ง๋ค ์ ์์ต๋๋ค...
@Hixie ๊ฐ ํ
์ด๋ธ์ ๊ฐ์ ธ์ค๋ ๋ช ๊ฐ์ง ์์ฌ์ ๊ณต์ ํฉ๋๋ค. ๋ค๋ฅธ ํํธ์ผ๋ก๋ Hooks๊ฐ ๊ฐ์ง๊ณ ์๋ ๋ถ๋ช
ํ ์ฅ์ ์ ๋ณด์๊ณ ๊ฝค ๋ง์ ๊ฐ๋ฐ์๋ค์ด ๊ทธ๊ฒ์ ์ข์ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
@timsneath๊ฐ ์ ์ํ ํจํค์ง ์ ๊ทผ ๋ฐฉ์์ ๋ํ ๋ด ๋ฌธ์ ๋ Hooks๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋๊ฐ Hooks๊ฐ ์๋ ์ฝ๋์ ํฌ๊ฒ ๋ค๋ฅด๊ฒ ๋ณด์ธ๋ค๋ ๊ฒ์
๋๋ค. ๊ทธ๋ค์ด ๊ณต์ ์นด๋
ผ์ ํฌํจ๋์ง ์๋๋ค๋ฉด ์ฐ๋ฆฌ๋ Flutter ์นด๋
ผ์ ๋ฐ๋ฅด๋ ์ฌ๋๋ค์ด ์ฝ์ ์ ์๋ Flutter ์ฝ๋๋ก ๋๋ ๊ฒ์
๋๋ค.
ํจํค์ง๊ฐ ํ๋ ์์ํฌ์ ์๋ต ๊ฐ๋ฅ์ฑ์ด ๋์ด์ผ ํ๋ ๊ฒ์ ๊ตฌํํ๊ธฐ ์์ํ๋ฉด ์๋ก์ด ์ฝ๋ ๊ธฐ๋ฐ์ ๋ฐฐ์ฐ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋๋ ๋ค์ํ Flutter ๋ฐฉ์ธ์ ์ป๊ฒ ๋ฉ๋๋ค. ๊ทธ๋์ ์ ๋ ์๋ง๋ Flutter์ ์ผ๋ถ๊ฐ ๋๋ ์๊ฐ ํํฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์์ํ ๊ฒ์
๋๋ค.
๊ทธ๊ฒ์ ๋๊ฒฐ๋ ํจํค์ง์ ๋ํ ๋์ ํ์ฌ ๊ฒฌํด์ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ๋๋ ๊ทธ ๊ธฐ๋ฅ์ ์ข์ํ์ง๋ง Union๊ณผ ๋ฐ์ดํฐ ํด๋์ค๊ฐ Dart์ ์ผ๋ถ๊ฐ ์๋ ํ ์ฌ๋๋ค์ด ๋ด ์ฝ๋๋ฅผ ์ฝ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ค๊ธฐ ๋๋ฌธ์ ๋ด ์ฝ๋ ๊ธฐ๋ฐ์ ํฌํจํ๊ณ ์ถ์ง ์์ต๋๋ค.
@escamoteur ๊ทธ๋ฅ ์ดํดํ๋๋ฐ, ์์ ฏ์ด ์๋ํ๋ ๋ฐฉ์์ ๊ทผ๋ณธ์ ์ผ๋ก
์ ์๋ ๋ณ๊ฒฝ ์์ฒด์ ๋ํ ๋ํ์ ์ง๊ตํ์ง๋ง @escamoteur , @rrousselGit ๋ฐ ์ฌ๊ธฐ์ ๋ค๋ฅธ ๊ณณ์์ ๋ค์ ๊ฒ์ ํ๋ ์์ํฌ์ ์๋ ๊ฒ์ด ํน์ ๋ณ๊ฒฝ์ ํฉ๋ฒ์ฑ์ ํ๋ฆฝํ๋ ์ค์ํ ๋ฐฉ๋ฒ์ผ๋ก ์ธ์๋๋ค๋ ๊ฒ์ ๋๋ค. ์ ๊ทผํ๋ค. ๋์ํ์ง ์์ผ๋ฉด ์ ๋ฅผ ์์ ํ์ญ์์ค.
๋๋ ๊ทธ ์๊ฐ์ ์ดํดํฉ๋๋ค. ํ๋ ์์ํฌ์์ ๋ง์ ๊ฒ์ด ๋์ค๊ธฐ ๋๋ฌธ์(์: DartPad๋ ์ค๋๋ ํ์ฌ ํจํค์ง๋ฅผ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ผ๋ถ ๊ณ ๊ฐ์ NPM์ผ๋ก ๊ตฌ์ด ํ ์์กดํ๋ ํจํค์ง ์์ ๋ํด ๊ฑฑ์ ํฉ๋๋ค. ๋ '๊ณต์์ '์ธ ๋๋์ด ๋ค๋ฉฐ null-safety์ ๊ฐ์ ๋ณ๊ฒฝ์ผ๋ก ์์ผ๋ก ๋์๊ฐ ๊ฒ์ด ๋ณด์ฅ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ ํฌํจํ๋ ๋ฐ์๋ ์๋นํ ๋น์ฉ์ด ์์๋ฉ๋๋ค. ํนํ ์ ๊ทผ ๋ฐฉ์๊ณผ API๋ฅผ ๊ณจํ์ํต๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ ๋ ๋ค ์ฐ๋ฆฌ๊ฐ ์ถ๊ฐํ๋ ๊ฒ์ ๋ํด ๋งค์ฐ ๋์ ๊ธฐ์ค์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ํนํ ๋ง์ฅ์ผ์น๋ก ๋์ํ์ง ์์ ๊ฒฝ์ฐ(๊ตญ๊ฐ ๊ด๋ฆฌ ์ฐธ์กฐ), ์งํ์ ๊ฐ๋ฅ์ฑ์ด ์๋ ๊ฒฝ์ฐ ๋๋ ํจํค์ง์ฒ๋ผ ์ฝ๊ฒ ๋ฌด์ธ๊ฐ๋ฅผ ์ถ๊ฐํ ์ ์๋ ๊ฒฝ์ฐ์ ๊ทธ๋ ์ต๋๋ค.
ํจํค์ง ์ฐ์ ์ฒ ํ์ ๋ฌธ์ํํด์ผ ํ๋์ง ๊ถ๊ธํฉ๋๋ค. ํ์ง๋ง ๋ค์ _์ด๋์_๊ฐ๋ ๊ฒ์ ์ํ ๋ ผ๋ฆฌ ์ฌ์ฌ์ฉ์ ๊ฐ์ ํ๊ธฐ ์ํด ๋ณ๊ฒฝํ ์ ์๋ _๋ฌด์_์ ๋ํ ๋ ผ์์ ๋ณ๊ฐ์ ๋๋ค.
ํจํค์ง ์ ์ฑ ์ https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#deciding -where-to-put-code์ ๋ฌธ์ํ๋์ด ์์ต๋๋ค.
๋๋ ํจํค์ง ์ฐ์ ์ ๊ทผ ๋ฐฉ์์ ์ถฉ๋ถํ ์ดํดํ๊ณ ๊ทธ๊ฒ์ด ์ค์ํ ์ผ์ด๋ผ๋ ๋ฐ ๋์ํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ผ๋ถ ๋ฌธ์ ๋ ํจํค์ง๊ฐ ์๋๋ผ ํต์ฌ์์ ํด๊ฒฐํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
์ด๊ฒ์ด ๋ด๊ฐ provider
๋ฅผ Flutter์ ๋ณํฉํด์ผ ํ๋ค๊ณ ์ฃผ์ฅํ๋ ๊ฒ์ด ์๋๋ผ ์ด ๋ฌธ์ ๊ฐ Flutter๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ํด๊ฒฐํด์ผ ํ๋ ๋ฌธ์ ๋ฅผ ์ค๋ช
ํ๋ค๊ณ ๋ฏฟ๋ ์ด์ ์
๋๋ค(๋ฌผ๋ก ํํฌ๊ฐ ์์ด์ผ ํ๋ ๊ฒ์ ์๋).
Provider์ ํจ๊ป Flutter๋ ์ด๋ฌํ ์ข
๋ฅ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๊ธฐ๋ณธ ์ ๊ณต๋๋ ๊ธฐ๋ณธ ์ ๊ณต๋๋ InheritedWidgets๋ฅผ ์ ๊ณตํฉ๋๋ค.
๊ณต๊ธ์๋ ์๋จ์ ์๊ฒฌ์ด ์๋ ๋ ์ด์ด๋ง ์ถ๊ฐํ์ฌ ""๋ ๋ฉ์ง๊ฒ"" ๋ง๋ญ๋๋ค.
ํํฌ๊ฐ ๋ค๋ฆ
๋๋ค. ๊ทธ๋ค์ ์์์ ์
๋๋ค. ํน์ ๋ฌธ์ ์ ๋ํ ์๊ฒฌ์ด ์๋ ์ ์์ค ์๋ฃจ์
์
๋๋ค. ์ฌ๋ฌ ์ํ์์ ๋
ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํฉ๋๋ค.
๊ทธ๊ฒ๋ค์ ์ต์ข
์ ํ์ด ์๋์ง๋ง ์ฌ๋๋ค์ด ์ฌ์ฉ์ ์ ์ ํจํค์ง๋ฅผ ๋น๋ํ๋ ๋ฐ ์ฌ์ฉํ ๊ฒ์ผ๋ก ์์๋๋ ๊ฒ์
๋๋ค(์: ๋ด๊ฐ hooks_riverpod์์ ํ๋
์์์ ๋ด๊ฐ ๋์ํ ์์ฑ ์ ๊ทผ ๋ฐฉ์์ด ํํฌ์ ์ด๋ป๊ฒ ๋น๊ต๋๋์ง์ ๋ํ ์์ธํ ๊ฒํ ๋ฅผ ๋๊ตฐ๊ฐ๊ฐ ์ ๊ณตํ ์ ์๋ค๋ฉด (์ฌ๊ธฐ์์ ์ํ๋ ๋ฐ๋ฅผ ์ดํดํ๊ณ ํํฌ๊ฐ ์ถฉ์กฑํ๋ ์๊ตฌ ์ฌํญ ๋ฑ์ ์ดํดํ๋ ์ธก๋ฉด์์) ๋์์ด ๋ ๊ฒ์ ๋๋ค. (Property ์์ด๋์ด์ ๋ํ ๋์ ๋ชฉํ๋ ์ฌ๋ฌ ์ํ์์ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํ๋ ์์ํฌ ์์ ์๊ฒฌ์ ์๋ ๊ฒ์ ๋๋ค.)
์์ฑ ์ ์์ด ์ด ๋ฌธ์ ์ ํต์ฌ ๋ชฉํ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์คํจํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ํ ๋ ผ๋ฆฌ๋ ๋งค๊ฐ๋ณ์๊ฐ ์ด๋์์ ์ค๊ณ ์ด๋ค ์ํฉ์์ ์ ๋ฐ์ดํธ๋๋์ง ์ ๊ฒฝ์ฐ์ง ์์์ผ ํฉ๋๋ค.
์ด ์ ์์ ๋ชจ๋ ๋ ผ๋ฆฌ๋ฅผ ํ ๊ณณ์์ ์ฌ๊ทธ๋ฃนํํ์ฌ ์ด๋ ์ ๋ ๊ฐ๋ ์ฑ์ ๋์ ๋๋ค. ๊ทธ๋ฌ๋ ์ฌ์ฌ์ฉ์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์คํจํฉ๋๋ค.
๋ณด๋ค ๊ตฌ์ฒด์ ์ผ๋ก ๋ค์์ ์ถ์ถํ ์ ์์ต๋๋ค.
Property(
initState: (_) => fetchUser(widget.userId),
didUpdateWidget: (oldWidget) {
if (oldWidget.userId != widget.userId)
return fetchUser(widget.userId);
}
)
_ExampleState
์์ ๋
ผ๋ฆฌ๊ฐ Example
๋ฐ initState
+ didUpdateWidget
๋ฐ์ธ๋ฉ๋๋ฏ๋ก ๋ค๋ฅธ ์์ ฏ์์ ์ฌ์ฌ์ฉํฉ๋๋ค.
ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
Rust ์ปค๋ฎค๋ํฐ์์ ๋น์ทํ ๊ฒ์ ๋ณธ ํ @timsneath์ ๋์ํฉ๋๋ค. ์ผ๋จ ์ฝ์ด์์ ๋ฌด์ธ๊ฐ๋ฅผ ์ถ์ถํ๋ ๊ฒ์ ๋งค์ฐ ์ด๋ ต์ต๋๋ค. BLoC ํจํด์ provider๊ฐ ๋์ค๊ธฐ ์ ์ ์ง์ ๋์์ง๋ง ์ง๊ธ์ provider๊ฐ ๊ถ์ฅ ๋ฒ์ ์ ๋๋ค. ์๋ง๋ flutter_hooks๋ ๊ฐ์ ๋ฐฉ์์ผ๋ก "์ถ๋ณต๋ฐ์" ๋ฒ์ ์ด ๋ ์ ์์ต๋๋ค. ๋ฏธ๋์ ์ฌ๋๋ค์ด ์๊ฐํด ๋ธ ํํฌ์ ๋ํ ๊ฐ์ ์ฌํญ์ด ์์ ์ ์๊ธฐ ๋๋ฌธ์ ์ด ๋ง์ ํ๋ ๊ฒ์ ๋๋ค. ์ด์ ํํฌ๊ฐ ์๋ React๋ ์ค์ ๋ก ํํฌ๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋ ๋น ์ ธ ๋์ฌ ์ ์์ต๋๋ค. ๊ทธ๊ฒ๋ค์ ํต์ฌ์ ์๊ธฐ ๋๋ฌธ์ ๋ณธ์ง์ ์ผ๋ก ์์ํ ํด๋์ค ๊ตฌ์ฑ ์์์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ด๋ฅผ ์ง์ํด์ผ ํฉ๋๋ค. ๋ฐ๋ผ์ ๋๋ ํจํค์ง ์ฒ ํ์ ๋์ํฉ๋๋ค.
๋ฌธ์ ๋ ์ฑํ๋ฅ ์ด ๋ฎ๊ณ ์ฌ๋๋ค์ด ์์ ์๊ฒ ๋ง๋ ๊ฒ์ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. ์ฌ๋๋ค์๊ฒ flutter_hooks๋ฅผ ์ฌ์ฉํ๋๋ก ๊ถ์ฅํ๋ฉด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค. ์ด๊ฒ์ ๋ง์ ์ฌ๋๋ค์ด ๊ณต๊ธ์๋ฅผ ์ฌ์ฉํ๋๋ผ๋ ์ํ ๊ด๋ฆฌ ์๋ฃจ์ ์ด ์ผ๋ง๋ ๋ง์์ง ์ ์ฌํ๊ฒ ์ดํด๋ณด๋ฉด ํฐ ๋ฌธ์ ๊ฐ ์๋ ์๋ ์์ต๋๋ค. ๋๋ ๋ํ ๊ตฌ์ฑ ๊ฐ๋ฅํ๊ณ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ผ์ดํ ์ฌ์ดํด ๋ก์ง์ ๋ํ ์ฐ์ํ ์๋ฃจ์ ์ ๋ง๋ค๊ธฐ ์ํด ํด๊ฒฐํด์ผ ํ๋ ๋ค๋ฅธ ํ๋ ์์ํฌ์์ ๋ช ๊ฐ์ง ๋ฌธ์ ์ "๋ฌธ์ ์ "์ ๊ฒฝํํ์ต๋๋ค.
ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
React/flutter_hooks์์ ์ ๊ณตํ๋ ๊ธฐ๋ณธ ํํฌ๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
class FetchUser extends Hook<AsyncSnapshot<User>> {
const FetchUser(this.userId);
final int userId;
<strong i="8">@override</strong>
_FetchUserState createState() => _FetchUserState();
}
class _FetchUserState extends HookState<AsyncSnapshot<User>, FetchUser> {
Future<User> userFuture;
<strong i="9">@override</strong>
void initHook() {
userFuture = fetchUser(hook.userId);
}
void didUpdateHook(FetchUser oldHook) {
if (oldHook.userId != hook.userId)
userFuture = fetchUser(hook.userId);
}
<strong i="10">@override</strong>
User build() {
return useFuture(userFuture);
}
}
๊ทธ๋ฐ ๋ค์ ์ฌ์ฉ:
class Example extends HookWidget {
const Example({Key key, this.userId}) : super(key: key);
final int userId;
<strong i="14">@override</strong>
Widget build(BuildContext context) {
AsyncSnapshot<User> user = use(FetchUser(userId));
if (!user.hasData)
return CircularProgressIndicator();
return Text(user.data.name);
}
}
์ด ์ํฉ์์ ๋
ผ๋ฆฌ๋ Example
๋ฐ StatefulWidget
์ ์๋ช
์ฃผ๊ธฐ์ ์์ ํ ๋
๋ฆฝ์ ์
๋๋ค.
๋ฐ๋ผ์ userId
๋ค๋ฅด๊ฒ ๊ด๋ฆฌํ๋ ๋ค๋ฅธ ์์ ฏ์์ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด์ฉ๋ฉด ๋ค๋ฅธ ์์ ฏ์ด ๋ ๊ฒ์ด๋ผ๋ StatefulWidget
์ ๊ด๋ฆฌํ๋ userId
๋ด๋ถ์ ์ผ๋ก. ๋์ InheritedWidget์์ userId
๋ฅผ ์ป์ ์๋ ์์ต๋๋ค.
์ด ๊ตฌ๋ฌธ์ ํํฌ๊ฐ ์์ฒด ์๋ช
์ฃผ๊ธฐ๋ฅผ ๊ฐ์ง ๋
๋ฆฝ์ ์ธ State
๊ฐ์ฒด์ ๊ฐ๋ค๋ ๊ฒ์ ๋ถ๋ช
ํ ํด์ผ ํฉ๋๋ค.
์ฐธ๊ณ ๋ก ํจํค์ง ์ฐ์ ์ ๊ทผ ๋ฐฉ์์ ํ ๊ฐ์ง ๋จ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ํจํค์ง ์์ฑ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํํฌ์ ์์กดํ๋ ํจํค์ง๋ฅผ ๊ฒ์ํ ๊ฐ๋ฅ์ฑ์ด ์ ์ต๋๋ค.
์๋ฅผ ๋ค์ด, Provider ์ฌ์ฉ์๊ฐ ์ง๋ฉดํ ํ ๊ฐ์ง ์ผ๋ฐ์ ์ธ ๋ฌธ์ ๋ ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ ๋ ํด๋น ์ํ๋ฅผ ์๋์ผ๋ก ํ๊ธฐํ๋ ค๋ ๊ฒ์
๋๋ค.
๋ฌธ์ ๋ Provider ์ฌ์ฉ์๊ฐ ์ฅํฉํ Consumer(builder: ...)
/ Selector(builder:...)
๊ตฌ๋ฌธ๊ณผ ๋ฌ๋ฆฌ context.watch
/ context.select
๊ตฌ๋ฌธ๋ ์๋นํ ์ข์ํ๋ค๋ ๊ฒ์
๋๋ค.
๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ์ด ๋ฉ์ง ๊ตฌ๋ฌธ์ _๊ทธ๋ฆฌ๊ณ _ ํํฌ ์์ด ์ด์ ์ ์ธ๊ธํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค(๋๋ ๊ฑฐ๋ถ๋ https://github.com/flutter/flutter/pull/33213).
๋ฌธ์ ๋:
๊ณต๊ธ์๋ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด flutter_hooks
์ ์์กดํ ์ ์์ต๋๋ค.
Provider์ ์ธ๊ธฐ ๋๋ฌธ์ ํํฌ์ ์์กดํ๋ ๊ฒ์ ๋นํฉ๋ฆฌ์ ์
๋๋ค.
๊ทธ๋์ ๊ฒฐ๊ตญ ๋ค์์ ์ ํํ์ต๋๋ค.
context.watch
๋ฅผ ์ฆ๊ธฐ๋ ์ฌ๋๋ค์ด ์ํ๋ ๊ตฌ๋ฌธ์ ์ ๊ณตํ๊ธฐ ์ํด ํํฌ์ ๋ํ ์ข
์์ฑ์ ์ถ๊ฐํ์ญ์์ค.๋๋ ๊ทธ๊ฒ์ด Provider์ ๋นํด ์๋นํ ๊ฐ์ ์ ๊ฐ์ ธ์จ๋ค๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ ๋ด๊ฐ ์๊ฐํด๋ธ ๊ฒ์ ์๋นํ ๋ง์กฑํฉ๋๋ค(๊ทธ๊ฒ์ InheritedWidgets๋ฅผ ์ปดํ์ผ ์์ ํ๊ฒ ๋ง๋ญ๋๋ค).
๊ทธ๋ฌ๋ ๊ฑฐ๊ธฐ์ ๊ฐ๋ ๊ธธ์ ๋์๊ฒ ๋์ ๋ท๋ง์ ๋จ๊ฒผ์ต๋๋ค.
ํํฌ ๋ฒ์ ๊ณผ ์์ฑ ๋ฒ์ ์ฌ์ด์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ธ ๊ฐ์ง ์ฐจ์ด์ ์ด ์์ต๋๋ค.
์์ฉ๊ตฌ ์ฝ๋๊ฐ ์ค์ ๋ก ๊ทธ๋ ๊ฒ ํฐ ๋ฌธ์ ์ ๋๊น? ๋ด ๋ง์, ์ด์ ์์ฑ์ ์ฝ๊ฒ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฝ๋๊ฐ ๋ชจ๋ ํ ๊ณณ์ ์์ต๋๋ค. ๊ทธ๋์ ์ง๊ธ์ ์ ๋ง _์ ์ผํ_ ์ฅํฉํ ์ฃผ์ฅ์ ๋๋ค.
๋๋ ์ข์ ์๋ฃจ์ ์ด ๊ทธ๊ฒ์ ๋ํด ์๊ณ ์๋ ๋ค๋ฅธ ํจํค์ง์ ์์กดํด์๋ ์ ๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ํ๋ ์์ํฌ์ ์๋์ง ์ฌ๋ถ๋ ์ค์ํ์ง ์์ต๋๋ค. ๊ทธ๊ฒ์ ์ฌ์ฉํ์ง ์๋ ์ฌ๋๋ค์ ๋ฌธ์ ๊ฐ๋์ด์๋ ์๋ฉ๋๋ค. ์ฌ๋๋ค์ด ๊ทธ๊ฒ์ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ๋ฌธ์ ๋ผ๋ฉด IMHO๋ API์ ๋ํ ์ํ ์ ํธ์ ๋๋ค.
๋ด ๋ง์, ์ด์ ์์ฑ์ ์ฝ๊ฒ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฝ๋๊ฐ ๋ชจ๋ ํ ๊ณณ์ ์์ต๋๋ค.
์ฝ๋๊ฐ ํ ๊ณณ์ ์๋ค๊ณ ํด์ ์ฌ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ์๋๋๋ค.
ํ์ฌ _ExampleState
๋ด๋ถ์ ์๋ ์ฝ๋๋ฅผ ๋ค๋ฅธ ์์ ฏ์์ ์ฌ์ฌ์ฉํ๋ ๋ณด์กฐ ์์ ฏ์ ๋ง๋ค์ด ์ฃผ์๊ฒ ์ต๋๊น?
๋นํ๊ธฐ: ์ ์์ ฏ์ ๋ค์๊ณผ ๊ฐ์ด State ๋ด๋ถ์์ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉ์ ID๋ฅผ ๊ด๋ฆฌํด์ผ ํฉ๋๋ค.
class _WhateverState extends State with PropertyManager {
// may change over time after some setState calls
int userId;
}
์ฌ๋๋ค์ด ๊ทธ๊ฒ์ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด ๋ฌธ์ ๋ผ๋ฉด IMHO๋ API์ ๋ํ ์ํ ์ ํธ์ ๋๋ค.
๊ณต์์ด ์๋๊ธฐ ๋๋ฌธ์ ์ฌ๋๋ค์ด ์ฌ์ฉํ์ง ์๋๋ค๊ณ ํด์ API๊ฐ ๋์๋ค๋ ๊ฒ์ ์๋๋๋ค.
(๋ฒ์ ๊ด๋ฆฌ, ๋ผ์ด์ ์ค, ๊ฐ๊ฐ์๊ฐ ๋ฐ ๊ธฐํ ์ฌํญ์ผ๋ก ์ธํด) ์ ์ง ๊ด๋ฆฌํด์ผ ํ๋ ์ถ๊ฐ ์์
์ด๊ธฐ ๋๋ฌธ์ ์ถ๊ฐ ์ข
์์ฑ์ ์ถ๊ฐํ์ง ์๋ ๊ฒ์ ์์ ํ ํฉ๋ฒ์ ์
๋๋ค.
๋ด๊ฐ ๊ธฐ์ตํ๋ ๋ฐ์ ๋ฐ๋ฅด๋ฉด Flutter์๋ ๊ฐ๋ฅํ ํ ์ ์ ์ข
์์ฑ์ด ์์ด์ผ ํ๋ค๋ ์๊ตฌ ์ฌํญ์ด ์์ต๋๋ค.
ํ์ฌ ๋๋ฆฌ ๋ฐ์๋ค์ฌ์ง๊ณ ๊ฑฐ์ ๊ณต์ํ๋ Provider ์์ฒด๋ฅผ ์ฌ์ฉํ๋๋ผ๋ "๋๋ ์ข ์์ฑ์ ์ถ๊ฐํ๋ ๊ฒ์ ํผํ๊ธฐ ์ํด ๋ด์ฅ๋ InheritedWidgets๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ ํธํฉ๋๋ค"๋ผ๊ณ ๋งํ๋ ์ฌ๋๋ค์ ๋ณด์์ต๋๋ค.
ํ์ฌ
_ExampleState
๋ด๋ถ์ ์๋ ์ฝ๋๋ฅผ ๋ค๋ฅธ ์์ ฏ์์ ์ฌ์ฌ์ฉํ๋ ๋ณด์กฐ ์์ ฏ์ ๋ง๋ค์ด ์ฃผ์๊ฒ ์ต๋๊น?
๋ฌธ์ ์ ์ฝ๋๋ ์์ ฏ์์ userId๋ฅผ ๊ฐ์ ธ์ fetchUser ๋ฉ์๋์ ์ ๋ฌํ๋ ๊ฒ์ ๊ดํ ๊ฒ์ ๋๋ค. ๋์ผํ ๊ฐ์ฒด์์ ๋ก์ปฌ๋ก ๋ณ๊ฒฝ๋๋ userId๋ฅผ ๊ด๋ฆฌํ๋ ์ฝ๋๋ ๋ค๋ฅผ ์ ์์ต๋๋ค. ๊ด์ฐฎ์ ๊ฒ ๊ฐ์ฃ ? ์ฌ๊ธฐ์ ํด๊ฒฐํ๋ ค๋ ๋ฌธ์ ๊ฐ ๋ฌด์์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๊ธฐ๋ก์ ์ํด ์์ฑ์ ์ฌ์ฉํ์ฌ ์ค๋ช ํ๋ ์์ ์ ์ํํ์ง ์์ ๊ฒ์ ๋๋ค.
class Example extends StatefulWidget {
Example({ Key key }): super(key: key);
<strong i="10">@override</strong>
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> with PropertyManager {
int _userId;
Future<User> _future;
void _setUserId(int newId) {
if (newId == _userId)
return;
setState(() {
_future = fetchUser(_userId);
});
}
// ...code that uses _setUserId...
<strong i="11">@override</strong>
Widget build(BuildContext context) {
return FutureBuilder<User>(
future: _future.value,
builder: (context, snapshot) {
if (!snapshot.hasData) return Text('loading');
return Text(snapshot.data.name);
},
);
}
}
๊ณต์์ด ์๋๊ธฐ ๋๋ฌธ์ ์ฌ๋๋ค์ด ์ฌ์ฉํ์ง ์๋๋ค๊ณ ํด์ API๊ฐ ๋์๋ค๋ ๊ฒ์ ์๋๋๋ค.
๋์.
์ฌ๋๋ค์ด ๋์ ๊ฒ์ ์ฌ์ฉํ์ง ์๋๋ค๋ ์ฌ์ค์ API๊ฐ ๋์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. "ํจํค์ง ์์ฑ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํํฌ์ ์์กดํ๋ ํจํค์ง๋ฅผ ๊ฒ์ํ ๊ฐ๋ฅ์ฑ์ด ์ ์ต๋๋ค."๋ผ๊ณ ๋งํ๋ฉด ํํฌ๊ฐ ์ฌ์ฉ์์๊ฒ ์ ์ฉํ๊ธฐ ์ํด ํํฌ๋ฅผ ์ฌ์ฉํ๋ ๋ค๋ฅธ ์ฌ๋์ ์์กดํ๋ค๋ ๊ฒ์ ๋ํ๋
๋๋ค. ์ข์ API์ธ IMHO๋ ๋ค๋ฅธ ์ฌ๋์ด ์ฑํํ๋๋ผ๋ ๋์์ง ์์ต๋๋ค. ๋ค๋ฅธ ์ฌ๋์ด ์์ง ๋ชปํ๋ ๊ฒฝ์ฐ์๋ ์ ์ง๋์ด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์์ Property
์์ ๋ ๊ทธ๊ฒ์ ์ฌ์ฉํ๋ ๋ค๋ฅธ ํจํค์ง์ ์์กดํ์ง ์๊ณ ๊ทธ ์์ฒด๋ก ์ ์ฉํฉ๋๋ค.
ํ์ฌ ๋๋ฆฌ ๋ฐ์๋ค์ฌ์ง๊ณ ๊ฑฐ์ ๊ณต์ํ๋ Provider ์์ฒด๋ฅผ ์ฌ์ฉํ๋๋ผ๋ "๋๋ ์ข ์์ฑ์ ์ถ๊ฐํ๋ ๊ฒ์ ํผํ๊ธฐ ์ํด ๋ด์ฅ๋ InheritedWidgets๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ ํธํฉ๋๋ค"๋ผ๊ณ ๋งํ๋ ์ฌ๋๋ค์ ๋ณด์์ต๋๋ค.
InheritedWidget์ ์ฌ์ฉํ๋ ๊ฒ์ ์ ํธํ๋ ์ฌ๋๋ค์ ๋ฌธ์ ๋ ๋ฌด์์ ๋๊น? ๋๋ ์ฌ๋๋ค์๊ฒ ํด๊ฒฐ์ฑ ์ ๊ฐ์ํ๊ณ ์ถ์ง ์์ต๋๋ค. ๊ทธ๋ค์ ๊ทธ๋ค์ด ์ฌ์ฉํ๊ณ ์ถ์ ๊ฒ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๋น์ ์ ๋ง ๊ทธ๋๋ก ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ ์ค๋ช ํ๊ณ ์์ต๋๋ค. InheritedWidget ์ฌ์ฉ์ ์ ํธํ๋ ์ฌ๋๋ค์ ๋ํ ํด๊ฒฐ์ฑ ์ ๋ฐฉํด๊ฐ ๋์ง ์๊ณ InheritedWidget์ ์ฌ์ฉํ๋๋ก ํ๋ ๊ฒ์ ๋๋ค.
. ์ข์ API์ธ IMHO๋ ๋ค๋ฅธ ์ฌ๋์ด ์ฑํํ๋๋ผ๋ ๋์์ง ์์ต๋๋ค. ๋ค๋ฅธ ์ฌ๋์ด ์์ง ๋ชปํ๋ ๊ฒฝ์ฐ์๋ ์ ์ง๋์ด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์์ Property ์์ ๋ ์์ฒด์ ์ผ๋ก ์ ์ฉํ๊ฒ ์ฌ์ฉํ๋ ๋ค๋ฅธ ํจํค์ง์ ์์กดํ์ง ์์ต๋๋ค.
์คํด๊ฐ ์์ต๋๋ค.
๋ฌธ์ ๋ ์ผ๋ฐ์ ์ผ๋ก ํํฌ๋ฅผ ์ฌ์ฉํ์ง ์๋ ์ฌ๋๋ค์ ๊ดํ ๊ฒ์ด ์๋๋๋ค.
ํํฌ๋ ๊ณต์์ ์ด์ง ์์ง๋ง Provider๋ ๊ณต์์ด๊ธฐ ๋๋ฌธ์ Provider๊ฐ ํํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค๋ ๊ฒ์
๋๋ค.
๋์ผํ ๊ฐ์ฒด์์ ๋ก์ปฌ๋ก ๋ณ๊ฒฝ๋๋ userId๋ฅผ ๊ด๋ฆฌํ๋ ์ฝ๋๋ ๋ค๋ฅผ ์ ์์ต๋๋ค. ๊ด์ฐฎ์ ๊ฒ ๊ฐ์ฃ ? ์ฌ๊ธฐ์ ํด๊ฒฐํ๋ ค๋ ๋ฌธ์ ๊ฐ ๋ฌด์์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๊ธฐ๋ก์ ์ํด ์์ฑ์ ์ฌ์ฉํ์ฌ ์ค๋ช ํ๋ ์์ ์ ์ํํ์ง ์์ ๊ฒ์ ๋๋ค.
์ด๊ฒ์ ์ง๋ฌธ์ ๋๋ตํ์ง ์์ต๋๋ค. ํํฌ์ ์์ฑ ๊ฐ์ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๋น๊ตํ๊ธฐ ์ํด ํน๋ณํ ์์ฒญํ์ต๋๋ค.
ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด FetchUser
์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
class _WhateverState extends State with PropertyManager {
// may change over time after some setState calls
int userId;
Widget build(context) {
final user = use(FetchUser(userId));
}
}
ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด
FetchUser
์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด๊ฒ ์ ๋ฐ๋์งํ์ง ์ดํด๊ฐ ์๋ฉ๋๋ค. FetchUser
์๋ ํฅ๋ฏธ๋ก์ด ์ฝ๋๊ฐ ์์ผ๋ฉฐ Hooks์์ fetchUser
ํจ์๋ก์ ์ด๋ํฐ์ผ ๋ฟ์
๋๋ค. fetchUser
์ง์ ํธ์ถํ์ง ์๋ ์ด์ ๋ ๋ฌด์์
๋๊น? ์ฌ์ฌ์ฉ ์ค์ธ ์ฝ๋๋ ํฅ๋ฏธ๋ก์ด ์ฝ๋๊ฐ ์๋๋๋ค.
ํํฌ๋ ๊ณต์์ ์ด์ง ์์ง๋ง Provider๋ ๊ณต์์ด๊ธฐ ๋๋ฌธ์ Provider๊ฐ ํํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค.
์ฝ๋ ์ฌ์ฌ์ฉ ๋ฌธ์ ์ ๋ํ IMHO์ ์ข์ ์๋ฃจ์ ์ ๊ณต๊ธ์๊ฐ ์ ํ ์ฑํํ ํ์๊ฐ ์์ต๋๋ค. ๊ทธ๊ฒ๋ค์ ์์ ํ ์ง๊ตํ๋ ๊ฐ๋ ์ผ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ Flutter ์คํ์ผ ๊ฐ์ด๋๊ฐ "์๋ฃ๋ฅผ ํผํ์ญ์์ค"๋ผ๋ ์ ๋ชฉ์ผ๋ก ์ค๋ช ํ๋ ๊ฒ์ ๋๋ค.
์ด๊ฒ ์ ๋ฐ๋์งํ์ง ์ดํด๊ฐ ์๋ฉ๋๋ค. FetchUser์๋ ํฅ๋ฏธ๋ก์ด ์ฝ๋๊ฐ ์์ผ๋ฉฐ Hooks์์ fetchUser ํจ์๋ก ์ฐ๊ฒฐ๋๋ ์ด๋ํฐ์ผ ๋ฟ์ ๋๋ค. fetchUser๋ฅผ ์ง์ ํธ์ถํ์ง ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? ์ฌ์ฌ์ฉ ์ค์ธ ์ฝ๋๋ ํฅ๋ฏธ๋ก์ด ์ฝ๋๊ฐ ์๋๋๋ค.
๊ทธ๊ฒ์ ์ค์ํ์ง ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๋ณด์ฌ์ฃผ๋ ค๊ณ ํฉ๋๋ค. fetchUser
๋ ๋ฌด์์ด๋ ๋ ์ ์์ต๋๋ค(์ ChangeNotifier.addListener
.
fetchUser
์ ์์กดํ์ง ์๋ ๋์ฒด ๊ตฌํ์ ๊ฐ์ง ์ ์์ผ๋ฉฐ ๋จ์ํ ์์์ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์ํํ๋ API๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค.
int userId;
Widget build(context) {
AsyncSnapshot<User> user = use(ImplicitFetcher<User>(userId, fetch: () => fetchUser(userId));
}
์ฝ๋ ์ฌ์ฌ์ฉ ๋ฌธ์ ์ ๋ํ IMHO์ ์ข์ ์๋ฃจ์ ์ ๊ณต๊ธ์๊ฐ ์ ํ ์ฑํํ ํ์๊ฐ ์์ต๋๋ค. ๊ทธ๊ฒ๋ค์ ์์ ํ ์ง๊ตํ๋ ๊ฐ๋ ์ผ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ Flutter ์คํ์ผ ๊ฐ์ด๋๊ฐ "์๋ฃ๋ฅผ ํผํ์ญ์์ค"๋ผ๋ ์ ๋ชฉ์ผ๋ก ์ค๋ช ํ๋ ๊ฒ์ ๋๋ค.
์ด๊ฒ์ด ๋ด๊ฐ ํํฌ๊ฐ ์์์ ์ด๋ผ๊ณ ์ธ๊ธํ ์ด์ ์ ๋๋ค.
์์ ๋ก:
package:animations
๋ Animation
์ ๋ฐ๋ผ ๋ค๋ฆ
๋๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ด ํต์ฌ ํ๋ฆฌ๋ฏธํฐ๋ธ์ด๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
package:animations
๊ฐ ์ปค๋ฎค๋ํฐ์์ ์ ์ง ๊ด๋ฆฌํ๋ Animation
์ ํฌํฌ๋ฅผ ๋์ ์ฌ์ฉํ๋ค๋ฉด ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ ๊ฒ์
๋๋ค.
@escamoteur ๊ทธ๋ฅ ์ดํดํ๋๋ฐ, ์์ ฏ์ด ์๋ํ๋ ๋ฐฉ์์ ๊ทผ๋ณธ์ ์ผ๋ก
@Hixie ์ ์์ ์ ํํฌ๊ฐ ๋ ์ ๋ช
๋๋ ๋น์ ์ ์ฐ๋ ค๋ฅผ ๋งค์ฐ ๋ง์ด ๊ณต์ ํ์ง๋ง ๋ค๋ฅธ ํํธ์ผ๋ก๋ ํํฌ๊ฐ ์๋ ์์ ฏ์ด ์ ๋ง ์ฐ์ํด ๋ณด์
๋๋ค.
์ด์ ๊ณผ ๊ฐ์ ์ผ์ ํ๋ ๊ฒ์ ๊ธ์งํ์ง ์์ต๋๋ค.
์ด์ ๊ณผ ๊ฐ์ ์ผ์ ํ๋ ๊ฒ์ ๊ธ์งํ์ง ์์ต๋๋ค.
๋๋ ๊ทธ๋ ๊ฒ ํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. Flutter ํ์ด "์ด์ ์ฐ๋ฆฌ๋ flutter hooks๋ฅผ ๊ถ์ฅํ์ง๋ง ์ฌ์ ํ ์ด์ ์ฒ๋ผ ํ ์ ์์ต๋๋ค"๋ผ๊ณ ๋งํ๋ ๊ฒ์ ์ข์ ์๊ฐ์ด ์๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ฌ๋๋ค์ด ์ด๊ฒ์ ๋ํด ํผ๋์ค๋ฌ์ํ ๊ฒ์ ๋๋ค. ๋ํ Flutter ํ์ด ํฅํ ํํฌ๋ฅผ ๊ถ์ฅํ๋ค๋ฉด ์ค์ Flutter ์ฝ๋๋ฅผ ์์ ๋ก ๊ฒ์ํ๋ ๊ฒ์ ์ค๋จํด์ผ ํฉ๋๋ค.
์ฌ๋๋ค์ ํญ์ "๊ณต์์ ์ธ ๋ฐฉ๋ฒ"์ ๋ฐ๋ฅด๊ณ Flutter๋ฅผ ์ฌ์ฉํ๋ ๋ ๊ฐ์ง ๊ณต์์ ์ธ ๋ฐฉ๋ฒ์ด ์์ด์๋ ์ ๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ทธ๊ฒ์ ์ค์ํ์ง ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๋ณด์ฌ์ฃผ๋ ค๊ณ ํฉ๋๋ค.
fetchUser
๋ ๋ฌด์์ด๋ ๋ ์ ์์ต๋๋ค(์ChangeNotifier.addListener
.
ํ์ ํ๋. ์ด๊ฒ์ด ๋ฐ๋ก ํจ์๊ฐ ์ข์ ์ด์ ์ ๋๋ค. ์ฝ๋๋ฅผ ์ถ์ํํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ์ด๋ฏธ ๊ธฐ๋ฅ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์์ ์์ฑ ์ฝ๋์ ์์ _setUserId ์ฝ๋๋ ํ๋ ์์ํฌ์ ํน๋ณํ ๋์ ์์ด ํด๋น ๊ธฐ๋ฅ์ ํธ์ถํ๋ ๋ชจ๋ ์ฝ๋๋ฅผ ํ ๊ณณ์ผ๋ก ๊ฐ์ ธ์ฌ ์ ์์์ ๋ณด์ฌ์ค๋๋ค. ์ด๋ฌํ ํจ์์ ๋ํ ํธ์ถ์ ๋ํํ๊ธฐ ์ํด Hook์ด ํ์ํ ์ด์ ๋ ๋ฌด์์ ๋๊น?
์ฝ๋ ์ฌ์ฌ์ฉ ๋ฌธ์ ์ ๋ํ IMHO์ ์ข์ ์๋ฃจ์ ์ ๊ณต๊ธ์๊ฐ ์ ํ ์ฑํํ ํ์๊ฐ ์์ต๋๋ค. ๊ทธ๊ฒ๋ค์ ์์ ํ ์ง๊ตํ๋ ๊ฐ๋ ์ผ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ Flutter ์คํ์ผ ๊ฐ์ด๋๊ฐ "์๋ฃ๋ฅผ ํผํ์ญ์์ค"๋ผ๋ ์ ๋ชฉ์ผ๋ก ์ค๋ช ํ๋ ๊ฒ์ ๋๋ค.
์ด๊ฒ์ด ๋ด๊ฐ ํํฌ๊ฐ ์์์ ์ด๋ผ๊ณ ์ธ๊ธํ ์ด์ ์ ๋๋ค.
๊ทธ๊ฒ๋ค์ ํธ๋ฆฌํจ์ด๋ฉฐ ์์์ ์ด์ง ์์ต๋๋ค. ๊ทธ๋ค์ด ์์์ ์ด๋ผ๋ฉด "๋ฌธ์ ๊ฐ ๋ฌด์์ ๋๊น?"๋ผ๋ ์ง๋ฌธ์ ๋๋ตํ๊ธฐ๊ฐ ํจ์ฌ ์ฌ์ธ ๊ฒ์ ๋๋ค. ๋น์ ์ "์ฌ๊ธฐ ๋ด๊ฐ ํ๊ณ ์ถ์ ์ผ์ด ์๋๋ฐ ํ ์ ์๋ค"๊ณ ๋งํ ๊ฒ์ ๋๋ค.
์์ ๋ก:
package:animations
๋Animation
์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ด ํต์ฌ ํ๋ฆฌ๋ฏธํฐ๋ธ์ด๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
package:animations
๊ฐ ์ปค๋ฎค๋ํฐ์์ ์ ์ง ๊ด๋ฆฌํ๋Animation
์ ํฌํฌ๋ฅผ ๋์ ์ฌ์ฉํ๋ค๋ฉด ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ ๊ฒ์ ๋๋ค.
Animation ํด๋์ค ๊ณ์ธต ๊ตฌ์กฐ๋ ๊ธฐ๋ณธ์ ์ธ ์์ ์ ์ํํฉ๋๋ค. ํฐ์ปค์ ์ด๋ฅผ ์ ์ดํ๊ณ ๊ตฌ๋ ํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํฉ๋๋ค. Animation ํด๋์ค ๊ณ์ธต ๊ตฌ์กฐ๊ฐ ์์ผ๋ฉด ์ ๋๋ฉ์ด์ ์ ์ํํ๋ ค๋ฉด Animation ํด๋์ค ๊ณ์ธต ๊ตฌ์กฐ์ ๊ฐ์ ๊ฒ์ ๋ฐ๋ช ํด์ผ ํฉ๋๋ค. (์ด์์ ์ผ๋ก๋ ๋ ๋์ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ์ ์ต์ ์ ์๋๋๋ค.) Hooks๋ ์๋ก์ด ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ ๋์ ํ์ง ์์ต๋๋ค. ๋์ผํ ์ฝ๋๋ฅผ ๋ค๋ฅด๊ฒ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์ฝ๋๊ฐ ๋ ๊ฐ๋จํ๊ฑฐ๋ ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ์ ๋ค๋ฅด๊ฒ ์ธ์๋ถํด๋ ์ ์์ง๋ง ๊ธฐ๋ณธ ์์๋ ์๋๋๋ค. Hooks๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋์ ๋์ผํ ์์ ์ ์ํํ๋ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํด Hooks์ ์ ์ฌํ ํ๋ ์์ํฌ๊ฐ ํ์ํ์ง ์์ต๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ์ด ๋ฌธ์ ์ ์ค๋ช ๋ ๋ฌธ์ ๋ ํ๋ ์์ํฌ์์ ์์ ํด์ผ ํ ๋ฌธ์ ๊ฐ ์๋๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ฌ๋๋ค๋ง๋ค ๊ทธ๊ฒ์ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์๊ตฌ ์ฌํญ์ด ๋งค์ฐ ๋ค๋ฅผ ๊ฒ์ ๋๋ค. ๊ณ ์น ์ ์๋ ๋ฐฉ๋ฒ์ ๋ง์ด ์์ต๋๋ค. ์ด ๋ฒ๊ทธ์์ ์ด๋ฏธ ๋ช ๊ฐ์ง๋ฅผ ๋ ผ์ํ์ต๋๋ค. ๋ช ๊ฐ์ง ๋ฐฉ๋ฒ์ ๋งค์ฐ ๊ฐ๋จํ๊ณ ๋ช ๋ถ ์์ ์์ฑํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์๋ฃจ์ ์ ์์ ํ๊ณ ์ ์งํ๋ ๋ฐ ๊ฐ์น๋ฅผ ์ ๊ณตํ ์ ๋๋ก ํด๊ฒฐํ๊ธฐ ์ด๋ ค์ด ๋ฌธ์ ๊ฐ ์๋๋๋ค. ๊ฐ ์ ์์๋ ๊ฐ์ ๊ณผ ์ฝ์ ์ด ์์ต๋๋ค. ์ฝ์ ์ ๊ฐ๊ฐ์ ๊ฒฝ์ฐ ๋๊ตฐ๊ฐ๊ฐ ์ฝ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ ๋ฐฉํดํ๋ ์์์ ๋๋ค. ๋ชจ๋ ์ฌ๋์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ๋ค๋ ๋ฐ ๋์ํ๋์ง์กฐ์ฐจ ๋ช ํํ์ง ์์ต๋๋ค.
ํํฌ _are_ ํ๋ฆฌ๋ฏธํฐ๋ธ
๋ค์์ Dan์ ์ค๋ ๋์
๋๋ค. https://twitter.com/dan_abramov/status/1093698629708251136 ์ด์ ๋ํด ์ค๋ช
ํฉ๋๋ค. ์ผ๋ถ ํํ์ ๋ค๋ฅด์ง๋ง React ํด๋์ค Components์ Flutter StatefulWidgets ๊ฐ์ ์ ์ฌ์ฑ์ผ๋ก ์ธํด ๋
ผ๋ฆฌ๋ ๋๋ถ๋ถ Flutter์ ์ ์ฉ๋ฉ๋๋ค.
๋ ๊ตฌ์ฒด์ ์ผ๋ก ๋งํ๋ฉด flutter_hooks
๋ฅผ ๋์ ์ํ ๋ฏน์ค์ธ์ผ๋ก ์๊ฐํ ์ ์์ต๋๋ค.
๊ทธ๋ค์ด ์์์ ์ด๋ผ๋ฉด "๋ฌธ์ ๊ฐ ๋ฌด์์ ๋๊น?"๋ผ๋ ์ง๋ฌธ์ ๋๋ตํ๊ธฐ๊ฐ ํจ์ฌ ์ฌ์ธ ๊ฒ์ ๋๋ค. ๋น์ ์ "์ฌ๊ธฐ ๋ด๊ฐ ํ๊ณ ์ถ์ ์ผ์ด ์๋๋ฐ ํ ์ ์๋ค"๊ณ ๋งํ ๊ฒ์ ๋๋ค.
OP์ ์์ต๋๋ค.
์ํ ๋
ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค. ๋ณต์กํ๊ณ ๊น์ด ์ค์ฒฉ๋ ๋น๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๊ฑฐ๋ ์ฌ๋ฌ ์์ ฏ์ ๋
ผ๋ฆฌ๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ์ด์ผ ํฉ๋๋ค.
๋ฏน์ค์ธ์ด๋ ํจ์๋ฅผ ํตํด ์ด๋ฌํ ๋
ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
์ฝ๋๊ฐ ๋ ๊ฐ๋จํ๊ฑฐ๋ ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ์ ๋ค๋ฅด๊ฒ ์ธ์๋ถํด๋ ์ ์์ง๋ง ๊ธฐ๋ณธ ์์๋ ์๋๋๋ค. Hooks๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋์ ๋์ผํ ์์ ์ ์ํํ๋ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํด Hooks์ ์ ์ฌํ ํ๋ ์์ํฌ๊ฐ ํ์ํ์ง ์์ต๋๋ค.
ํ๋ก๊ทธ๋จ์ ์์ฑํ๋ ๋ฐ ํด๋์ค๊ฐ ํ์ํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ๊ตฌ์กฐํํ๊ณ ์๋ฏธ ์๋ ๋ฐฉ์์ผ๋ก ์ธ์๋ถํดํ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ํด๋์ค๋ ๊ธฐ๋ณธ ์์์
๋๋ค.
ํ๋ฆฌ๋ฏธํฐ๋ธ์ธ ๋ฏน์ค์ธ๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค.
ํํฌ๋ ๊ฐ์ ๊ฒ์ ๋๋ค.
์ด๋ฌํ ํจ์์ ๋ํ ํธ์ถ์ ๋ํํ๊ธฐ ์ํด Hook์ด ํ์ํ ์ด์ ๋ ๋ฌด์์ ๋๊น?
์ฐ๋ฆฌ๊ฐ ์ด ๋ ผ๋ฆฌ๋ฅผ _one_ ์ฅ์๊ฐ ์๋๋ผ _two_ ์ฅ์์์ ํธ์ถํด์ผ ํ ๋๋ฅผ ์ํด.
๋ฏน์ค์ธ์ด๋ ํจ์๋ฅผ ํตํด ์ด๋ฌํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
์ด๋ค ๊ฒฝ์ฐ์ธ์ง ๊ตฌ์ฒด์ ์ธ ์๋ฅผ ๋ค์ด์ฃผ์ธ์. ์ง๊ธ๊น์ง ์ฐ๋ฆฌ๊ฐ ์ฐ๊ตฌํ ๋ชจ๋ ์์ ๋ ํํฌ ์์ด ๊ฐ๋จํ์ต๋๋ค.
์ง๊ธ๊น์ง ์ด ์ค๋ ๋์์ @rrousselGit ํํฌ๋ฅผ ํด๊ฒฐํ๊ณ ์ฝ๊ฒ ์ฌ์ฌ์ฉํ๊ณ ์ํ ๋ ผ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ ์ ์๋ ๋ค๋ฅธ ์๋ฃจ์ ์ ๋ณธ ์ ์ด ์์ต๋๋ค.
์ต๊ทผ์ ๋คํธ์ ํ๋ฌํฐ๋ฅผ ๋ง์ด ํ์ง ์์๊ธฐ ๋๋ฌธ์ ์์ ์์ฑ ์๋ฃจ์
์ฝ๋ ์ํ์์ ๋๋ฝ๋ ํญ๋ชฉ์ด ์์ ์ ์์ง๋ง ์๋ฃจ์
์ด ์์ต๋๊น? ์ค๋๋ ์ฌ์ฌ์ฉ ๋์ ๋ณต์ฌ ๋ถ์ฌ๋ฃ๊ธฐ๊ฐ ํ์ํ์ง ์์ ์ต์
์ ๋ฌด์์
๋๊น?
@rrousselGit ์ง๋ฌธ์ ๋ํ ๋๋ต์ ๋ฌด์์
๋๊น?
ํ์ฌ _ExampleState ๋ด๋ถ์ ์๋ ์ฝ๋๋ฅผ ๋ค๋ฅธ ์์ ฏ์์ ์ฌ์ฌ์ฉํ๋ ๋ณด์กฐ ์์ ฏ์ ๋ง๋ค์ด ์ฃผ์๊ฒ ์ต๋๊น?
ํธ์์คํธ: ์ ์์ ฏ์ State ๋ด๋ถ์์ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉ์ ID๋ฅผ ๊ด๋ฆฌํด์ผ ํฉ๋๋ค.
์์ ์์ฑ ์๋ฃจ์
์ผ๋ก ์ฌ์ด ์ํ ๋
ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๋ค๋ฉด ๋ค๋ฅธ ์ต์
์ ๋ฌด์์
๋๊น?
๋ต์ ๋จ์ํ ํ๋ฌํฐ์์ ์ฝ๊ฒ ์ฌ์ฌ์ฉํ ์ ์์ด์ผ ํ๋ค๋ ๊ฒ์
๋๊น? ์์ ํ ๊ด์ฐฎ์ง ๋ง ์ฝ๊ฐ ์ฌํ IMHO.
BTW, SwiftUI๊ฐ ์๋กญ๊ณ /๋ค๋ฅธ ์๊ฐ์ ์ฃผ๋ ๋ฐฉ์์ผ๋ก ์ํํฉ๋๊น? ์๋๋ฉด ๋์ผํ ์ํ ๋ ผ๋ฆฌ ์ฌ์ฌ์ฉ ๊ฐ๋ฅ์ฑ๋ ๋ถ์กฑํฉ๋๊น? ๋๋ swiftui๋ฅผ ์ ํ ์ฌ์ฉํ์ง ์์์ต๋๋ค. ์ด์ฉ๋ฉด ๋๋ฌด ๋ค๋ฅธ๊ฐ์?
๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ๋น๋. ๋น๋๋ ํ์ฌ ์ํ๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๋ ์ ์ผํ ๋ฐฉ๋ฒ์
๋๋ค.
Hooks๋ ๋น๋๋ฅผ ๋ ์ฝ๊ธฐ ์ฝ๊ณ ์์ฑํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
๋ค์์ ๋ค๋ฅธ ํ๋ก์ ํธ๋ฅผ ์ํด ์ง๋๋ฌ์ ๋ง๋ ์ฌ์ฉ์ ์ ์ ํํฌ ๋ชจ์์ ๋๋ค.
useQuery
โ ์ด์ ์ ์ ๊ณตํ ImplicitFetcher
ํํฌ์ ๋์ผํ์ง๋ง ๋์ GraphQL ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ญ๋๋ค.useOnResume
์ฝ๋ฐฑ ์ ๊ณต์ ์ง์ ๋์ ์ํ AppLifecycleState.resumed
์๊ณ ๋useDebouncedListener
๋ฆฌ์ค๋๋ธ(์ผ๋ฐ์ ์ผ๋ก TextField ๋๋ ScrollController)์ ์์ ํ์ง๋ง ๋ฆฌ์ค๋์์ ๋๋ฐ์ด์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค.useAppLinkService
์ ์ ์ฌํ์ง๋ง ๋น์ฆ๋์ค ๊ท์น์ด ์๋ ์ฌ์ฉ์ ์ ์ ์ด๋ฒคํธ์์ ์์ ฏ์ด ์ผ๋ถ ๋
ผ๋ฆฌ๋ฅผ ์ํํ ์ ์๋๋ก ํ๋ AppLifecycleState.resumed
useShrinkUIForKeyboard
ํค๋ณด๋ ๋ชจ์์ ๋ถ๋๋ฝ๊ฒ ์ฒ๋ฆฌํฉ๋๋ค. UI๊ฐ ํ๋จ ํจ๋ฉ์ ์ ์ํด์ผ ํ๋์ง ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ ๋ถ์ธ์ ๋ฐํํฉ๋๋ค(focusNode ์์ ์ ๊ธฐ๋ฐ์ผ๋ก ํจ).useFilter
useDebouncedListener
๋ฐ useState
(๋จ์ผ ์์ฑ์ ์ ์ธํ๋ ๊ธฐ๋ณธ ํํฌ)๋ฅผ ๊ฒฐํฉํ์ฌ ๊ฒ์ ์ฐฝ์ ๋ํ ํํฐ๋ฅผ ๋
ธ์ถํ๋ useImplicitlyAnimated<Int/Double/Color/...>
โ TweenAnimationBuilder
ํํฌ์ ๋์ผ์ฑ์ ๋ํ ๋ค์ํ ๋ ผ๋ฆฌ์ ๋ํด ๋ง์ ์ ์์ค ํํฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์ ๋์ :
Whatever whatever;
initState() {
whatever = doSomething(widget.id);
}
didUpdateWidget(oldWidget) {
if (oldWidget.id != widget.id)
whatever = doSomething(widget.id);
}
๊ทธ๋ค์ดํ๋ค:
Widget build(context) {
final whatever = useUnaryEvent<Whatever, int>(widget.id, (int id) => doSomething(id));
}
์ด๊ฒ์ initState
/ didUpdateWidget
/ didChangeDependencies
์ฌ์ด์ ์ค๋ณต์ ๋ฐฉ์งํฉ๋๋ค.
๊ทธ๋ค์ ๋ํ StreamBuilder
/ ValueListenableBuilder
์ด์ด์ผ ํ๋ useProvider
๋ง์ด ์ฌ์ฉํฉ๋๋ค.
์ค์ํ ๋ถ๋ถ์ ์์ ฏ์ด "๋จ ํ๋์ ํํฌ"๋ฅผ ๊ฑฐ์ ์ฌ์ฉํ์ง ์๋๋ค๋ ๊ฒ์
๋๋ค.
์๋ฅผ ๋ค์ด ์์ ฏ์ ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
class ChatScreen extends HookWidget {
const ChatScreen({Key key}) : super(key: key);
<strong i="13">@override</strong>
Widget build(BuildContext context) {
final filter = useFilter(debounceDuration: const Duration(seconds: 2));
final userId = useProvider(authProvider).userId;
final chatId = useProvider(selectedChatProvider);
final chat = useQuery(ChatQuery(userId: userId, chatId: chatId, filter: filter.value));
return Column(
children: [
Searchbar(onChanged: (value) => filter.value = value),
Expanded(
child: ChatList(chat: chat),
),
],
);
}
}
๊ฐ๊ฒฐํ๊ณ ๋งค์ฐ ์ฝ๊ธฐ ์ฝ์ต๋๋ค(๋ฌผ๋ก API์ ๋ํ ๊ธฐ๋ณธ ์ง์์ด ์๋ค๊ณ ๊ฐ์ ).
๋ชจ๋ ๋
ผ๋ฆฌ๋ ์์์ ์๋๋ก ์ฝ์ ์ ์์ต๋๋ค. ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ํด ๋ฉ์๋ ๊ฐ์ ์ ํ๊ฐ ์์ต๋๋ค.
์ฌ๊ธฐ์ ์ฌ์ฉ๋ ๋ชจ๋ ํํฌ๋ ์ฝ๋๋ฒ ์ด์ค์ ์ฌ๋ฌ ์์น์์ ์ฌ์ฌ์ฉ๋ฉ๋๋ค.
ํํฌ ์์ด ๋๊ฐ์ ์์ ์ ์ํํ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ฉ๋๋ค.
class ChatScreen extends StatefulWidget {
const ChatScreen({Key key}) : super(key: key);
<strong i="20">@override</strong>
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
String filter;
Timer timer;
<strong i="21">@override</strong>
void dispose() {
timer?.cancel();
super.dispose();
}
<strong i="22">@override</strong>
Widget build(BuildContext context) {
return Consumer<Auth>(
provider: authProvider,
builder: (context, auth, child) {
return Consumer<int>(
provider: selectedChatProvider,
builder: (context, chatId, child) {
return GraphQLBuilder<Chat>(
query: ChatQuery(
userId: auth.userId,
chatId: chatId,
filter: filter.value,
),
builder: (context, chat, child) {
return Column(
children: [
Searchbar(
onChanged: (value) {
timer?.cancel();
timer = Timer(const Duration(seconds: 2), () {
filter = value;
});
},
),
Expanded(
child: ChatList(chat: chat),
),
],
);
},
);
},
);
},
);
}
}
์ด๊ฒ์ ๊ฐ๋ ์ฑ์ด ํ์ ํ ๋จ์ด์ง๋๋ค.
FilterBuilder
๋ฅผ ๋ง๋๋ ๊ฒฝ์ฐ 12๋จ๊ณ์
๋๋ค.timer
์ทจ์ํ๋ ๊ฒ์ ์์ด๋ฒ๋ฆด ์ ์์ต๋๋ค.build
๋ฐฉ๋ฒ์ ์ ๋ฐ์ ๋
์์๊ฒ ์ ์ฉํ์ง ์์ต๋๋ค. Builders๋ ์ค์ํ ๊ฒ์์ ์ฐ๋ฆฌ๋ฅผ ์ฐ๋งํ๊ฒ ํฉ๋๋ค.flutter_hooks
์ฌ์ฉ์๋ก์ ์ ์๊ฒฌ์ ๋๋ฆฌ๊ฒ ์ต๋๋ค. ํํฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์๋ Flutter์ ๋ง์กฑํ์ต๋๋ค. ๋๋ ๊ทธ๋ฐ ๊ฒ์ด ํ์ํ๋ค๊ณ ๋ณด์ง ์์๋ค. ๊ทธ๊ฒ์ ๋ํด ์ฝ๊ณ ๊ทธ๊ฒ์ ๋ํ YouTube ๋น๋์ค๋ฅผ ๋ณธ ํ์๋ ์ฌ์ ํ ํ์ ์ด ์์ง ์์๊ณ ๋ฉ์์ด ๋ณด์์ง๋ง ์ค์ ๋ก ๋๊ธฐ๋ฅผ ๋ถ์ฌํ๋ ค๋ฉด ๋ช ๊ฐ์ง ์ฐ์ต์ด๋ ์์ ๊ฐ ํ์ํ์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ๋๋ ๋ญ๊ฐ๋ฅผ ์์์ฐจ๋ ธ๋ค. ๋๋ ์ด๋ค ํฌ์์ ์น๋ฅด๋๋ผ๋ ์ํ ์ ์ฅ ์์ ฏ์ ํผํ๊ณ ์์๊ณ ๋ง์ ์์ฉ๊ตฌ์ ๊ด๋ จ๋ ๋ด์ฉ์ด ์์๊ณ ํด๋์ค๋ฅผ ๊ฑด๋๋ฐ๋ฉด์ ๋ฌด์ธ๊ฐ๋ฅผ ์ฐพ์ผ๋ ค๊ณ ๋
ธ๋ ฅํ์ต๋๋ค. ๊ทธ ๋๋ฌธ์ ๋๋ ์์ ์ํ์ ๋๋ถ๋ถ์ ๋๋จธ์ง ์ฑ ์ํ์ ํจ๊ป ์ํ ๊ด๋ฆฌ ์๋ฃจ์
์ผ๋ก ์ฎ๊ฒผ๊ณ ์ํ ๋น์ ์ฅ ์์ ฏ๋ง ์ฌ์ฉํ์ต๋๋ค. ๊ทธ๋ฌ๋,์ด ๋น์ฆ๋์ค ๋ก์ง์ ์ ์ ์ด์ ๋ก ์ธํด ์ ๋ขฐ์ ์ ์ ๋จ๋ฆผ์ ๋ฐ๋ผ ์์ธ์ด Navigator
, ๋๋ BuildContext
์ ์ก์ธ์คํ๊ธฐ์ํ InheritedWidget
์ / Providers
๋์ ๋๋ฌด. ๊ทธ๊ฒ์ด ์ข์ ์ํ ๊ด๋ฆฌ ์ ๊ทผ ๋ฐฉ์์ด๋ผ๊ณ ๋งํ์ง๋ ์์์ง๋ง ๊ทธ๋ ์ง ์๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ํ์ง๋ง UI์์ ์ํ ๊ด๋ฆฌ์ ๋ํ ๊ฑฑ์ ์ ํ์ง ์๊ธฐ ์ํด ํ ์ ์๋ ๋ชจ๋ ๊ฒ์ ํ์ต๋๋ค.
์ ์ ํํฌ๋ฅผ ์ฌ์ฉํ ํ Flutter๋ฅผ ์ฌ์ฉํ์ฌ ์ฑ ์ํ๋ณด๋ค ์์ ์ํ๋ฅผ ์ ์ ํ ์์น์(UI์ ํจ๊ป) ํจ์ฌ ๋ ์์ฐ์ ์ด๊ณ ํจ์ฌ ๋ ๋ง์กฑ์ค๋ฝ๊ฒ ์ฌ์ฉํ์ต๋๋ค.
๋์๊ฒ ๊ทธ๊ฒ์ ์์ ์ํ/์ปจํธ๋กค๋ฌ๋ฅผ ์ํ ๊ฐ๋น์ง ์์ง๊ธฐ์ ๊ฐ์ต๋๋ค. UI์์ ๋ชจ๋ ๊ตฌ๋
์ ์ญ์ ํ๋ ๊ฒ์ ๊ธฐ์ตํ ํ์๋ ์์ง๋ง ์ด๊ฒ์ด flutter_hooks
๊ฐ ์ ์๊ฒ ํ๋ ์ผ์ด๋ผ๋ ์ฌ์ค์ ์ฌ์ ํ ์ ์๊ณ ์์ต๋๋ค. ๋ํ ๋ด ์ฝ๋๋ฅผ ์ ์ง ๊ด๋ฆฌํ๊ณ ๋ฆฌํฉํ ๋งํ๊ธฐ๊ฐ ํจ์ฌ ์ฝ์ต๋๋ค. ์ง๋ 1๋
๋์ ๋ํ์ ์ฐ๊ตฌ์ ์ฌ๋ฏธ๋ฅผ ์ํด ~10๊ฐ์ ์ฑ์ ์์ฑํ๋ฉด์ ์ด์ผ๊ธฐํ์ต๋๋ค.
๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก Flutter SDK ์์ฒด์ ํฌํจํด์ผ ํ๋ ์ฃผ๋ ๋๊ธฐ๊ฐ ๋ฌด์์ธ์ง ์ ํํ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๊ธฐ์ ๊ทธ ์ฃผ์ ์ ๋ํด ๋ ๊ฐ์ง ์๊ฐ์ด ์์ต๋๋ค.
๊ฐ๋ ์ด๊ธฐํ/ํ๊ธฐํด์ผ ํ๋ ์ปจํธ๋กค๋ฌ๊ฐ ์๋ ํจํค์ง๋ฅผ ๋ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ํํฌ๋ฅผ ๋ง๋ค ๊ฒ์
๋๋ค. (์: golden_layout
๋๋ zefyr
). ๋๋ flutter_hooks
์ฌ์ฉํ๋ ๋ค๋ฅธ ์ฌ์ฉ์๋ค์ด ๊ทธ๋ฌํ ํจํค์ง๋ก๋ถํฐ ํํ์ ๋ฐ์ ๊ฒ์ด๋ผ๊ณ ๋ฏฟ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ง ๊ทธ๋๋ก 1-3๊ฐ์ ๊ธฐ๋ฅ์ ํฌํจํ๋ ํจํค์ง๋ฅผ ๊ฒ์ํ๋ ๊ฒ์ ์ ๋นํํ ์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋์์ ๋ด๊ฐ ์ฌ์ฉํ๋ ๋ค์ํ ํจํค์ง์ ๋ํ ๋ง์ ํํฌ๋ฅผ ํฌํจํ๋ ์ฃผ๋ฐฉ ์ฑํฌ ํจํค์ง๋ฅผ ๋ง๋๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฐ ๋ค์ git ์ข
์์ฑ์ ์ฌ์ฉํ ์ ์์ง๋ง ๋ค๋ฅธ ํจํค์ง + flutter_hooks๋ฅผ ์ฌ์ฉํ๋ ์ฌ๋์ ๋ด git์ ์์กดํด์ผ ํฉ๋๋ค. ํํ์ ๋ฐ๊ธฐ ์ํด(๊ฒ์ ๊ฐ๋ฅ์ฑ์ด ๋ฎ๊ณ ๊ด์ฌ ์๋ ํจํค์ง์ ๋ํ ์ข
์์ฑ์ ํฌํจํ ์ ์์) 3๊ฐ์ง ๊ธฐ๋ฅ์ด ํฌํจ๋ ํจํค์ง ๋๋ pub.dev์ garden-sink ํจํค์ง๋ฅผ ๊ฒ์ํฉ๋๋ค. ๋ชจ๋ ์์ด๋์ด๋ ์ฐ์ค๊ฝ์ค๋ฝ๊ณ ๋ฐ๊ฒฌํ๊ธฐ ์ฝ์ง ์์ต๋๋ค. flutter_hooks
์ ๋ค๋ฅธ ์ฌ์ฉ์๋ ํด๋น ๊ธฐ๋ฅ์ ์ฝ๊ฒ ๋ณต์ฌํ์ฌ ์ฝ๋์ ๋ถ์ฌ๋ฃ๊ฑฐ๋ ๋
ผ๋ฆฌ ์์ฒด๋ฅผ ํ์
ํ๋ ค๊ณ ์๋ํ ์ ์์ง๋ง, ์ด๋ ์ฝ๋/ํจํค์ง๋ฅผ ๊ณต์ ํ๋ ์์ ์ ์์ ํ ๋์น๊ณ ์์ต๋๋ค. ๊ธฐ๋ฅ์ ์ผ๋ถ 'ํ์ฅ ํจํค์ง'๊ฐ ์๋ ์๋ ํจํค์ง๋ก ๋ค์ด๊ฐ๋ ๊ฒ์ด ํจ์ฌ ์ข์ต๋๋ค. flutter_hooks
์ด ํ๋ ์์ํฌ์ ์ผ๋ถ์ด๊ฑฐ๋ characters
์ ๊ฐ์ด ํ๋ ์์ํฌ์์ ์ฌ์ฉ๋๊ฑฐ๋ ๋ด๋ณด๋ด์ง ํจํค์ง์ธ ๊ฒฝ์ฐ ์๋ ํจํค์ง ์์ฑ์๋ ๊ฐ๋จํ ํํฌ์ ๋ํ ํ ์์ฒญ์ ์๋ฝํ ๊ฐ๋ฅ์ฑ์ด ํจ์ฌ ๋ ๋์ต๋๋ค. ๊ธฐ๋ฅ์ด ์์ผ๋ฉฐ 1-3๊ฐ์ ๊ธฐ๋ฅ ํจํค์ง๊ฐ ์๋ง์ด ๋์ง ์์ต๋๋ค.
flutter_hooks
๊ฐ Flutter์ ์ํด ์ฑํ๋์ง ์์ผ๋ฉด pub.dev ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ์ด์ง๋ฝํ๋ 1-3๊ฐ์ ํจ์ ํจํค์ง๋ฅผ ์์ํฉ๋๋ค. ์ด ํจํค์ง๊ฐ ์ ๋ง ์๋ค๋ ์ฌ์ค์ ์ด๊ฒ์ด ์์์ ์ด๋ผ๋ @rrousselGit์ ์ ๋ง๋ก ๋์ํ๊ฒ ๋ง๋ญ๋๋ค. flutter_hooks
์ ์ฅ์ ์ ์๋ 1228๊ฐ์ ๋ณ์ด @rrousselGit์์ ์ธ๊ธํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค๋ ํ์๊ฐ
๋ด๊ฐ ๋์ธ ์ ์๋ ์ผ์ ๊ด์ฌ์ด ์์๊ธฐ ๋๋ฌธ์ Flutter ๋ฆฌํฌ์งํ ๋ฆฌ์ ๊ธฐ์ฌํ๋ ๋ฐฉ๋ฒ์ ๋ํ YouTube ๋์์์ ๋ณด๊ณ ์์์ต๋๋ค. ๋ด๊ฐ ๋ณด๊ณ ์๋ ๋์ ์ ์์ฑ์ ๋น๋์ค๋ฅผ ๋ง๋๋ ์ฌ๋์ด ์๋นํ ์ฝ๊ฒ ์ถ๊ฐ๋์์ง๋ง dispose
, didUpdateWidget
๋ฐ debugFillProperties
์
๋ฐ์ดํธ๋ฅผ ๊ฑฐ์ ์์ด ๋ฒ๋ ธ์ต๋๋ค. ์ํ ์ ์ฅ ์์ ฏ์ ๋ชจ๋ ๋ณต์ก์ฑ๊ณผ ๋ฌด์ธ๊ฐ๋ฅผ ๋์น๋ ๊ฒ์ด ์ผ๋ง๋ ์ฌ์ด์ง ๋ค์ ๋ณด๋ ๊ทธ๊ฒ๋ค์ ๋ค์ ๋ถ์ ํ๊ฒ ๋์๊ณ ๋ฉ์ธ Flutter ์ ์ฅ์์ ๊ธฐ์ฌํ๋ ๊ฒ์ ๋ํด ํฅ๋ถํ์ง ์๊ฒ ๋์์ต๋๋ค. ๊ทธ๊ฒ์ด ๋๋ฅผ ์์ ํ ๋จ๋
์์ผฐ๋ค๋ ๋ง์ ์๋์ง๋ง, ๋๋ ์ฌ์ ํ ๊ธฐ์ฌํ๋ ๋ฐ ๊ด์ฌ์ด ์์ง๋ง ์ ์ง ๋ฐ ๊ฒํ ํ๊ธฐ ์ด๋ ค์ด ์์ฉ๊ตฌ ์ฝ๋๋ฅผ ๋ง๋๋ ๊ฒ์ฒ๋ผ ๋๊ปด์ง๋๋ค. ์ฝ๋ ์์ฑ์ ๋ณต์ก์ฑ์ด ์๋๋ผ ์ฝ๋๋ฅผ ์ฝ๊ณ ์์ ์ํ๋ฅผ ์ ์ ํ๊ฒ ์ฒ๋ฆฌํ๊ณ ์ฒ๋ฆฌํ๋์ง ํ์ธํ๋ ๋ณต์ก์ฑ์ ๊ดํ ๊ฒ์
๋๋ค.
์ฅํฉํ ๋ต๋ณ์ ์ฃ์กํฉ๋๋ค. ํ์ง๋ง ์ด ๋ฌธ์ ๋ฅผ ์์๋ก ์ดํด๋ณด๊ณ ์์๊ณ Flutter ํ์ ๋ต๋ณ์ ๋ค์ ๋นํฉํ์ต๋๋ค. ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์ฑ์ ์ฌ์ฉํด ๋ณด๊ณ ์ฐจ์ด์ ์ ์ง์ ํ์ธํ๋ ๋ฐ ์๊ฐ์ ๋ค์ด์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค. ์ถ๊ฐ ์ข
์์ฑ์ ์ ์งํ๊ฑฐ๋ ํ๋ ์์ํฌ์ ๋๋ฌด ๋ง์ด ํตํฉํ์ง ์์ผ๋ ค๋ ๋ฐ๋์ ์ดํดํฉ๋๋ค. ๊ทธ๋ฌ๋ flutter_hook
ํ๋ ์์ํฌ์ ํต์ฌ ๋ถ๋ถ์ ๊ฝค ์ ๋ฌธ์ํ๋ ์ฝ๋์ 500์ค์ ๋ถ๊ณผํฉ๋๋ค. ๋ค์ ๋งํ์ง๋ง ์ด๊ฒ์ด ๋ํ์ ๊ด๋ จ์ด ์๋ค๋ฉด ์ฃ์กํฉ๋๋ค. ์ 2์ผํธ๋ฅผ ์ฃผ๊ณ ์ ๋ชฉ์๋ฆฌ๋ฅผ ๋ธ ๊ฒ์ ๋ํด ๋ค๋ฅธ ์ฌ๋์ ๊ธฐ๋ถ์ ์ํ๊ฒ ํ์ง ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. @rrousselGit ์ด ๋งค์ฐ ์ข์ ์ง์ ์ ํ๊ณ ์๊ณ ๋ช
ํํ๋ค๊ณ
์ฅํฉํ ๋ต๋ณ์ ์ฃ์กํฉ๋๋ค. ํ์ง๋ง ์ด ๋ฌธ์ ๋ฅผ ์์๋ก ์ดํด๋ณด๊ณ ์์๊ณ Flutter ํ์ ๋ต๋ณ์ ๋ค์ ๋นํฉํ์ต๋๋ค. ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์ฑ์ ์ฌ์ฉํด ๋ณด๊ณ ์ฐจ์ด์ ์ ์ง์ ํ์ธํ๋ ๋ฐ ์๊ฐ์ ๋ค์ด์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค.
๊ณต์ ํ๊ฒ ๋งํ์๋ฉด ์ด๊ฒ์ ์์ฒญ๋๊ฒ ๊ธด ์ค๋ ๋์ด๋ฉฐ ํ๋ ์์ํฌ์ ์ค๋ฆฝ์๋ ์ฌ๋ฌ ์๋ฃจ์ ์ผ๋ก ๋งค์ผ ์ฌ๋ฌ ๋ฒ ์ ๊ทน์ ์ผ๋ก ๊ธฐ์ฌํ๊ณ ์ด์ ๋ํ ํผ๋๋ฐฑ์ ์์ฒญํ๊ณ ์ฐธ์ฌํ๊ณ ์์ฒญ๋ ๋ด์ฉ์ ์ดํดํ๊ธฐ ์ํด ๋ ธ๋ ฅํ์ต๋๋ค. ๋๋ ์์งํ ๋์์ด ๋๋ ์ ์ง ๋ณด์์ ๋ช ํํ ์๋ฅผ ์๊ฐํ๊ธฐ ์ํด ๊ณ ๊ตฐ๋ถํฌํฉ๋๋ค.
์ด ๋ฌธ์ ์ ๋ํด ์กฐ๊ธ ๋ ์ธ๋ด์ฌ์ด ์์์ผ๋ฉด ํฉ๋๋ค. ์ด ์ค๋ ๋๋ฅผ ์ฝ์ ํ ํํฌ๋ฅผ ๋ ๊น์ด ์ดํดํ์ง ๋ชปํฉ๋๋ค. ๋จ, ์ผํ์ฉ ์ ํ์ ์๋ช ์ State์ ๋ฌถ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด๋ผ๋ ์ ์ ๋๋ค. ๋๋ ๊ทธ ์ ๊ทผ ๋ฐฉ์์ ์คํ์ผ์ ์ผ๋ก ์ ํธํ์ง ์์ผ๋ฉฐ, ์ ์ฅ์ด '์๊ฐ์ ๋ค์ฌ ํจ๋ฌ๋ค์์์ ์์ ํ ์๋ก์ด ์ฑ์ ์์ฑํ๋ฉด ๊ทผ๋ณธ์ ์ผ๋ก ๊ฒฐํจ์ด ์๋ ๋ฌด์ธ๊ฐ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ์ ํ๋ ์์ํฌ์ ๋ผ์๋ฃ์ด์ผ ํ๋์ง ์ดํดํ ์ ์์ ๊ฒ์ ๋๋ค! ' - React ์์ง๋์ด๊ฐ ์ด ์ค๋ ๋์์ ์ธ๊ธํ๋ฏ์ด Flutter์๋ ์ค์ ๋ก ๊ถ์ฅ๋์ง ์์ผ๋ฉฐ ์ด ์ค๋ ๋์์ ์ค๋ช ํ๋ ์ด์ ์ ์ฌ๋ฐฐ์ ์ ๋น์ฉ์ ๋นํด ์์ต๋๋ค. ์ฆ, ์ด์ ์ ๋ณด๋ ค๋ฉด ์์ ํ ์๋ก์ด ์ฝ๋๋ฒ ์ด์ค๊ฐ ํ์ํฉ๋๋ค.
๋๋ ์์งํ ๋์์ด ๋๋ ์ ์ง ๋ณด์์ ๋ช ํํ ์๋ฅผ ์๊ฐํ๊ธฐ ์ํด ๊ณ ๊ตฐ๋ถํฌํฉ๋๋ค.
๋์. ์๊ฐ์ ๋ด์ด ์ด ํ ๋ก ์ ์ฐธ์ฌํด ์ฃผ์ Hixie์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
์ด ์ค๋ ๋๋ฅผ ์ฝ์ ํ ํํฌ๋ฅผ ๋ ์ด์ ๊น์ด ์ดํดํ์ง ๋ชปํฉ๋๋ค.
๊ณต์ ํ๊ฒ ๋งํ๋ฉด ์ด ๋ฌธ์ ๋ ๋ช
์์ ์ผ๋ก ํํฌ์ ๋ํด ์ด์ผ๊ธฐํ๋ ๊ฒ์ ํผํ๋ ค๊ณ ํฉ๋๋ค.
์ด๊ฒ์ ํด๊ฒฐ์ฑ
๋ณด๋ค ๋ฌธ์ ๋ฅผ ์ค๋ช
ํ๋ ค๊ณ ๋
ธ๋ ฅํ๋ ๊ฒ์ ๊ดํ ๊ฒ์
๋๋ค.
๊ทธ๋ ๊ฒ ํ์ง ๋ชปํ๋ค๊ณ ๋๋ผ์ญ๋๊น?
์ ๋ ์ฌ๊ธฐ์ ์์ชฝ( @rrousselGit ๋ฐ @Hixie)์ ๋๋ ์ ์์ผ๋ฉฐ Flutter ํ๋ ์์ํฌ์ (๋ด) ์ฌ์ฉ ์ธก๋ฉด/๊ด์ ์์ ํผ๋๋ฐฑ์ ๋จ๊ธฐ๊ณ ์ถ์์ต๋๋ค.
flutter_hooks
์ ๊ทผ ๋ฐฉ์์ ์์ฉ๊ตฌ๋ฅผ ์๋นํ ์ค์ด๊ณ (์ด๋ฌํ ์ํ ๊ตฌ์ฑ์ ์ฌ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ์ฌ๊ธฐ์ ํ์๋ ์์์๋ง) ๋ฆฌ์์ค ์ด๊ธฐํ/ํ๊ธฐ์ ๋ํด ์ ๊ทน์ ์ผ๋ก ์๊ฐํ ํ์๊ฐ ์์ด ๋ณต์ก์ฑ์ ์ค์
๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๋งํ์๋ฉด Flutter ์์ฒด์ "ํต์ฌ"์ (์ฃผ๊ด์ ์ผ๋ก) ์ ๋ง์ง๋ ์์ง๋ง ๊ฐ๋ฐ ํ๋ฆ/์๋๋ฅผ ๊ฐ์ ํ๊ณ ์ง์ํ๋ ๋ฐ ์ข์ ์ญํ ์ ํฉ๋๋ค.
๋ด๊ฐ ์์ฑํ ์ฝ๋์ 95% ์ด์์ ๋น๋ ๋ฉ์๋๊ฐ ์ ์ธ์ ์ผ ๋ฟ์ด๊ณ ๋ก์ปฌ ๋ณ์๋ ๋ฐํ๋ ์์ ฏ ํ์ ํธ๋ฆฌ ์ธ๋ถ์ ํธ์ถ์ด ์๋ ๊ฒ์ฒ๋ผ ๋ชจ๋ ๋
ผ๋ฆฌ ๋ถ๋ถ์ ๋ฆฌ์์ค๋ฅผ ์ด๊ธฐํ, ํ ๋น ๋ฐ ์ญ์ ํ๊ณ ๋ฆฌ์์ค๋ฅผ ์ถ๊ฐํ๋ ์ํ ํจ์ ๋ด๋ถ์ ์์ต๋๋ค. ์ฒญ์ทจ์(์ ๊ฒฝ์ฐ์๋ MobX ๋ฐ์) ๋ฐ ๊ทธ๋ฌํ ๋
ผ๋ฆฌ์ ์ธ ๊ฒ์
๋๋ค. ์ด๊ฒ์ Flutter ์์ฒด์ ๋๋ถ๋ถ์ ์ ๊ทผ ๋ฐฉ์์ด๊ธฐ๋ ํ๋ฏ๋ก ๋งค์ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ๋๊ปด์ง๋๋ค. ๊ทธ๋ ๊ฒ ํ๋ฉด ๊ฐ๋ฐ์์๊ฒ ๋น์ ์ด ํ๋ ์ผ์ ๋ํด ํญ์ ๋ช
์์ ์ด๊ณ ๊ฐ๋ฐฉ์ ์ผ ์ ์๋ ๊ธฐํ๋ฅผ ์ฃผ๊ธฐ๋ ํฉ๋๋ค. ๋ฐ๋ผ์ ์ด๋ฌํ ์์ ฏ์ ํญ์ StatefulWidget
๋ณํํ๊ณ initState / dispose์ ์ ์ฌํ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค. ํญ์ ์ ํํ ๋ฌด์์ ํ๋ ค๋์ง ์ ํํ ๊ธฐ๋กํ๋ ๊ฒฐ๊ณผ๋ฅผ ์์ ฏ์ด ์ฌ์ฉ ์ค์ธ ์์ ฏ์ ์ง์ ์์ฑํฉ๋๋ค. ๊ฐ์ธ์ ์ผ๋ก @Hixie๊ฐ ์ด๋ฏธ ์์ ์ ์ธ๊ธํ๋ฏ์ด ์ด๋ฐ ์ข
๋ฅ์ ์์ฉ๊ตฌ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์ด๋ค ์์ผ๋ก๋ ๊ท์ฐฎ๊ฒ ํ์ง ์์ผ๋ฉฐ ๊ฐ๋ฐ์๋ก์ flutter_hooks
์ ์์กดํ๋ ๋์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๊ฒฐ์ ํ ์ ์์ต๋๋ค flutter_hooks
์ฌ์ฉํ๋ฉด ์ด๋ค ์ํ๋ฅผ ํํฌ๋ก ์์ฑํ์ฌ ์ฌ์ฌ์ฉํ ๊ฐ์น๊ฐ ์๋์ง์ ๋ํด ์ฌ์ ํ ์๊ฐํด์ผ ํฉ๋๋ค. ๋ค๋ฅธ ํ๋ฏธ๋ ๋ค์ํ "๋จ์ผ" ์ฌ์ฉ ํํฌ๋ฅผ ์์ฑํ๊ฑฐ๋ ํํฌ๋ฅผ ์ ํ ์ฌ์ฉํ์ง ์์ ์ ์์ต๋๋ค. ๊ตฌ์ฑ์ ๋๋ฌด ์์ฃผ ์ฌ์ฌ์ฉํ์ง ์์ง๋ง ๋ ๋ง์ ์ฌ์ฉ์ ์ ์ ๊ตฌ์ฑ์ ์์ฑํ๋ ๊ฒฝํฅ์ด ์์ต๋๋ค.
์คํดํ์ง ๋ง์ธ์. ์ด๋ฌํ ํํฌ์ ์ ๊ทผ ๋ฐฉ์์ ๋งค์ฐ ํ๋ฅญํ๊ณ ์ ์ฉํด ๋ณด์ด์ง๋ง ์ ์๊ฒ๋ ์ด๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ํต์ฌ ๊ฐ๋ ์ ๋ณ๊ฒฝํ๋ ๋งค์ฐ ๊ธฐ๋ณธ์ ์ธ ๊ฐ๋ ์ฒ๋ผ ๋๊ปด์ง๋๋ค. ๊ฐ๋ฐ์๊ฐ "๊ธฐ๋ณธ์ ์ผ๋ก" ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ง์กฑํ์ง ์๋ ๊ฒฝ์ฐ ์ด๋ฌํ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ ์ ์๋ ๊ธฐํ๋ฅผ ๊ฐ๋ฐ์์๊ฒ ์ ๊ณตํ๋ ํจํค์ง ์์ฒด๋ก์ ๋งค์ฐ ๊ธฐ๋ถ์ด ์ข์ต๋๋ค. ํตํฉ๋๋ฉด ์ด ๊ฐ๋ ์ ์ฌ์ฉํ๊ธฐ ์ํด Flutter์ ํฐ ๋ถ๋ถ์ ๋ค์ ์์ฑํ๊ฑฐ๋(๋ง์ ์์ ) ๋ฏธ๋/์ ํ๋ ํญ๋ชฉ์ ์ฌ์ฉํฉ๋๋ค(์ด๋ฌํ ํผํฉ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ ๊ฒ์ด ํผ๋์ค๋ฌ์ธ ์ ์์).
Flutter ํ๋ ์์ํฌ ์์ฒด์ ํตํฉ๋๊ณ ์ง์/ํ์ฉ๋๋ค๋ฉด ๋ถ๋ช ํ ์ฌ๊ธฐ์ ๋ฐ์ด๋ค ๊ฒ์ ๋๋ค. ํ์ฌ ์ ๊ทผ ๋ฐฉ์์ ์ดํดํ๊ณ ์ฌ์ง์ด ์ข์ํ๋ฉฐ ์ด๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ตฌํํ๋ ๋ฐ ํ์ํ (๊ฐ๋ฅํ) ์กฐ์น๋ฅผ ๋ณด์๊ธฐ ๋๋ฌธ์ ์ฃผ์ ๋ฐ/๋๋ ์ํํด์๋ ์ ๋๋ ์ด์ ๋ฅผ ์ดํดํ๊ณ ํจํค์ง๋ก ๋ณด๊ดํ ์ ์์ต๋๋ค.
๋ด๊ฐ ํ๋ ธ๋ค๋ฉด ์ ์ ํด ์ฃผ์ธ์. ํ์ง๋ง ์ด ์ค๋ ๋๋ ์ฝ๊ธฐ ๊ฐ๋ฅํ๊ณ ๊ตฌ์ฑ ๊ฐ๋ฅํ ๋ฐฉ์์ผ๋ก ์ฌ๋ฌ ์์ ฏ์์ ์ํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๋ฌธ์ ์ ๊ดํ ๊ฒ์ ๋๋ค. ํนํ ํํฌ๊ฐ ์๋๋๋ค. ๋๋ ์ด ์ค๋ ๋๊ฐ ํด๊ฒฐ์ฑ ์ด ๋ฌด์์ธ์ง์ ๋ํ ๊ณต๊ฐ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ผ๋ก ๋ฌธ์ ์ ๋ํ ํ ๋ก ์ ํ๊ณ ์ถ์๊ธฐ ๋๋ฌธ์ ์ด๋ฆฐ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
ํํฌ๋ ํ๋์ ์๋ฃจ์ ์ด๊ธฐ ๋๋ฌธ์ ์ธ๊ธ๋์์ง๋ง @rrousselGit ์ด ์ฌ๊ธฐ์์ ์ฌ์ฉํ์ฌ ๊ทธ๋ค์ด ํด๊ฒฐํ๋ ๋ฌธ์ /๋ฌธ์ ๋ฅผ ์ค๋ช ํ๊ณ (์๋ฃจ์ ์ด๊ธฐ ๋๋ฌธ์) ํ๋ฌํฐ์ ๋ ๊ณ ์ ํ ๋ค๋ฅธ ์๋ฃจ์ ์ด ๋์ฌ ์ ์๋ค๊ณ ๋ฏฟ์ต๋๋ค. ์ ํจ๊ป ์ ์ํ์ต๋๋ค. ์ง๊ธ๊น์ง ์ฌ์ฌ์ฉ์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง๋ง ์ด ์ค๋ ๋์ ๋ค๋ฅธ ์๋ฃจ์ ์ด ์ ์๋์ง ์์์ต๋๊น?
์ฆ, ์ค๋ ๋๊ฐ ํ์ฌ ์ด๋๋ก ๊ฐ๊ณ ์๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๋ฌธ์ ๊ฐ ์ค์ ๋ก ์กด์ฌํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์๋๋ฉด ์ฐ๋ฆฌ๊ฐ ์ด๊ฒ์ ํ ๋ก ํ๊ณ ์์ต๋๊น?
์ค๋๋ Flutter์ ํต์ฌ์ด ์๋ ์ฌ๋ฌ ์์ ฏ์์ ๊ตฌ์ฑ ๊ฐ๋ฅํ ๋ฐฉ์์ผ๋ก ์ํ ๋
ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ์ด๋ ต๋ค๋ ๋ฐ ๋ชจ๋ ๋์ํ๋ค๋ฉด ํต์ฌ ์๋ฃจ์
์ด ๋ ์ ์๋ ์๋ฃจ์
์ ๋ฌด์์
๋๊น? ๋น๋๋ ์ค์ ๋ก (์ธ์ฉํ๊ธฐ ์ํด)
๊ฐ๋ ์ฑ์ด ํ์ ํ ๋จ์ด์ง
์์ฑ ์๋ฃจ์ ์ ์ฝ๊ฒ ์ฌ์ฌ์ฉํ ์ ์๋ ๊ฒ ๊ฐ๊ฑฐ๋ ๋ค์๊ณผ ๊ฐ์ ์ฉ๋๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋ต๋ณ์ด ์์๊ธฐ ๋๋ฌธ์ ์๋ชป๋ ๊ฒฐ๋ก ์ ๋ด๋ ธ์ต๋๋ค.
ํ์ฌ ๋ค๋ฅธ ์์ ฏ์ _ExampleState ๋ด๋ถ์ ์๋ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ ๋ณด์กฐ ์์ ฏ์ ๋ง๋์๊ฒ ์ต๋๊น?
ํธ์์คํธ: ์ ์์ ฏ์ State ๋ด๋ถ์์ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉ์ ID๋ฅผ ๊ด๋ฆฌํด์ผ ํฉ๋๋ค.
@timsneath๊ฐ ์ ์ํ ๋๋ก ์ค๊ณ ๋ฌธ์๋ฅผ ๊ธฐ๊บผ์ด ๋์๋๋ฆฌ๊ฒ ์ต๋๋ค. ๋ช ๊ฐ์ง ์ฌ๋ก ์ฐ๊ตฌ ์ฌ๋ก๋ก ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๊ณ ๋ค์ํ ์๋ฃจ์ ์ ์ธ๊ธํ๊ณ Flutter์ ๋ง๋ ์๋ฃจ์ ์ ์ฐพ์ ์ ์๋์ง ํ์ํ๋ ๊ฒ์ด ๋ ๋์ ํ์์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋๋ ์ด ๋ฌธ์ ์ ๋ํ ๋ ผ์๊ฐ ๋ค์ ๊ธธ์ ์๋ ๋ฐ ๋์ํฉ๋๋ค.
๋๋ ํ์ฌ ๋์์ธ ๋ฌธ์๋ฅผ ๋ง๋๋ ์์ด๋์ด์ ๋ํด ์๋นํ ํ์์ ์
๋๋ค.
ํ์ฌ @Hixie ๋ Flutter ๋ด์์ ์ด ๋ฌธ์ ๋ฅผ ์ง์ ํด๊ฒฐํ๋ ๊ฒ์ ๋ฐ๋ํฉ๋๋ค.
์ ๊ฐ ๋ณด๊ธฐ์๋ ๋ฌธ์ ์ ์ค์์ฑ๊ณผ ๊ทธ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ Google์ ์ญํ ์ ๋ํด ์๊ฒฌ์ด ์ผ์นํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์์ธก์ด ์ด์ ๋์ํ์ง ์๋๋ค๋ฉด, ํด๊ฒฐ์ฑ
์ด ๋ฌด์์ด๋ ๊ฐ์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ด๋ป๊ฒ ์์ฐ์ ์ธ ํ ๋ก ์ ํ ์ ์์์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
์ด ๋ฌธ์ ์ค๋ ๋๋ ๋งค์ฐ ํฅ๋ฏธ๋กญ๊ฒ ์ฝ์์ผ๋ฉฐ ๊ด์ ์ ๊ตํ์ด ์ฌ์ ํ ์๋ฏผ์ ์ด๋ผ๋ ๊ฒ์ ์๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ํ์ฌ์ ๋๊ตญ์ ์ฝ๊ฐ ๋๋์ต๋๋ค.
ํํฌ์ ๊ด๋ จํ์ฌ ๋ด ๊ฒฌํด๋ Flutter๊ฐ @rrousselGit ์์ ์ ๊ณตํ๋ ํน์ ํํฌ ์๋ฃจ์ ์ด ๋ฐ๋์ ํ์ํ ๊ฒ์ ์๋์ง๋ง ๊ทธ๋ ๋ค๊ณ ๋งํ์ง๋ ์๋๋ค๋ ๊ฒ์ ๋๋ค. Remi์ ๋ค๋ฅธ ์ง์ง์๋ค์ด ์ธ๊ธํ ๋ชจ๋ ์ด์ ๋๋ฌธ์ Flutter๋ ํํฌ์ ์ ์ฌํ ์ด์ ์ ์ ๊ณตํ๋ ์๋ฃจ์ ์ด ํ์ํฉ๋๋ค. @emanuel-lundman์ ์์ ์ฃผ์ฅ์ ์ ์์ฝํ์ผ๋ฉฐ ๋๋ ๊ทธ์ ๊ฒฌํด์ ๋์ํฉ๋๋ค.
๋์ผํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๋ค๋ฅธ ์คํ ๊ฐ๋ฅํ ์ ์์ด ์๊ณ ํํฌ๊ฐ React์์ ์ ์ ์ฆ๋ ์ค์ ์ ๊ฐ๊ณ ์๊ณ Flutter๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ์ ์๋ ๊ธฐ์กด ์๋ฃจ์ ์ด ์๋ค๋ ์ฌ์ค์ ๊ฐ์ํ ๋ ์ ์๊ฐ์๋ ๊ทธ๋ ์ง ์์ ๊ฒ์ ๋๋ค. ๊ทธ๋ ๊ฒ ํ๋ ๊ฒ์ ๋์ ์ ํ์ ๋๋ค. ํํฌ ๊ฐ๋ ์ Flutter SDK(๋๋ ๊ทธ ์ดํ)์๋ ํฌํจ๋ ํ๋ฆฌ๋ฏธํฐ๋ธ๋ก์ Flutter์์ ์ด๋ค ๊ฒ๋ ๋นผ์์ ๊ฐ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ์ ์๊ฐ์๋ Flutter๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ํ๋ถํ๊ฒ ๋ง๋ค๊ณ ์ ์ง ๊ด๋ฆฌ ๊ฐ๋ฅํ๊ณ ์ฆ๊ฑฐ์ด ์ฑ์ ํจ์ฌ ๋ ์ฝ๊ฒ ๊ฐ๋ฐํ ์ ์์ ๊ฒ์ ๋๋ค.
ํํฌ๊ฐ ํํ์ ๋ฐ๊ณ ์ ํ๋ ์ฌ๋๋ค์ ์ํ ํจํค์ง๋ก ์ ๊ณต๋๋ค๋ ์ฃผ์ฅ์ ์ผ๋ฆฌ๊ฐ ์๋ ๋ง์ด์ง๋ง, ํํฌ์ ๊ฐ์ ์์์ ์ธ ๊ฒฝ์ฐ์๋ ์ ํฉํ์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ฌ๊ธฐ ์ด์ ๊ฐ ์์ต๋๋ค.
๋ด๋ถ์ ์ผ๋ก ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ํจํค์ง๋ฅผ ๋ง๋ค ๋ ์ฐ๋ฆฌ๋ ์ข ์ข Dart+Flutter SDK์๋ง ์์กดํ ์ ์๋ค๋ ์ ์์ ํจํค์ง๊ฐ "์์"ํด์ผ ํ๋์ง ๋๋ ๊ทธ ์์ ๋ค๋ฅธ ํจํค์ง๋ฅผ ํ์ฉํ๋์ง ์ฌ๋ถ์ ๋ํด ํ ๋ก ํฉ๋๋ค. ๊ฒ. ์ฌ์ง์ด Provider๋ "์์ํ" ํจํค์ง๋ฅผ ์ํด ๋์ค์ง๋ง ์ข ์ข ๋ ๋์ ์์ค์ ํจํค์ง๋ฅผ ์ํด ํ์ฉ๋ฉ๋๋ค. ์ฑ์ ๊ฒฝ์ฐ ์ด๋ค ํจํค์ง๊ฐ ๊ด์ฐฎ์์ง ์๋์ง์ ๋ํ ๋์ผํ ๋ ผ์์ด ํญ์ ์์ต๋๋ค. ๊ณต๊ธ์๋ ๋ น์์ด์ง๋ง Hooks์ ๊ฐ์ ๊ฒ์ ์ฌ์ ํ โโํจํค์ง๋ก ๋ฌผ์ํ์ ๋๋ค.
์๋ฃจ์ ๊ณผ ๊ฐ์ ํํฌ๊ฐ SDK์ ์ผ๋ถ์ธ ๊ฒฝ์ฐ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ถ๋ช ํ ์ ํ์ด ๋ ๊ฒ์ ๋๋ค. Hooks๋ฅผ ์ฌ์ฉํ๊ณ ์ด๋ฏธ ํจํค์ง๋ก ํ์ฉํ๊ณ ์ถ์ง๋ง, ์ด๊ฒ์ด Flutter ์ฝ๋ ์คํ์ผ์ ์์ฑํ๊ณ ์ด๋ฅผ ์ฌ์ฉํ์ง ์๋ Flutter ๊ฐ๋ฐ์์๊ฒ ์ต์ํ์ง ์์ ์ ์๋ ๊ฐ๋ ์ ๋์ ํ๋ ๊ฒ๋ ๊ฑฑ์ ๋ฉ๋๋ค. SDK์์ ์ง์ํ์ง ์๊ณ ์ด ๊ธธ์ ๊ฐ๋ค๋ฉด ๊ฐ๋ฆผ๊ธธ ๊ฐ์ ๋๋์ด ๋ญ๋๋ค. ์๊ท๋ชจ ๊ฐ์ธ ํ๋ก์ ํธ์ ๊ฒฝ์ฐ Hooks๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ฌ์ด ์ ํ์ ๋๋ค. Riverpod์ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
(์ ํฌ ํจํค์ง ๋ณด์์ฃผ์๋ ๊ณผ๊ฑฐ์ ๋ค๋ฅธ ํจํค์ง ๊ด๋ฆฌ์์ ๋ํ ํจํค์ง ๋ฐ ์ข ์์ฑ ์๋ง์ผ๋ก ์ธํด ํ์์ ์ ์๊ธฐ ๋๋ฌธ์ ์๋ง๋ ๊ณ ์ ํ์ง ์์ ๊ฒ์ ๋๋ค.)
์ง๊ธ๊น์ง ์ ์ผํ๊ฒ ์๋ํ๋ ์์ฐ๋ ์๋ฃจ์ ์ด๋ผ ํ ์ง๋ผ๋ ํํฌ๊ฐ ํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์ ์ผํ ๋ฐฉ๋ฒ์ด ๋ ๊ฒ์ด๋ผ๊ณ ๋งํ๋ ๊ฒ์ ์๋๋๋ค. ์๋ฃจ์ ์ ์ปค๋ฐํ๊ธฐ ์ ์ ๋ณด๋ค ์ผ๋ฐ์ ์ธ ์์ค์์ ์ต์ ์ ์กฐ์ฌํ๋ ๊ฒ์ ํ์คํ ํฅ๋ฏธ๋กญ๊ณ ์ ํจํ ์ ๊ทผ ๋ฐฉ์์ผ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๊ธฐ ์ํด์๋ Flutter SDK๊ฐ _ํ์ฌ ์ฝ๊ฒ ์ฌ์ฌ์ฉํ ์ ์๋ ์ํ ๋ ผ๋ฆฌ์ ๊ด๋ จํ์ฌ ๊ฒฐํจ์ด ์์์ ์ธ์ํด์ผ ํฉ๋๋ค. ์ด๋ ์ ๊ตํ ์ค๋ช ์๋ ๋ถ๊ตฌํ๊ณ ํ์ฌ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ ์๊ฒ๋ Hooks๋ฅผ ํต์ฌ ํ๋ ์์ํฌ์ ๋ฃ์ง ์๋ ๋ ๊ฐ์ง ์ฃผ์ ์ด์ ๊ฐ ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ๋ API์ ์ํํ ํจ์ ์ด ์๋ค๋ ๊ฒ์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์๋ชป๋ ์์๋ก ํํฌ๋ฅผ ์ด๋ป๊ฒ๋ ํธ์ถํ๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด๊ฒ์ ๋์๊ฒ ์น๋ช ์ ์ธ ๋ฌธ์ ์ฒ๋ผ ๋ณด์ธ๋ค. ๊ท์จ์ ๋ฐ๋ฅด๊ณ ๋ฌธ์๋ฅผ ๋ฐ๋ฅด๋ฉด ํผํ ์ ์์ง๋ง ์ด ์ฝ๋ ์ฌ์ฌ์ฉ ๋ฌธ์ ์ ๋ํ IMHO์ ์ข์ ์๋ฃจ์ ์๋ ๊ทธ๋ฐ ๊ฒฐํจ์ด ์๋ค๋ ๊ฒ์ ์ดํดํฉ๋๋ค.
๋ ๋ฒ์งธ๋ ์ฌ๋๋ค์ด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Hooks(๋๋ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ)๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ด์ ๊ฐ ์์ด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค. ์ด์ ์ฌ๋๋ค์ด ๋ ผ์ํ ๊ฒ์ฒ๋ผ Hooks๋ ํนํ ์๋ํ์ง ์์ต๋๋ค. ์๋ํ๋ฉด Hooks๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ฌ๋๋ค์ด ๊ด๋ จ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ hooks๋ฅผ ์ง์ํ๊ธฐ๋ฅผ ๋ฐ๋ ๋งํผ ์ถฉ๋ถํ ๋ถ๋ด์ค๋ฝ๊ธฐ ๋๋ฌธ์ ๋๋ค. ํ์ง๋ง ์ด ๋ฌธ์ ์ ๋ํ ์ข์ ํด๊ฒฐ์ฑ ์ ๊ทธ๋ด ํ์๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ข์ ์๋ฃจ์ ์ ๋จ๋ ์ผ๋ก ์กด์ฌํ๋ฉฐ ๋ค๋ฅธ ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ด์ ๋ํด ์ ํ์๊ฐ ์์ต๋๋ค.
์ต๊ทผ์ ํ๋ ์์ํฌ์ RestorableProperties๋ฅผ ์ถ๊ฐํ์ต๋๋ค. ๊ทธ๋ค์ด ์ฌ๊ธฐ์์ ์ด๋ป๊ฒ๋ ํ์ฉ๋ ์ ์๋์ง ๋ณด๋ ๊ฒ์ ํฅ๋ฏธ๋ก์ธ ๊ฒ์ ๋๋ค...
๋๋ ๋ถ์๊ธฐ ๋๋ ๋ฆฐํฐ๊ฐ ํด๊ฒฐํด์ผ ํ๋ ์จ๊ฒจ์ง ๋ฌธ์ ๊ฐ ์๋ API์ ๋ํด @Hixie ๊ฐ ๋์ํฉ๋๋ค. ์ฐธ์ฌ๋ฅผ ์ํ๋ ์ฌ๋์ด๋ผ๋ฉด ๋๊ตฌ๋ ์ค๊ณ ๋ฌธ์ ์ ์์ ํตํด, ์๋๋ฉด ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์๋ช ์ฃผ๊ธฐ ๊ด๋ฆฌ ๋ฌธ์ ์ ๋ํด ๋ค์ํ ์๋ฃจ์ ์ ๋ชจ์ํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด์์ ์ผ๋ก๋ ๋ Flutter์ ๊ณ ์ ํ๊ณ Flutter API๋ฅผ ํ์ฉํ๋ ๋์์ hook API๊ฐ ์ํํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ์ ๋๋ค. Vue ๋ฒ์ ์ ์์ ์ธ๊ธํ๋ฏ์ด ํํฌ ํธ์ถ ์์์ ์์กดํ์ง ์๊ธฐ ๋๋ฌธ์ ์์ํ๊ธฐ์ ์ข์ ๋ชจ๋ธ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋์ ํจ๊ป ์กฐ์ฌํ๋ ๋ฐ ๊ด์ฌ์ด ์๋ ์ฌ๋์ด ์์ต๋๊น?
@Hixie ํ์ง๋ง ์์ ฏ ๊ฐ์ ๊ตฌ์ฑ ๊ฐ๋ฅํ ๋ฐฉ์์ผ๋ก ์ํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ์ข์ ๋ฐฉ๋ฒ์ด ์๋ค๋ ๋ฌธ์ ์ ๋์ํฉ๋๊น? ๊ทธ๋์ ResuableProperties๋ฅผ ์ด๋ป๊ฒ๋ ํ์ฉํ๋ ๊ฒ์ ๋ํด ์๊ฐํ๊ธฐ ์์ํ์ต๋๊น?
์ ์๊ฒ๋ Hooks๋ฅผ ํต์ฌ ํ๋ ์์ํฌ์ ๋ฃ์ง ์๋ ๋ ๊ฐ์ง ์ฃผ์ ์ด์ ๊ฐ ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ๋ API์ ์ํํ ํจ์ ์ด ์๋ค๋ ๊ฒ์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์๋ชป๋ ์์๋ก ํํฌ๋ฅผ ์ด๋ป๊ฒ๋ ํธ์ถํ๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด๊ฒ์ ๋์๊ฒ ์น๋ช ์ ์ธ ๋ฌธ์ ์ฒ๋ผ ๋ณด์ธ๋ค. ๊ท์จ์ ๋ฐ๋ฅด๊ณ ๋ฌธ์๋ฅผ ๋ฐ๋ฅด๋ฉด ํผํ ์ ์์ง๋ง ์ด ์ฝ๋ ์ฌ์ฌ์ฉ ๋ฌธ์ ์ ๋ํ IMHO์ ์ข์ ์๋ฃจ์ ์๋ ๊ทธ๋ฐ ๊ฒฐํจ์ด ์๋ค๋ ๊ฒ์ ์ดํดํฉ๋๋ค.
ํํฌ์ ํจ๊ป ์์
ํ๊ณ ํํฌ๋ฅผ ์ฌ์ฉํ๋ ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ํจ๊ป ์์
ํ๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ์ค์ ๋ก ๊ทธ๋ ๊ฒ ํฐ ๋ฌธ์ ๊ฐ ์๋๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ๋ค์ด ํ
์ด๋ธ์ ๊ฐ์ ธ์ค๋ ๋ชจ๋ ํฐ ์ด์ (๊ฐ๋ฐ ์๋, ์ฌ์ฌ์ฉ์ฑ, ๊ตฌ์ฑ ๊ฐ๋ฅ์ฑ ๋ฐ ์ฝ๊ฒ ์ฝ์ ์ ์๋ ์ฝ๋์ ํฐ ์ด์ )๊ณผ ์ ํ ๋น๊ต๋์ง ์์ต๋๋ค.
ํํฌ๋ ํํฌ์
๋๋ค. ๋ง์น ํด๋์ค๊ฐ ํจ์๊ฐ ์๋ ํด๋์ค์ธ ๊ฒ์ฒ๋ผ ์กฐ๊ฑด๋ถ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋น์ ์ ๊ทธ๊ฒ์ ๋นจ๋ฆฌ ๋ฐฐ์๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋น์ ์ ํธ์ง์๋ ์ด ๋ฌธ์ ์ ๋ํด ๋์์ ์ค ์ ์์ต๋๋ค.
๋ ๋ฒ์งธ๋ ์ฌ๋๋ค์ด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Hooks(๋๋ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ)๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ด์ ๊ฐ ์์ด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค. ์ด์ ์ฌ๋๋ค์ด ๋ ผ์ํ ๊ฒ์ฒ๋ผ Hooks๋ ํนํ ์๋ํ์ง ์์ต๋๋ค. ์๋ํ๋ฉด Hooks๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ฌ๋๋ค์ด ๊ด๋ จ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ hooks๋ฅผ ์ง์ํ๊ธฐ๋ฅผ ๋ฐ๋ ๋งํผ ์ถฉ๋ถํ ๋ถ๋ด์ค๋ฝ๊ธฐ ๋๋ฌธ์ ๋๋ค. ํ์ง๋ง ์ด ๋ฌธ์ ์ ๋ํ ์ข์ ํด๊ฒฐ์ฑ ์ ๊ทธ๋ด ํ์๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ข์ ์๋ฃจ์ ์ ๋จ๋ ์ผ๋ก ์กด์ฌํ๋ฉฐ ๋ค๋ฅธ ๋ชจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ด์ ๋ํด ์ ํ์๊ฐ ์์ต๋๋ค.
ํํฌ๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋ถ๋ด์ค๋ฝ์ง ์์ต๋๋ค.
ํ์ฌ IMHO์์ ์ฌ์ฉํ ์ ์๋ ์๋ฃจ์
๋ณด๋ค ์ฌ์ ํ ์ฝ์ต๋๋ค(ํด๋น ๋ฌธ๊ตฌ๋ฅผ ๋ค์ ์ฌ์ฉํ๊ธฐ ์ํด ๐).
์ ๊ฐ ๊ธ์ ์๋ชป ์ดํดํ๊ณ ์๋ ๊ฒ์ผ ์๋ ์์ต๋๋ค. ํ์ง๋ง ์๋ฌด๋ ๊ทธ๋ฐ ๋ง์ ํ์ง ์์ ๊ฒ ๊ฐ์๋ฐ?
์ฌ๋๋ค์ด ํํฌ ์๋ฃจ์
์ด ํ
์ด๋ธ์ ๊ฐ์ ธ๋ค์ฃผ๋ ๋ชจ๋ ์ด์ ์ ์ ๋ง๋ก ๊ฐ์ฌํ๊ฒ ์ฌ๊ธฐ๊ณ ๋ชจ๋ ๊ณณ์์ ์ฌ์ฉํ ์ ์๊ธฐ๋ฅผ ๋ฐ๋ผ๋ ๊ฒ์ฒ๋ผ ์ฝ์์ต๋๋ค. ๋ชจ๋ ํํ์ ๋๋ฆฌ๊ธฐ ์ํด. ํํฌ๋ ์ฌ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ํ์ฌ ๊ฐ๋ฐ์๊ฐ ์์ ์ ๋ํผ๋ฅผ ์์ฑํ์ง ์๊ณ ๋ ์์ ์ ํํฌ๋ฅผ ์ฝ๋ฉํ๊ณ ๋ฐฐ์กํ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์
๋๋ค. ์ํ ๋
ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๋ค๋ ์ด์ ์ ์ป์ผ์ญ์์ค.
@rrousselGit ๊ณผ @gaearon ์ด ์ด๋ฏธ ์์์ ์ธ ๊ฒ์ ์ค๋ช
ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋์ ๋๋ ๊ทธ๊ฒ์ ๋ค์ด๊ฐ์ง ์์ ๊ฒ์ด๋ค.
์๋ง๋ ์ด ๊ธ์ด ์ฌ๋๋ค์ด ์ด ์ค๋ ๋์ ์์ฑํ ๋ด์ฉ์ ์ ์์ฝํ ๊ฒ์ธ์ง ์ ์ ์๊ธฐ ๋๋ฌธ์ ์ดํดํ์ง ๋ชปํ ์๋ ์์ต๋๋ค. ์ฃ์กํฉ๋๋ค.
์์ผ๋ก ๋ฐฉ๋ฒ์ด ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๊ทธ๋ฌ๋ ์ ์ด๋ ์ด๊ฒ์ด ๋ฌธ์ ๋ผ๋ ๋ฐ ๋์ํ๊ณ ํํฌ๊ฐ ํ
์ด๋ธ ์์ ์์ง ์์ ๊ฒ ๊ฐ๊ธฐ ๋๋ฌธ์ ๋ ๋์ ๋์ฒด ์๋ฃจ์
์ ์๊ฐํด ๋ด์ผ ํ ๋๋ผ๊ณ ์๊ฐํฉ๋๋ค.
์๋๋ฉด ๊ทธ๋ฅ ํ๋ฌํฐ ์ฝ์ด์์ ๋ฌธ์ ์์ ์ ๊ฑด๋๋ฐ๊ธฐ๋ก ๊ฒฐ์ ํ์ญ์์ค.
๋๊ฐ ์์ผ๋ก์ ๊ธธ์ ๊ฒฐ์ ํฉ๋๊น?
๋ค์ ๋จ๊ณ๋ ๋ฌด์์
๋๊น?
์ด๊ฒ์ ๋์๊ฒ ์น๋ช ์ ์ธ ๋ฌธ์ ์ฒ๋ผ ๋ณด์ธ๋ค. ๊ท์จ์ ๋ฐ๋ฅด๊ณ ๋ฌธ์๋ฅผ ๋ฐ๋ฅด๋ฉด ํผํ ์ ์์ง๋ง ์ด ์ฝ๋ ์ฌ์ฌ์ฉ ๋ฌธ์ ์ ๋ํ IMHO์ ์ข์ ์๋ฃจ์ ์๋ ๊ทธ๋ฐ ๊ฒฐํจ์ด ์๋ค๋ ๊ฒ์ ์ดํดํฉ๋๋ค.
React์์๋ ์ ์ ๋ถ์์ธ linter๋ฅผ ์ฌ์ฉํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ๊ฒฝํ์ ์ด ๊ฒฐํจ์ ๋๊ท๋ชจ ์ฝ๋๋ฒ ์ด์ค์์๋ ์ค์ํ์ง ์์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ๊ฒฐํจ์ผ๋ก ๊ฐ์ฃผํ ์ ์๋ ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ์์ง๋ง ์ง์ ํธ์ถ ์์์ ์์กดํ๋ ๊ฒ์ด ์ฌ๋๋ค์ด ์ง๊ด์ ์ผ๋ก ๋ฌธ์ ๊ฐ ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ ๋ฐ๋ฉด ๊ท ํ์ ์ค์ ๋ก๋ ์๋นํ ๋ค๋ฅด๋ค๋ ์ ์ ์ง์ ํ๊ณ ์ถ์์ต๋๋ค.
๋ด๊ฐ ์ด ๋๊ธ์ ์ฐ๋ ์ง์ง ์ด์ ๋ Flutter๊ฐ ์ปดํ์ผ๋ ์ธ์ด๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋๋ค. "๋ฆฐํ "์ ์ ํ ์ฌํญ์ด ์๋๋๋ค. ๋ฐ๋ผ์ ํธ์คํธ ์ธ์ด์ UI ํ๋ ์์ํฌ ์ฌ์ด์ ์ ๋ ฌ์ด ์์ผ๋ฉด "์กฐ๊ฑด๋ถ" ๋ฌธ์ ๊ฐ ์ ์ ์ผ๋ก ๋ฐ์ํ์ง ์๋๋ก ๊ฐ์ ํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ UI ํ๋ ์์ํฌ๊ฐ ์ธ์ด ๋ณ๊ฒฝ(์: Compose + Kotlin)์ ๋๊ธฐ๋ฅผ ๋ถ์ฌํ ์ ์๋ ๊ฒฝ์ฐ์๋ง ์๋ํฉ๋๋ค.
@Hixie ํ์ง๋ง ์์ ฏ ๊ฐ์ ๊ตฌ์ฑ ๊ฐ๋ฅํ ๋ฐฉ์์ผ๋ก ์ํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ์ข์ ๋ฐฉ๋ฒ์ด ์๋ค๋ ๋ฌธ์ ์ ๋์ํฉ๋๊น? ๊ทธ๋์ ResuableProperties๋ฅผ ์ด๋ป๊ฒ๋ ํ์ฉํ๋ ๊ฒ์ ๋ํด ์๊ฐํ๊ธฐ ์์ํ์ต๋๊น?
๊ทธ๊ฒ์ ํ์คํ ์ฌ๋๋ค์ด ์ ๊ธฐํ ๊ฒ์ ๋๋ค. ๊ทธ๊ฒ์ ๋ด๊ฐ ๋ณธ๋ฅ์ ์ผ๋ก ๊ฒฝํํ ๊ฒ์ด ์๋๋๋ค. Flutter๋ก ๋ด ์์ ์ ์ฑ์ ์์ฑํ ๋ ๋ฌธ์ ๋ผ๊ณ ๋๋ ๊ฒ์ ์๋๋๋ค. ๊ทธ๋ ๋ค๊ณ ํด์ ์ผ๋ถ ์ฌ๋๋ค์๊ฒ ์ค์ ๋ฌธ์ ๊ฐ ๋์ง ์๋๋ค๋ ์๋ฏธ๋ ์๋๋๋ค.
ํํฌ๋ ์ฌ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ํ์ฌ ๊ฐ๋ฐ์๊ฐ ์์ ์ ๋ํผ๋ฅผ ์์ฑํ์ง ์๊ณ ๋ ์์ ์ ํํฌ๋ฅผ ์ฝ๋ฉํ๊ณ ๋ฐฐํฌํ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
์ ์์ ์ ์ฌ๊ธฐ์์ ์ข์ ์๋ฃจ์ ์ ๋ํผ๋ฅผ ์์ฑํ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค.
๋ค์ ๋จ๊ณ๋ ๋ฌด์์ ๋๊น?
์๋ฅผ ๋ค์ด ๋ค์ ๋จ๊ณ๊ฐ ๋ง์ด ์์ต๋๋ค.
์ด ๋ฌธ์ ์ค๋ ๋๋ ๋งค์ฐ ํฅ๋ฏธ๋กญ๊ฒ ์ฝ์์ผ๋ฉฐ ๊ด์ ์ ๊ตํ์ด ์ฌ์ ํ ์๋ฏผ์ ์ด๋ผ๋ ๊ฒ์ ์๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค.
๋๋ ๊ทธ ๋ ๋ฌด๋กํ ์ค๋ ๋๊ฐ ์ด๋ป๊ฒ ์๊ฒผ๋์ง๋ณด๊ณ ์ถ์ง ์์ต๋๋ค. ์ด ์ค๋ ๋์๋ ๊ณต๊ฐ์ด ๋๋ฌด ์ ์ด์ ์์์ ์ฝ๊ณ ๋ฐ๋ผ๊ฐ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.
์ ์์ ์ ์ฌ๊ธฐ์์ ์ข์ ์๋ฃจ์ ์ ๋ํผ๋ฅผ ์์ฑํ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค.
ํ์ง๋ง ๋ํผ๋ฅผ ์์ฑํ ํ์๋ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ต์ํด์ง ์์ ์ ์ฝ๋์์ ์ด์ ๊ณผ ์ฌ์ฌ์ฉ์ฑ์ ์ป๊ณ ์ถ์ ์๋ ์์ต๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ํํฌ ๋ํ ์ฌ๋ฃ๋ฅผ ์์ฑํ๋ ๊ฒฝ์ฐ(๊ฐ๋ฅํ ๊ฒฝ์ฐ) ์ด๋ ๋ถ๋ด์ด๋ผ๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ด ์๋๋ผ ๋์๋ณด๋ค ๋ซ๋ค๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ผ ์ ์์ต๋๋ค.
์ด๊ฒ์ ์ค์ ๋ก ์ข์ ์ด์ ์ด๋ฉฐ ์ด ์ค๋ ๋์ ๋ฌธ์ ์ ๋ํ ์๋ฃจ์ ์ด ํต์ฌ์ ์ธ ์ด์ ๋ฅผ ์ธ๊ธํ ์ด์ ์ ๋๋ค. ์ฝ์ด์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๊ตฌ์ฑ ๊ฐ๋ฅํ ์ํ ๋ ผ๋ฆฌ ์๋ฃจ์ ์ ์ด๋ฌํ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ ผ๋ฆฌ๊ฐ ์ข ์์ฑ์ ์ถ๊ฐํ์ง ์๊ณ ๋ชจ๋ ํจํค์ง์ ์์ ํ๊ฒ ๋ฐฐ์ก๋ ์ ์๊ธฐ ๋๋ฌธ์ ์ฌ๋๋ค์ด ๋ํผ๋ฅผ ์์ฑํ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์ฝ์ด์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๊ตฌ์ฑ ๊ฐ๋ฅํ ์ํ ๋ ผ๋ฆฌ ์๋ฃจ์ ์ ์ด๋ฌํ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ ผ๋ฆฌ๊ฐ ์ข ์์ฑ์ ์ถ๊ฐํ์ง ์๊ณ ๋ชจ๋ ํจํค์ง์ ์์ ํ๊ฒ ๋ฐฐ์ก๋ ์ ์๊ธฐ ๋๋ฌธ์ ์ฌ๋๋ค์ด ๋ํผ๋ฅผ ์์ฑํ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
๋ด๊ฐ ๋งํ๋ ค๋ ์์ ์ IMHO๊ฐ ์ข์ ์๋ฃจ์ ์ ์ฌ์ฉํ๋ ค๋ฉด _์๋ฌด๋_๊ฐ ํด๋น ๋ ผ๋ฆฌ๋ฅผ ์์ฑํ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ฌ์ฌ์ฉํ ์ค๋ณต ๋ ผ๋ฆฌ๊ฐ ์์ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ์ด์ ์ "fetchUser" ์์ ๋ฅผ ๋ณด๋ฉด ์๋ฌด๋ "fetchUser" ํจ์๋ฅผ ํธ์ถํ๊ธฐ ์ํด ํํฌ ๋๋ ์ด์ ๋๋ฑํ ๊ฒ์ ์์ฑํ ํ์๊ฐ ์์ผ๋ฉฐ "fetchUser" ํจ์๋ฅผ ์ง์ ํธ์ถํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ์ ์ฌํ๊ฒ "fetchUser"๋ ํํฌ(๋๋ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ๋ชจ๋ ๊ฒ)์ ๋ํด ์๋ฌด๊ฒ๋ ์ ํ์๊ฐ ์๊ณ ํํฌ(๋๋ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ๋ชจ๋ ๊ฒ)๋ "fetchUser"์ ๋ํด ์๋ฌด๊ฒ๋ ์ ํ์๊ฐ ์์ต๋๋ค. ํํฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ์ฌ์ํ ๋ ผ๋ฆฌ๋ฅผ ์์ฑํ๋ ๋์ ์ ์งํฉ๋๋ค.
ํ์ฌ ์ ํ ์ฌํญ์ ํํฌ๊ฐ ์ธ์ด ์ ํ ์ฌํญ ์์ ์๋ ํจ์น๋ผ๋ ์ฌ์ค๋ก ์ธํด ๋ฐ์ํฉ๋๋ค.
์ผ๋ถ ์ธ์ด์์ ํํฌ๋ ๋ค์๊ณผ ๊ฐ์ ์ธ์ด ๊ตฌ์กฐ์ ๋๋ค.
state count = 0;
return RaisedButton(
onPressed: () => count++,
child: Text('clicked $count times'),
)
์ด๋ ํธ์ถ ๊ฐ์ ์ผ๋ถ ์ํ๋ฅผ ์ ์งํ ์ ์๋ ๋น๋๊ธฐ /๋๊ธฐํ ํจ์์ ๋ณํ์ ๋๋ค.
์ธ์ด์ ์ผ๋ถ๋ก ์ ํ์ด ์๋ ์ค ๋ฒํธ๋ก ๊ฐ ๋ณ์๋ฅผ ๊ตฌ๋ณํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ ์ด์ ์กฐ๊ฑด ์๋ ์ฌ์ฉ์ด ํ์ํ์ง ์์ต๋๋ค.
ํํฌ ์ ํ ์ฌํญ์ --track-widget-creation ์ ํ ์ฌํญ๊ณผ ์ ์ฌํ๋ค๊ณ ๋ง๋ถ์ ๋๋ค.
์ด ํ๋๊ทธ๋ ์์ ฏ์ ๋ํ const ์์ฑ์ ์ ๊ทํ๋ฅผ ์ค๋จํฉ๋๋ค. ๊ทธ๋ฌ๋ ์์ ฏ์ ์ ์ธ์ ์ด๋ฏ๋ก ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
๊ทธ๋ฐ ์๋ฏธ์์ ํํฌ๋ ๋์ผํฉ๋๋ค. ์ ํ ์ฌํญ์ ์ ์ธ์ ์ผ๋ก ์กฐ์๋๋ฏ๋ก ์ค์ ๋ก ์ค์ํ์ง ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ๋ค๋ฅธ ๊ฒ์ ์ฝ์ง ์๊ณ ๋ ํ๋์ ๋งค์ฐ ํน์ ํ ํํฌ๋ฅผ ์ป์ง ๋ชปํ ๊ฒ์
๋๋ค.
fetchuser ์์ ๊ฐ ์ด์์ ์ธ ์์ ๊ฐ ์๋ ์๋ ์์ต๋๋ค.
๊ทธ๋ฌ๋ useStream, useAnimstion ๋๋ useStreamCinroller๋ ์์ ฏ ํธ๋ฆฌ๋ฅผ ํจ์ฌ ๋ ๊น๋ํ๊ฒ ๋ง๋ค๊ณ dudChangeDependencues๋ฅผ ์ฒ๋ฆฌํ๊ฑฐ๋ ์ฒ๋ฆฌํ๋ ๊ฒ์ ์์ด๋ฒ๋ฆฌ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค.
๋ฐ๋ผ์ ํ์ฌ ๋ฐฉ์์ ํจ์ ์ ๋น ์ง ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ํธ์ถ ์ํ์ค์ ์ ์ฌ์ ์ธ ๋ฌธ์ ๋ ๊ทธ๋ณด๋ค ๋ ํฐ ๋ฌธ์ ๋ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
๋ด ์์ ์ ํํฌ๋ฅผ ์์ฑํ๊ธฐ ์์ํ ์ง ํ์คํ์ง ์์ง๋ง ํ๋ ์์ํฌ ๋ด์์ ์ฌ์ฉํ ์ค๋น๊ฐ ๋ ์์ฃผ ํ์ํ ์ปฌ๋ ์
์ด ์์ผ๋ฉด ์ข์ ๊ฒ์
๋๋ค.
๊ทธ๊ฒ์ ๊ทธ๋ค์ ์ฒ๋ฆฌํ๋ ๋์์ ์ธ ๋ฐฉ๋ฒ์ผ ๋ฟ์
๋๋ค.
@Hixie , ์ค๋ช ํ๋ ค๋ ๋ด์ฉ์ ํ์ ํ์ง ๋ชปํด ์ ๋ง ์ฃ์กํฉ๋๋ค. ๋ฆ์ ์ ๋ ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง ์๋ง ์ ๋ง ๊ทธ๋ฐ ๊ฒ ๊ฐ์ต๋๋ค ๐ณ.. ํ์ง๋ง ์ค๋ช ํ๋ ์ข์ ์๋ฃจ์ ์์ ์ํ ๊ฐ์ ์ด๋์ ๋ฌธ์ ์ ๋ํ ์๋ฃจ์ ์ด ์์ ฏ ๊ฐ์ ์ฝ๊ฒ ๊ตฌ์ฑ ๋ฐ ๊ณต์ ํ ์ ์๋๋ก ๋ํ/์บก์ํํ๋ ์ํ ๋น์ฆ๋์ค ๋ ผ๋ฆฌ ๋ฐ ์๋ช ์ด๋ฒคํธ ๋ ผ๋ฆฌ๊ฐ ์์ต๋๊น? ์ข์ ์๋ฃจ์ ์ ๊ธฐ๋ฅ๊ณผ ์ด์์ ์ผ๋ก ์๋ํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ ์ค๋ช ํด ์ฃผ์๊ฒ ์ต๋๊น?
์ฌ๊ธฐ์ ์ฝ๊ฐ ๋ผ์ด๋ค์ด ์ด ํ ๋ก ์ ์์์ ๋ํ ์ธ๊ธ์ด ์์์ ํ์ธํฉ๋๋ค. ์ ๋ ๊ฐ์ธ์ ์ผ๋ก ์ฌ๊ธฐ ์๋ ๋๊ตฐ๊ฐ๊ฐ ๋ฌด๋กํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
์ฆ, ์ด๊ฒ์ด ์ฌ๋๋ค์ด ๋ชจ๋ ๋ฉด์์ ๊น์ด ๊ด์ฌ์ ๊ฐ๋ ์ฃผ์ ๋ผ๋ ์ ์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
package:provider
๋ฌธ์ ์ถ์ ๊ธฐ์ ์ํ ๊ด๋ฆฌ์ ๋ํ ์ด๋ณด์ ์ง๋ฌธ์ ์๋
๋์ ๋ต๋ณํด ์์ต๋๋ค. ๋๋ ์ด ํ์ด์ดํธ์ค ์ค ํ์๋ง ๋ฐ๋ฅด๊ณ ์๊ณ , ๋ ๋ฏธ์ ๊ทผ๋ฉด์ฑ๊ณผ ์ธ๋ด์ฌ์ ๊ฒฝ์๋ฅผ ํํ ์๋ฐ์ ์๋ค.์ด ํ ๋ก ์ ๋ชจ๋ ๋น์ฌ์๊ฐ ์์ ์ด ํ๋ ์ผ์ ๋ํด ๋ ผ์ํ ์ถฉ๋ถํ ์ด์ ๊ฐ ์์์ด ๋ถ๋ช ํฉ๋๋ค. ๋ฉ์์ง๋ฅผ ์ ๋ฌํ๋ ๋ฐ ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ ๊ฒ๋ ์ดํดํ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ํ ๋ก ์ด ์ฌ๊ธฐ์์๋ ๋ค๋ฅธ ํ์์ผ๋ก๋ ๊ณ์๋๋ค๋ฉด ๊ธฐ์ ๊ฒ์ ๋๋ค. ๊ณต์ ๋ฌธ์์ ๊ฐ์ด ์ด๋ค ์์ผ๋ก๋ ๋์์ด ๋๋ค๋ฉด ์๋ ค์ฃผ์ธ์.
๋ฐ๋ฉด์ ์ฌ๋๋ค์ด ์ฌ๊ธฐ ํ ๋ก ์ด ์์ ์กํ์ง ์๋๋ค๊ณ ์๊ฐํ๋ค๋ฉด ์ ์ ๋ฉ์ถ๊ณ ๋ ๋์ ์์ฌ ์ํต ๋ฐฉ๋ฒ์ด ์๋์ง ๋ด ์๋ค.
(๋ฐ๋ก ์ด ํ ๋ก ์ ์ฐธ์ฌ ํด์ฃผ์ @gaearon ์๊ฒ ์ ํ๊ณ ์ถ์ต๋๋ค . ์ด ์ ์์ React์ ๊ฒฝํ์ ๋งค์ฐ ์์คํฉ๋๋ค.)
@emanuel-lundman
๊ทธ๋ฌ๋ ๋น์ ์ด ์ค๋ช ํ๋ ์ข์ ์๋ฃจ์ ์์ ๋ฌธ์ ์ ๋ํ ์๋ฃจ์ ์ด ์์ ฏ ๊ฐ์ ์ฝ๊ฒ ๊ตฌ์ฑํ๊ณ ๊ณต์ ํ ์ ์๋๋ก ๋ํ/์บก์ํํ๋ ์ํ ๊ฐ, ์ํ ๋น์ฆ๋์ค ๋ ผ๋ฆฌ ๋ฐ ์๋ช ์ด๋ฒคํธ ๋ ผ๋ฆฌ๊ฐ ์ด๋์ ์์ต๋๊น? ์ข์ ์๋ฃจ์ ์ ๊ธฐ๋ฅ๊ณผ ์ด์์ ์ผ๋ก ์๋ํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ ์ค๋ช ํด ์ฃผ์๊ฒ ์ต๋๊น?
์ ๊ฐ ์ ๋ชฐ๋ผ์ ์์ธํ ๋ง์์ ๋๋ฆฌ์ง ๋ชปํด์ ์ฃ์กํฉ๋๋ค. :-)
@escamoteur
fetchuser ์์ ๊ฐ ์ด์์ ์ธ ์์ ๊ฐ ์๋ ์๋ ์์ต๋๋ค.
๊ทธ๋ฌ๋ useStream, useAnimstion ๋๋ useStreamCinroller๋ ์์ ฏ ํธ๋ฆฌ๋ฅผ ํจ์ฌ ๋ ๊น๋ํ๊ฒ ๋ง๋ค๊ณ dudChangeDependencues๋ฅผ ์ฒ๋ฆฌํ๊ฑฐ๋ ์ฒ๋ฆฌํ๋ ๊ฒ์ ์์ด๋ฒ๋ฆฌ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค.
์ด ๋ฌธ์ ์ ์ด๋ ค์ ์ค ํ๋๋ ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๊ณ ๋ถ์ํ ๋ ๋ฌธ์ ๋ฅผ ์ค์ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ผ๋ก ์น๋ถํ๊ณ ์๋ก์ด ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๋ ๋ฑ์ "๊ณจ๋ ์ด๋"์ด์์ต๋๋ค. ์ค์ ๋ก ์ ์ฉํ ์ ์๋ ๊ฒ์ ๋ฌธ์ ์ ์ค์ ์๊ฐ ์๋ ๋ฐ๋ชจ Flutter ์์ฉ ํ๋ก๊ทธ๋จ๊ณผ ๊ฐ์ด ์ค๋ช ์ ์ํด ์ง๋์น๊ฒ ๋จ์ํ๋์ง ์์ ๋ช ๊ฐ์ง ์ ์ ์๋ฅผ ์ ์ํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฐ ๋ค์ Hooks ๋ฐ ๊ธฐํ ์ ์์ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ๋ค์ ๊ตฌํํ๊ณ ๊ตฌ์ฒด์ ์ธ ์ฉ์ด๋ก ์๋ก์ ๋ํด ์ค์ ๋ก ํ๊ฐํ ์ ์์ต๋๋ค. (๋ฌธ์ ๊ฐ ๋ฌด์์ธ์ง ์ ํํ ์ดํดํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ๋ฅผ ์ ์ธํ๊ณ ๋ ์ง์ ์ด ์์ ์ ์ํํ ๊ฒ์ด๋ฏ๋ก Hooks๋ฅผ ์นํธํ๋ ์ฌ๋์ด ์ํํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๋ค.)
์ค์ ๋ก ์ ์ฉํ ์ ์๋ ๊ฒ์ ๋ช ๊ฐ์ง ์ ์ ์๋ฅผ ์ ์ํ๋ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด ์ค๋ช ์ ์ํด ์ง๋์น๊ฒ ๋จ์ํ๋์ง ์์ ๋ฌธ์ ์ ์ค์ ์๊ฐ ์๋ ๋ฐ๋ชจ Flutter ์ ํ๋ฆฌ์ผ์ด์
๋ด๊ฐ ์ฌ๊ธฐ์ ์ ์ํ ์์ ๋ํด ์ด๋ป๊ฒ ์๊ฐํฉ๋๊น? https://github.com/flutter/flutter/issues/51752#issuecomment -669626522
์ด๊ฒ์ ์ค์ ์ฝ๋ ์ค๋ํซ์ ๋๋ค.
์ข์ ์์์ด ๋ ๊ฒ ๊ฐ์์. ํํฌ๋ฅผ ์ฌ์ฉํ์ง ์๋ ๋ฒ์ ๊ณผ ํํฌ๋ฅผ ์ฌ์ฉํ๋ ๋ฒ์ ์ผ๋ก ๋ ๋ฆฝ ์คํํ ์ฑ์ผ๋ก ์คํ๋๋ ์ํ๋ก ๋ง๋ค ์ ์์ต๋๊น?
์ฃ์กํฉ๋๋ค. ์ฑ์ด ์๋ ์ฝ๋ ์ค๋ํซ์ ์๋ฏธํ์ต๋๋ค.
"๋ฐ๋ชจ Flutter ์์ฉ ํ๋ก๊ทธ๋จ" ์์ด๋์ด์ ๋ฌธ์ ์ค ํ๋๋ ์ด ์ค๋ ๋์์ ๋ง๋ ์์ ๊ฐ ๋งค์ฐ ์ค์ ์ ์ด๋ผ๋ ๊ฒ์
๋๋ค.
๊ทธ๊ฒ๋ค์ ์ง๋์น๊ฒ ๋จ์ํ๋์ง ์์์ต๋๋ค.
ํํฌ์ ์ฃผ์ ์ฌ์ฉ ์ฌ๋ก๋ ๋๋ฐ์ด์ค, ์ด๋ฒคํธ ํธ๋ค๋ฌ, ๊ตฌ๋
๋๋ ์์์ ๋ถ์์ฉ๊ณผ ๊ฐ์ ๋ง์ดํฌ๋ก ์ํ๋ฅผ ์ธ์๋ถํดํ์ฌ ๋ ์ ์ฉํ ๋ก์ง์ ๋ฌ์ฑํ๊ธฐ ์ํด ํจ๊ป ๊ฒฐํฉ๋ฉ๋๋ค.
https://marvel.riverpod.dev/#/ ์ ๊ฐ์ Riverpod์ ๋ํ ๋ช ๊ฐ์ง ์๊ฐ ์์ต๋๋ค. ์ฌ๊ธฐ์ ์์ค ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. https://github.com/rrousselGit/river_pod/tree/master/examples/marvel/lib
๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ์ง๊ธ๊น์ง ์ธ๊ธ๋ ๊ฒ๊ณผ ํฌ๊ฒ ๋ค๋ฅด์ง ์์ ๊ฒ์
๋๋ค.
@Hixie
์ด๊ฒ์ด ์ ๋ฌธ์ ์ธ์ง ์ดํดํ๊ธฐ๊ฐ ์ ๋ง ์ด๋ ต์ต๋๋ค. ์ ๋ Flutter ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง์ด ์์ฑํ์ง๋ง ์ค์ ๋ก ๊ทธ๋ ๊ฒ ํฐ ๋ฌธ์ ๊ฐ ๋์ง ์๋ ๊ฒ ๊ฐ์ต๋๊น? ์ต์ ์ ๊ฒฝ์ฐ์๋ ์์ฑ์ ์ ์ธํ๊ณ , ์ด๊ธฐํํ๊ณ , ํ๊ธฐํ๊ณ , ๋๋ฒ๊ทธ ๋ฐ์ดํฐ์ ๋ณด๊ณ ํ๋ ๋ฐ 4์ค์ด ์์๋ฉ๋๋ค(์ค์ ๋ก๋ ์ผ๋ฐ์ ์ผ๋ก ์ด๊ธฐํํ ๋์ ๋์ผํ ์ค์์ ์ ์ธํ ์ ์๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ์ ์ผ๋ก ๋ ์ ์ต๋๋ค. ์ฑ์ ์ผ๋ฐ์ ์ผ๋ก ๋๋ฒ๊ทธ ์์ฑ์ ์ํ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๋ํด ๊ฑฑ์ ํ ํ์๊ฐ ์์ผ๋ฉฐ ์ด๋ฌํ ๊ฐ์ฒด ์ค ๋ค์๋ ํ๊ธฐํด์ผ ํ๋ ์ํ๊ฐ ์์ต๋๋ค.
๋๋ ๊ฐ์ ๋ฐฐ์ ์๋ค.
์ ๋ ์ฌ๊ธฐ์ ์ค๋ช
๋ ๋ฌธ์ ๋ฅผ ์ ์ดํดํ์ง ๋ชปํ๋ค๋ ์ ์ ์ธ์ ํฉ๋๋ค. ๋๋ ์ฌ๋๋ค์ด ์ฌ์ฌ์ฉํ ํ์๊ฐ ์๋ "์ํ ๋
ผ๋ฆฌ"๊ฐ ๋ฌด์์ธ์ง ์ดํดํ์ง ๋ชปํฉ๋๋ค.
๋๋ ๋ง์ ์ํ ์ ์ฅ ์์ ์์ ฏ์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ ์ผ๋ถ๋ ์์ญ ๊ฐ์ ์์ ํ๋๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ ํ
์คํธ ์ปจํธ๋กค๋ฌ์ ํฌ์ปค์ค ๋
ธ๋๋ฅผ ์ง์ ๊ด๋ฆฌํด์ผ ํฉ๋๋ค. statelesswidget์ ์๋ช
์ฃผ๊ธฐ ๋ฉ์๋์์ ์์ฑํ๊ณ ์ญ์ ํฉ๋๋ค. ๊ฝค ์ง๋ฃจํ์ง๋ง ๋์ผํ ์์ ์ปจํธ๋กค๋ฌ/focusNode ๋๋ ๋์ผํ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์ฌ์ฉํ๋ ์์ ฏ์ด ์์ต๋๋ค. ๊ทธ๋ค ์ฌ์ด์ ์ ์ผํ ๊ณตํต์ ์ ์ํ๊ฐ ์๊ณ ํ์์ด ๋๋ค๋ ์ผ๋ฐ์ ์ธ ๊ฐ๋
์
๋๋ค. ํจํด์ด๋ผ๊ณ ํด์ ์ฝ๋๊ฐ ๋ฐ๋ณต๋๋ ๊ฒ์ ์๋๋๋ค.
๋ด ์ฝ๋์ ๋ง์ ๋ถ๋ถ์์ ๋ฐฐ์ด์ ๋ฐ๋ณตํด์ผ ํ๋ฏ๋ก ์ฑ ๋ฐ๋ณต ์ฝ๋ ์ ์ฒด์์ "for(var thing in things)"๋ฅผ ํธ์ถํ์ง ์์ ๊ฒ์
๋๋ค.
์ ๋ ๋ผ์ดํ์ฌ์ดํด API์ ๋จ์ํจ์์ ๋น๋กฏ๋ StatefulWidget์ ํ์ ์ข์ํฉ๋๋ค. ํ ๊ฐ์ง ์์ ์ ์ํํ๊ณ ์ฑ์ ๋๋จธ์ง ๋ถ๋ถ๊ณผ ๋ถ๋ฆฌํ์ฌ ์ํํ๋ StatefulWidget์ ์์ฑํ ์ ์์ต๋๋ค. ๋ด ์์ ฏ์ "์ํ"๋ ํญ์ ์์ฒด์ ์ผ๋ก ๋น๊ณต๊ฐ์ด๋ฏ๋ก ๋ด ์์ ฏ์ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ ๋ฌธ์ ๊ฐ ๋์ง ์์ผ๋ฉฐ ์ฝ๋ ์ฌ์ฌ์ฉ๋ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
์ฌ๊ธฐ์์ ๊ฐ์ ธ์จ ์์ ์ ๊ด๋ จํ์ฌ ๋ช ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์ด๋ ๊ทํ์ ์์ ๊ณผ ์ด๋ ์ ๋ ์ผ์นํฉ๋๋ค.
์ด๊ฒ์ ๊ฐ๋ ์ฑ์ด ํ์ ํ ๋จ์ด์ง๋๋ค.
- 10๋จ๊ณ์ ๋ค์ฌ์ฐ๊ธฐ๊ฐ ์์ต๋๋ค. ํํฐ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ ์ํด
FilterBuilder
๋ฅผ ๋ง๋๋ ๊ฒฝ์ฐ 12๋จ๊ณ์ ๋๋ค.ํํฐ ๋ก์ง์ ๊ทธ๋๋ก ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์ค์๋ก
timer
์ทจ์ํ๋ ๊ฒ์ ์์ด๋ฒ๋ฆด ์ ์์ต๋๋ค.build
๋ฐฉ๋ฒ์ ์ ๋ฐ์ ๋ ์์๊ฒ ์ ์ฉํ์ง ์์ต๋๋ค. Builders๋ ์ค์ํ ๊ฒ์์ ์ฐ๋ฆฌ๋ฅผ ์ฐ๋งํ๊ฒ ํฉ๋๋ค.- ๊ดํธ๊ฐ ์์ด์ ์ฝ๋๊ฐ ์ปดํ์ผ๋์ง ์๋ ์ด์ ๋ฅผ ์ดํดํ๋ ๋ฐ 5๋ถ์ ๋ญ๋นํ์ต๋๋ค.
๊ทํ์ ์๋ Flutter์ StatelessWidget ๋ฐ State ์๋ช ์ฃผ๊ธฐ API์ ์ค์ ๋ฌธ์ ๋ผ๊ธฐ๋ณด๋ค๋ ๊ณต๊ธ์๊ฐ ์ผ๋ง๋ ์ฅํฉํ์ง, ๊ทธ๋ฆฌ๊ณ ๋ชจ๋ ๊ฒ์ ๋ํด InheritedWidgets๋ฅผ ๋จ์ฉํ๋ ๊ฒ์ด ์ ๋์์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ ๋๋ค.
@rrousselGit ๋ช ํํ์ง ์์ ๊ฒฝ์ฐ ์ฃ์กํฉ๋๋ค. ์์์ ์ ๊ฐ ์ ์ํ ๊ฒ์ ๊ตฌ์ฒด์ ์ผ๋ก ํ์ค์ ์ด๊ณ ์ค๋ช ํ๋ ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ฐ๋๋ผ Flutter ์์ฉ ํ๋ก๊ทธ๋จ(StatefulWidget ๋ฑ์ ์ฌ์ฉํ์ฌ)์ ์์ฑํ์ฌ ์ค์ ์ ์ฒด ์์ฉ ํ๋ก๊ทธ๋จ์ ๊ธฐ๋ฐ์ผ๋ก ์ ์ํ ์ ์๋๋ก ํ๋ ๊ฒ์ ๋๋ค. "fetchUser" ์์ ์ ๊ฐ์ด ์ฌ๊ธฐ์์ ๋ ผ์ํ ๊ตฌ์ฒด์ ์ธ ์์ ๋ ํญ์ "์ด๋ฐ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์๊ณ ๊ฐ๋จํ๊ณ Hooks๊ฐ ํ์ํ์ง ์์ ๊ฒ์ ๋๋ค"๋ผ๋ ๋ผ์ธ์ ๋ฐ๋ฅธ ํ ๋ก ์ผ๋ก ๋๋ฌ์ต๋๋ค. "๊ธ์์, ๊ทธ๊ฑด ์ง๋์น๊ฒ ๋จ์ํ๋์ด ์์ต๋๋ค. ์ค์ ์ธ๊ณ์์๋ Hooks๊ฐ ํ์ํฉ๋๋ค." ๊ทธ๋์ ์ ์์ ์ ์ค์ ๋ก Hooks๊ฐ ํ์ํ๊ณ ์ง๋์น๊ฒ ๋จ์ํ๋์ง ์์ ์ค์ ์์ ๋ฅผ ๋ง๋ค์ด ์ฝ๋ ์ฌ์ฌ์ฉ์ ์ด๋ ค์์ ๋ณด์ฌ์ค์ผ๋ก์จ ์๋ก์ด ์ฝ๋๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํผํ ์ ์๋์ง ์ฌ๋ถ๋ฅผ ํ์ธํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. , ๋๋ ์ ์ฝ๋๊ฐ ํ์ํ ๊ฒฝ์ฐ, ํ์์ ๊ฒฝ์ฐ Hooks์ ๊ฐ์ ๋ชจ์์ด์ด์ผ ํ๋์ง ๋๋ ๋ ๋์ ์๋ฃจ์ ์ ์ฐพ์ ์ ์๋์ง ์ฌ๋ถ.
๋๋ ์ฌ๋๋ค์ด ์ฌ์ฌ์ฉํ ํ์๊ฐ ์๋ "์ํ ๋ ผ๋ฆฌ"๊ฐ ๋ฌด์์ธ์ง ์ดํดํ์ง ๋ชปํฉ๋๋ค.
๊ทธ๋ด ์ ์์ง
์ํ ๋
ผ๋ฆฌ์ ํํ์ ์ด๋ฃจ๋ ๊ฒ์ UI ๋
ผ๋ฆฌ์ ์์ ฏ์ด ํ
์ด๋ธ์ ๊ฐ์ ธ์ค๋ ๊ฒ์
๋๋ค.
๊ธฐ์ ์ ์ผ๋ก ์์ ฏ ๋ ์ด์ด๋ฅผ ์ ๊ฑฐํ ์ ์์ต๋๋ค. ์ด ์ํฉ์์ ๋จ์ ๊ฒ์ RenderObjects์ ๋๋ค.
์๋ฅผ ๋ค์ด, ์ฐ๋ฆฌ๋ ์ต์ํ์ ์นด์ดํฐ๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค:
var counter = 0;
final counterLabel = RenderParagraph(
TextSpan(text: '$counter'),
textDirection: TextDirection.ltr,
);
final button = RenderPointerListener(
onPointerUp: (_) {
counter++;
counterLabel.text = TextSpan(text: '$counter');
},
child: counterLabel,
);
๊ทธ๊ฒ์ด ๋ฐ๋์ ๋ณต์กํ ๊ฒ์ ์๋๋๋ค. ๊ทธ๋ฌ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ์ต๋๋ค. counterLabel
๋ ๋๋ง์ ์ค๋ณต ํญ๋ชฉ์ด ์์ต๋๋ค.
์์ ฏ์ ์ฌ์ฉํ๋ฉด ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
class _CounterState exends State {
int counter = 0;
Widget build(context ) {
return GestureDetector(
onTap: () => setState(() => counter++);
child: Text('$counter'),
);
}
}
์ด๊ฒ์ด ํ ์ ์ผํ ๊ฒ์ Text
๋
ผ๋ฆฌ๋ฅผ ์ ์ธ์ ์ผ๋ก ๋ง๋ค์ด ์ธ์๋ถํดํ๋ ๊ฒ์
๋๋ค.
์ต์ํ์ ๋ณํ์
๋๋ค. ๊ทธ๋ฌ๋ ๋๊ท๋ชจ ์ฝ๋๋ฒ ์ด์ค์์ ์ด๋ ์๋นํ ๋จ์ํ์
๋๋ค.
ํํฌ๋ ๋๊ฐ์ ์ผ์ ํฉ๋๋ค.
๊ทธ๋ฌ๋ Text
๋์ ์ํ ๋
ผ๋ฆฌ์ ๋ํ ์ฌ์ฉ์ ์ ์ ํํฌ๋ฅผ ์ป์ต๋๋ค. ์ฌ๊ธฐ์๋ ๋ฆฌ์ค๋, ๋๋ฐ์ด์ฑ, HTTP ์์ฒญ ๋ง๋ค๊ธฐ ๋ฑ์ด ํฌํจ๋ฉ๋๋ค.
๊ทํ์ ์๋ Flutter์ StatelessWidget ๋ฐ State ์๋ช ์ฃผ๊ธฐ API์ ์ค์ ๋ฌธ์ ๋ผ๊ธฐ๋ณด๋ค๋ ๊ณต๊ธ์๊ฐ ์ผ๋ง๋ ์ฅํฉํ์ง, ๊ทธ๋ฆฌ๊ณ ๋ชจ๋ ๊ฒ์ ๋ํด InheritedWidgets๋ฅผ ๋จ์ฉํ๋ ๊ฒ์ด ์ ๋์์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ ๋๋ค.
์ด๊ฒ์ ๊ณต๊ธ์์ ๊ด๋ จ์ด ์์ต๋๋ค(์ด ์ฝ๋๋ ๊ฒฐ๊ตญ ๊ณต๊ธ์๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค).
์ด๋ค ๊ฒฝ์ฐ๊ฐ ์๊ธฐ ๋๋ฌธ์, ์ ๊ณต์๋ ๋ ๋์์ด context.watch
๋์ Consumer
.
ํ์ค ์๋ฃจ์
์ Consumer
๋ฅผ ValueListenableBuilder
๋ก ๋ฐ๊พธ๋ ๊ฒ์ด๋ฏ๋ก ๋๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
@Hixie ์ ๋์ํฉ๋๋ค. ํํฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ Flutter๋ง ์ฌ์ฉํ๋ ๊ฒ์ ํจ์จ์ฑ์ ๋น๊ตํ๊ธฐ ์ํด ๋ ๊ฐ์ง๋ฅผ ๋๋ํ ๋น๊ตํ ํ์๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด๊ฒ์ ๋ํ ํํฌ๊ฐ ๋ ๋์์ง ์๋์ง ๋๋ ๋ฐ๋๋ผ ์ฑ์ด ์ด ์ธ ๋ฒ์งธ ์๋ฃจ์ ์ผ๋ก ๋น๋๋ ๊ฒฝ์ฐ ๋ค๋ฅธ ์๋ฃจ์ ์ด ๋ ๋์์ง ์ฌ๋ถ๋ฅผ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ ํ์ ์ํค๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ์ด ๋ฐ๋๋ผ ์ฑ ๊ฐ๋ ์ TodoMVC ์ ๊ฐ์ ๊ฒ๋ค์ด ๋ค์ํ ํ๋ก ํธ ์๋ ํ๋ ์์ํฌ ๊ฐ์ ์ฐจ์ด์ ์ ๋ณด์ฌ์ฃผ๋ ๊ฒ๊ณผ ํจ๊ป ํ๋์ ์ฌ์ฉ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋ฐ๋์ ์๋ก์ด ๊ฒ์ ์๋๋๋ค. ์ด ์์ ์ฑ์ ๋ง๋๋ ๋ฐ ๋์์ ๋๋ฆด ์ ์์ต๋๋ค.
@satvikpendem
๊ธฐ๊บผ์ด ๋์๋๋ฆฌ๊ฒ ์ต๋๋ค.
flutter_hooks
๋ฆฌํฌ์งํ ๋ฆฌ์ ์์ ์ฑ์ ์๋ง๋ ์ฌ๋ฌ ๊ฐ์ง ๋ค๋ฅธ ํํฌ์ ์ด๋ค์ด ๋ ์ฝ๊ฒ ๋ง๋๋/๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ์ ๋ณด์ฌ์ฃผ๊ณ ์ข์ ์ถ๋ฐ์ ์ด ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๋๋ ๋ํ ์ฐ๋ฆฌ๊ฐ ์ด ํธ์ ์ ์๋ ๋ช ๊ฐ์ง ์์ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์
๋ฐ์ดํธ: ์ฝ๋๋ https://github.com/TimWhiting/local_widget_state_approaches์ ์์ต๋๋ค.
์ ์ฅ์์ ์ ์ ํ ์ด๋ฆ์ด ํ์คํ์ง ์์ผ๋ฏ๋ก ๊ทธ๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ํด๊ฒฐํ๋ ค๋ ๋ฌธ์ ๋ผ๊ณ ๊ฐ์ ํ์ง ๋ง์ญ์์ค. ์ํ ์ ์ฅ ๋ฐ ํํฌ์์ ๊ธฐ๋ณธ ์นด์ดํฐ ์ฑ์ ์ํํ์ต๋๋ค. ์ค๋ ๋ฐค ์๊ฐ์ด ๋ง์ง๋ ์์ง๋ง ๋ฌธ์ ๊ฐ ๋ ์ ์๋ ๋ถ๋ถ์ ๋ ์ ์ค๋ช
ํ๋ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋ ์ถ๊ฐํ๋ ค๊ณ ๋
ธ๋ ฅํ ๊ฒ์
๋๋ค. ๊ธฐ์ฌํ๊ณ ์ถ์ ์ฌ๋์ ์ก์ธ์ค ๊ถํ์ ์์ฒญํ์ญ์์ค.
"fetchUser" ์์ ์ ๊ฐ์ด ์ฌ๊ธฐ์์ ๋ ผ์ํ ๊ตฌ์ฒด์ ์ธ ์์ ๋ ํญ์ "์ด๋ฐ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์๊ณ ๊ฐ๋จํ๊ณ Hooks๊ฐ ํ์ํ์ง ์์ ๊ฒ์ ๋๋ค"๋ผ๋ ๋ผ์ธ์ ๋ฐ๋ฅธ ํ ๋ก ์ผ๋ก ๋๋ฌ์ต๋๋ค. "๊ธ์์, ๊ทธ๊ฑด ์ง๋์น๊ฒ ๋จ์ํ๋์ด ์์ต๋๋ค. ์ค์ ์ธ๊ณ์์๋ Hooks๊ฐ ํ์ํฉ๋๋ค."
๋๋ ๋์ํ์ง ์๋๋ค. ๋๋ "์ด๋ฐ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค"๋ ๊ฒ์ ๋ณธ ์ ์ด ์๋ค๊ณ ์๊ฐํ๊ณ ๊ฒฐ๊ณผ ์ฝ๋๊ฐ ํํฌ ๋ณํ๋ณด๋ค ๋ซ๋ค๋ ๋ฐ ๋์ํ์ต๋๋ค.
๋ด ์์ ์ ์ฐ๋ฆฌ๊ฐ ์ผ์ ๋ค๋ฅด๊ฒ ํ ์ ์์ง๋ง ๊ฒฐ๊ณผ ์ฝ๋๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ๊ณ ๊ฐ๋
์ฑ์ด ๋ฎ๋ค๋ ๊ฒ์
๋๋ค.
์ด๊ฒ์ fetchUser
์๋ ์ ์ฉ๋ฉ๋๋ค.
ํํฌ๋ ๋๊ฐ์ ์ผ์ ํฉ๋๋ค.
๊ทธ๋ฌ๋Text
๋์ ์ํ ๋ ผ๋ฆฌ์ ๋ํ ์ฌ์ฉ์ ์ ์ ํํฌ๋ฅผ ์ป์ต๋๋ค. ์ฌ๊ธฐ์๋ ๋ฆฌ์ค๋, ๋๋ฐ์ด์ฑ, HTTP ์์ฒญ ๋ง๋ค๊ธฐ ๋ฑ์ด ํฌํจ๋ฉ๋๋ค.
์๋์, ์ ๋ ์ฌ์ ํ ์ด ์ผ๋ฐ์ ์ธ ์ํ ๋ ผ๋ฆฌ๊ฐ ๋ฌด์์ธ์ง ์ดํดํ์ง ๋ชปํฉ๋๋ค. ๋ด ๋ง์ "initState/didUpdateDependency" ๋ฉ์๋์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฝ๋ ๋ง์ ์์ ฏ์ด ์์ง๋ง ์ ํํ ๋์ผํ ์ฟผ๋ฆฌ๋ฅผ ๋ง๋๋ ๋ ์์ ฏ์ ์ฐพ์ ์ ์์ผ๋ฏ๋ก "๋ ผ๋ฆฌ"๊ฐ ๋์ผํ์ง ์์ต๋๋ค.
HTTP ์์ฒญ์ ๋ง๋๋ ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ด ์์ ฏ ์ค ์ผ๋ถ๊ฐ ์ฌ์ฉํด์ผ ํ๋ ์๋น์ค ํด๋์ค ์ด๋๊ฐ์ "makeHTTPRequest(url, paramters)"๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๋ฉด ํ์ํ ๋๋ง๋ค ๋ฉ์๋๋ฅผ ์ง์ ํธ์ถํ๋ ๋์ ํํฌ๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? ์ด ๊ฒฝ์ฐ ํํฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ฐ ๋ฉ์๋ ํธ์ถ๊ณผ ์ด๋ป๊ฒ ๋ค๋ฆ ๋๊น?
์ฒญ์ทจ์. ๊ฐ์ ๊ฒ์ ๋ฃ๋ ์์ ฏ์ด ์์ต๋๋ค. ๊ฐ ์์ ฏ์ ํ์ํ ๋ชจ๋ ๊ฒ์ ๊ตฌ๋ ํ๊ณ ๊ตฌ๋ ์ ์ทจ์ํ ์ฑ ์์ด ์์ต๋๋ค. ํํฌ๋ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๊ตฌ๋ฌธ์์ ์คํ์ผ ์ ์์ง๋ง ๋ด ์์ ฏ์ ๋์ผํ ๊ฐ์ฒด ์กฐํฉ์ ์์ ํ์ง ์๊ธฐ ๋๋ฌธ์ ํํฌ๋ ์ด๋ป๊ฒ๋ "๋งค๊ฐ๋ณ์ํ"๋์ด์ผ ํฉ๋๋ค. ๋ค์ ๋งํ์ง๋ง, ํํฌ๋ ํ๋ฒํ ์ด์ ํจ์์ ์ด๋ป๊ฒ ๋ค๋ฅธ๊ฐ์?
์ด๊ฒ์ ๊ณต๊ธ์์ ๊ด๋ จ์ด ์์ต๋๋ค(์ด ์ฝ๋๋ ๊ฒฐ๊ตญ ๊ณต๊ธ์๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค).
์ด๋ค ๊ฒฝ์ฐ๊ฐ ์๊ธฐ ๋๋ฌธ์, ์ ๊ณต์๋ ๋ ๋์์ดcontext.watch
๋์Consumer
.
๋ญ? "ChatScreen" HookWidget์ด ํด๊ฒฐํด์ผ ํ๋ ๊ฒ์ ๋ํ ๋ฐ๋ก๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
<strong i="19">@override</strong>
Widget build(BuildContext context) {
return Consumer<Auth>(
provider: authProvider,
builder: (context, auth, child) {
return Consumer<int>(
provider: selectedChatProvider,
builder: (context, chatId, child) {
์ด๊ฒ์ ๊ณต๊ธ์์ ์ด๋ป๊ฒ ๊ด๋ จ์ด ์์ต๋๊น? ํผ๋์ค๋ฌ์์. ๋๋ Provider์ ์ ๋ฌธ๊ฐ๋ ์๋์ง๋ง ์ด๊ฒ์ ํ์คํ Provider๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋์ฒ๋ผ ๋ณด์ธ๋ค.
์ ๋ ์ด ๋ฌธ์ ๊ฐ ๋ณต์กํ ์ํ์ ๊ดํ ๊ฒ์ด ์๋๋ผ๋ ์ฌ์ค์ ๊ฐ์กฐํ๊ณ ์ถ์ต๋๋ค.
์ ์ฒด ์ฝ๋๋ฒ ์ด์ค์ ์ ์ฉํ ์ ์๋ ์์ ์ฆ๋ถ์ ๊ดํ ๊ฒ์
๋๋ค.
์ฌ๊ธฐ์ ์ ๊ณต๋ ์์ ์ ๊ฐ์น์ ๋์ํ์ง ์์ผ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ํ์ ์๋ฌด ๊ฒ๋ ๊ฐ์ ธ์ค์ง ์์ต๋๋ค. StatefulWidget์ผ๋ก ํ ์ ์๋ ํํฌ๋ก ํ ์ ์๋ ๊ฒ์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋์ ImplicitFetcher
์ ๊ฐ์ ๋ง์ดํฌ๋ก ์ค๋ํซ์ ๋๋ํ ๋น๊ตํ๊ณ ์ธก์ ๊ฐ๋ฅํ ๋ฉํธ๋ฆญ์ ์ฌ์ฉํ์ฌ ์ด๋ค ์ฝ๋๊ฐ ๋ ๋์์ง _๊ฐ๊ด์ ์ผ๋ก_ ๊ฒฐ์ ํ๊ณ ๋ค์ํ ์์ ์ค๋ํซ์ ๋ํด ์ํํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ด๊ฒ์ ๊ณต๊ธ์์ ์ด๋ป๊ฒ ๊ด๋ จ์ด ์์ต๋๊น? ํผ๋์ค๋ฌ์์. ๋๋ Provider์ ์ ๋ฌธ๊ฐ๋ ์๋์ง๋ง ์ด๊ฒ์ ํ์คํ Provider๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋์ฒ๋ผ ๋ณด์ธ๋ค.
์ด ์ฝ๋๋ Provider์์ ์จ ๊ฒ์ด ์๋๋ผ InheritedWidgets๋ฅผ ์ฌ์ฉํ์ง ์๋ ๋ค๋ฅธ ํ๋ก์ ํธ์์ ์จ ๊ฒ์
๋๋ค.
๊ณต๊ธ์์ Consumer
์ provider
๋งค๊ฐ๋ณ์๊ฐ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ ๊ฐ ์ธ๊ธํ๋ฏ์ด Consumer
-> ValueListenableBuilder/StreamBuilder/BlocBuilder/Observer/...
"initState/didUpdateDependency" ๋ฉ์๋์ ์์ง๋ง ์ ํํ ๋์ผํ ์ฟผ๋ฆฌ๋ฅผ ๋ง๋๋ ๋ ๊ฐ์ ์์ ฏ์ ์ฐพ์ ์ ์์ผ๋ฏ๋ก "๋ ผ๋ฆฌ"๊ฐ ๋์ผํ์ง ์์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ฌ์ฌ์ฉํ๋ ค๋ ์ํ ๋ ผ๋ฆฌ๋ "์ฟผ๋ฆฌ ์์ฑ"์ด ์๋๋ผ "x๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ฌด์์ธ๊ฐ ์ํ"์ ๋๋ค. "๋ฌด์ธ๊ฐ๋ฅผ ํ๋ผ"๋ ๋ณํ ์ ์์ง๋ง "x๊ฐ ๋ณํ ๋"๋ ์ผ๋ฐ์ ์ ๋๋ค
๊ตฌ์ฒด์ ์ธ ์:
ID๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์์ ฏ์ด HTTP ์์ฒญ์ ํ๋๋ก ํ ์ ์์ต๋๋ค.
๋ํ package:async
์ CancelableOperation์ ์ฌ์ฉํ์ฌ ๋ณด๋ฅ ์ค์ธ ์์ฒญ์ ์ทจ์ํ๋ ค๊ณ ํฉ๋๋ค.
์ด์ ์ ํํ ๋์ผํ ์์
์ ์ํํ๋ ค๋ ๋ ๊ฐ์ ์์ ฏ์ด ์์ง๋ง ๋ค๋ฅธ HTTP ์์ฒญ์ด ์์ต๋๋ค.
๊ฒฐ๊ตญ, ์ฐ๋ฆฌ๋ ๋ค์์ ๊ฐ์ง๊ณ ์์ต๋๋ค:
CancelableOperation<User> pendingUserRequest;
initState() {
pendingUserRequest = fetchUser(widget.userId);
}
didUpdateWidget(oldWidget) {
if (widget.userId != oldWidget.userId) {
pendingUserRequest.cancel();
pendingUserRequest = fetchUser(widget.userId);
}
}
dispose() {
pendingUserRequest.cancel();
}
๋:
CancelableOperation<Message> pendingMessageRequest;
initState() {
pendingMessageRequest = fetchMessage(widget.messageId);
}
didUpdateWidget(oldWidget) {
if (widget.userId != oldWidget.messageId) {
pendingMessageRequest.cancel();
pendingMessageRequest = fetchMessage(widget.messageId);
message = pendingMessageRequest.value;
}
}
dispose() {
pendingMessageRequest.cancel();
}
์ ์ผํ ์ฐจ์ด์ ์ fetchUser
๋ฅผ fetchMessage
๋ณ๊ฒฝํ๋ค๋ ๊ฒ์
๋๋ค. ๋
ผ๋ฆฌ๋ ๊ทธ๋ ์ง ์์ผ๋ฉด 100% ๋์ผํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๊ฒ์ useUnaryCancelableOperation
ํํฌ๋ก ๋ถํดํ ์ ์์ต๋๋ค.
์ฆ, ๋์ผํ ๋ ์์ ฏ์ ์ฌ์ฉํ๋ฉด ๋์ ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
Widget build(context) {
Future<User> user = useUnaryCancelableOperation(userId, fetchUser);
}
VS
Widget build(context) {
Future<Message> message = useUnaryCancelableOperation(messageId, fetchMessage);
}
์ด ์๋๋ฆฌ์ค์์๋ ์์ฒญ ๋ฐ ์ทจ์์ ๊ด๋ จ๋ ๋ชจ๋ ๋
ผ๋ฆฌ๊ฐ ๊ณต์ ๋ฉ๋๋ค. fetchUser
vs fetchMessage
๋ผ๋ ์๋ฏธ ์๋ ์ฐจ์ด๋ง ๋จ์ต๋๋ค.
์ด useUnaryCancelableOperation
์์ ํจํค์ง๋ฅผ ๋ง๋ค ์๋ ์์ผ๋ฉฐ ์ด์ ๋ชจ๋ ์ฌ๋์ด ์ฑ์์ ์ด๋ฅผ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฌ๊ธฐ์ ์ ๊ณต๋ ์์ ์ ๊ฐ์น์ ๋์ํ์ง ์์ผ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ํ์ ์๋ฌด ๊ฒ๋ ๊ฐ์ ธ์ค์ง ์์ต๋๋ค. StatefulWidget์ผ๋ก ํ ์ ์๋ ํํฌ๋ก ํ ์ ์๋ ๊ฒ์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋ง์ฝ ๊ทธ๊ฒ์ด ์ ๋ง๋ก ์ฌ์ค์ด๋ผ๋ฉด ์ฐ๋ฆฌ๋ ์ด ๋ฒ๊ทธ๋ฅผ ๋ซ์์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์๋ํ๋ฉด ์ฐ๋ฆฌ๋ ์ด๋ฏธ ์ฌ๊ธฐ์ ์ฃผ์ด์ง ์๋ฅผ ๋ ผ์ํ๊ณ ๊ทธ๊ฒ๋ค์ ์ค๋๋ ฅ์ด ์์๊ธฐ ๋๋ฌธ์ ๋๋ค. ํ์ง๋ง ์ํฉ์ ๋ ์ ์ดํดํ๊ณ ์ถ์ต๋๋ค. ์ด ๋ฒ๊ทธ์ ์ด์ ์๊ฒฌ์์ ์ด์ ์ด ์์ฉ ํ๋ก๊ทธ๋จ ์์ค์ ์๋ ๊ฒ์ฒ๋ผ ๋ค๋ฆฌ๋ฏ๋ก ์์ฉ ํ๋ก๊ทธ๋จ์ ์๋ฅผ ์ฐ๊ตฌํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ ์ผํ ์ฐจ์ด์ ์
fetchUser
๋ฅผfetchMessage
๋ณ๊ฒฝํ๋ค๋ ๊ฒ์ ๋๋ค. ๋ ผ๋ฆฌ๋ ๊ทธ๋ ์ง ์์ผ๋ฉด 100% ๋์ผํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด ๊ฒ์ ๋ฌด์์ด๋ฉฐ ์ฌ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ๋ฌด์์ ๋๊น? ์์ ํ ์๋ก์ด ์ถ์ํ ๋ฐ ํด๋์ค ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๊ตฌํํ๋ ๊ฒ์ ํด๋์ค์ ์ธ ๊ฐ์ง ๋ฉ์๋๋ฅผ ๊ตฌํํ ํ์๊ฐ ์๊ณ ๋๋ฌด ๊ณผ๋ํฉ๋๋ค.
๋ค์ ๋งํ์ง๋ง, ์ด๋ค ๊ฒ์ด ์ผ๋ฐ์ ์ธ ํจํด์ด๋ผ๊ณ ํด์ ์ ๊ธฐ๋ฅ์ ๋ง๋ค์ด์ผ ํ๋ค๋ ์๋ฏธ๋ ์๋๋๋ค. ๊ฒ๋ค๊ฐ ์ด ๊ฒฝ์ฐ ๋ฐ๋ณต์ ์ธ ์ฝ๋๋ฅผ ์ค์ด๋ ค๋ฉด StatefulWidget* ํด๋์ค๋ฅผ ํ์ฅํ๊ณ initstate/didUpdateWidget ๋ฉ์๋๋ฅผ ๊ณตํต ๋นํธ๋ก ์ฌ์ ์ํ๋ฉด ๋ฉ๋๋ค.
ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๊ฒ์
useUnaryCancelableOperation
ํํฌ๋ก ์ธ์๋ถํดํ ์ ์์ต๋๋ค.์ฆ, ๋์ผํ ๋ ์์ ฏ์ ์ฌ์ฉํ๋ฉด ๋์ ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
Widget build(context) { Future<User> user = useUnaryCancelableOperation(userId, fetchUser); }
VS
Widget build(context) { Future<Message> message = useUnaryCancelableOperation(messageId, fetchMessage); }
์ด ์๋๋ฆฌ์ค์์๋ ์์ฒญ ๋ฐ ์ทจ์์ ๊ด๋ จ๋ ๋ชจ๋ ๋ ผ๋ฆฌ๊ฐ ๊ณต์ ๋ฉ๋๋ค.
fetchUser
vsfetchMessage
๋ผ๋ ์๋ฏธ ์๋ ์ฐจ์ด๋ง ๋จ๊ฒ ๋ฉ๋๋ค.
์ดuseUnaryCancelableOperation
์์ ํจํค์ง๋ฅผ ๋ง๋ค ์๋ ์๊ณ ์ด์ ๋ชจ๋ ์ฌ๋์ด ์ฑ์์ ์ด๋ฅผ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ฏธ์ํ์ง๋ง ๊ทธ๊ฑด ๋์๊ฒ ํฐ ๊ฒฐ์ ์ ์๋์ค. ์ ์ ์์ ์ฝ๋ ์ค๋ณต์ฑ๋ง ์ ์ฝํ๋ค๋ ์ฌ์ค ์ธ์๋ ๊ฐ๋ ์ ์ผ๋ก "initState" ๋ฐ "update" ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋์ ์ํ๋ ์ฝ๋๋ฅผ ๋น๋ ๋ฉ์๋๋ก "์ธ์๋ถํด"ํ๋ ๊ฒ์ ํฐ ๋ฌธ์ ๊ฐ ์๋๋๋ค.
๋ด ๋น๋ ๋ฐฉ๋ฒ์ด ๋ ์ด์์๋ง ๋น๋ํ๊ณ ๋ค๋ฅธ ๊ฒ์ ๋น๋ํ์ง ์์ ๊ฒ์ผ๋ก ๊ธฐ๋ํฉ๋๋ค. ์ข ์์ฑ์ ์ค์ ํ๊ณ ํด์ ํ๋ ๊ฒ์ ํ์คํ ๋น๋ ๋ฐฉ๋ฒ์ ์ํ์ง ์์ผ๋ฉฐ, ๋์ผํ ์ ํ์ ์ฝ๋๋ฅผ ๋ช ์์ ์ผ๋ก ๋ค์ ์์ฑํ์ฌ ๋ด ์์ ฏ์ด ํ๋ ์ผ์ ๋ฏธ๋์ ๋์ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ ๋ช ์์ ์ผ๋ก ํ์ํด์ผ ํ๋ ๊ฒ์ด ๋งค์ฐ ๊ธฐ์ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋น๋ ๋ฉ์๋์ ๋ชจ๋ ๊ฒ์ ์ง์ด๋ฃ์ง ๋ง์๋ค.
์ ๋ง ๊ทธ๋ ๋ค๋ฉด ์ด ๋ฒ๊ทธ๋ฅผ ๋ซ์์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
@Hixie ์ ๋ฐ ํ์ง๋ง. ์ฌ๋๋ค์ ์ด ๋ฌธ์ ์ ๊ด์ฌ์ด ์์ต๋๋ค. ๋๋ ์ฝ ๋ ๋ง์ ๋น์ ๊ณผ ํจ๊ป ์ด์ผ๊ธฐ ํ ๊ฐ์ ์ผ์ ํ์ง๋ง, SwiftUI์ ๋งฅ๋ฝ์์ : https://github.com/szotp/SwiftUI_vs_Flutter
ํํฌ๊ฐ ์๋๋ผ ์ํ ์ ์ฅ ์์ ฏ์ ์ด๋ป๊ฒ๋ ๊ฐ์ ํ๋ ๊ฒ์ ๋๋ค. ์ฌ๋๋ค์ ๋จ์ํ ์์ฉ๊ตฌ ์์ฑ์ ์ซ์ดํฉ๋๋ค. RAII ๋ฐ View์ ์๋ฏธ๋ฅผ ๋ณต์ฌํ๋ ๋ฐ ์ต์ํ SwiftUI ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฐ๋ฐ์์๊ฒ๋ ์ผํ์ฉํ์ ์๋์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ด ์ณ์ง ์์ ๊ฒ์ฒ๋ผ ๋ณด์ ๋๋ค.
๊ทธ๋์ ์ ๋ flutter ํ์ด ์ ์ด๋ ์ด๊ฒ์ ๋ฌธ์ ๋ก ๋ณด๊ณ ๋์์ ์ธ ์๋ฃจ์ /๊ฐ์ ์ฌํญ์ ๋ํด ์๊ฐํ๊ธฐ๋ฅผ ๊ถ์ฅํฉ๋๋ค.
๋ด ๋น๋ ๋ฐฉ๋ฒ์ด ๋ ์ด์์๋ง ๋น๋ํ๊ณ ๋ค๋ฅธ ๊ฒ์ ๋น๋ํ์ง ์์ ๊ฒ์ผ๋ก ๊ธฐ๋ํฉ๋๋ค. ์ข ์์ฑ์ ์ค์ ํ๊ณ ํด์ ํ๋ ๊ฒ์ ํ์คํ ๋น๋ ๋ฐฉ๋ฒ์ ์ํ์ง ์์ต๋๋ค.
์ค์ํ ํฌ์ธํธ์ ๋๋ค. ๋น๋ ๋ฉ์๋๋ ์์ํด์ผ ํฉ๋๋ค. ๊ทธ๋๋ ๋ ์ฐ๋ฆฌ๊ฐ ์ด๋ ค์ ์์ด ์ฅ์ ์ ๊ฐ์ง ์ ์๊ธฐ๋ฅผ ๋ฐ๋์ด
์ฌ๊ธฐ์ ๋ ๋ง์ ์๋ฅผ ์๊ตฌํ๋ ๊ฒ์ด ์ ๋ง ์ดํด๊ฐ ๋์ง ์์ต๋๋ค. ์ผ๊ตด์ ์ ๋ช ํฉ๋๋ค.
ํํฌ์ ์ํด ํด๊ฒฐ๋ ๋ฌธ์ ๋ ๊ฐ๋จํ๊ณ ๋ช ๋ฐฑํ๋ฉฐ ์ฝ๋๋ฅผ DRY๋ก ์ ์งํฉ๋๋ค. ์ด๊ฒ์ ์ด์ ์ ๋ช ๋ฐฑํ ๊ฒ, ๋ ์ ์ ์ฝ๋ == ๋ ์ ์ ๋ฒ๊ทธ, ๋ ์ฌ์ด ์ ์ง ๊ด๋ฆฌ, ๋ ์ ์ ๋ฒ๊ทธ๊ฐ ์จ๊ธธ ์ฅ์, ๋ ์ ์ ์ค์ ์ ์ฒด ๊ฐ๋ ์ฑ ์ฆ๊ฐ, ์ฃผ๋์ด ํ๋ก๊ทธ๋๋จธ๊ฐ ๋ ์ ์ ์ฐ๋๋ค๋ ๊ฒ์ ๋๋ค.
์ค์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋งํ๋ ๊ฒฝ์ฐ ๋งค๋ฒ 12๊ฐ์ ๋ค๋ฅธ ๋ณด๊ธฐ์์ 12๊ฐ์ ์ ๋๋ฉ์ดํฐ ์ปจํธ๋กค๋ฌ๋ฅผ ์ค์ ๋ฐ ๋ถํดํ์ฌ dispose() ํธ์ถ์ ๋์น๊ฑฐ๋ ์ผ๋ถ๋ฅผ ์ฌ์ ์ํ ์ ์๋ ๋ฌธ์ ์ด์ด๋๋ ์ฑ์ ๋๋ค. ๋ค๋ฅธ ์๋ช ์ฃผ๊ธฐ ๋ฐฉ๋ฒ. ๊ทธ๋ฐ ๋ค์ ์ด๋ฅผ ์์ญ ๊ฐ์ ๋ค๋ฅธ ์ํ ์ ์ฅ ์ธ์คํด์ค์ ์ ์ฉํ๋ฉด ์๋ฐฑ ๋๋ ์์ฒ ๊ฐ์ ๋ฌด์๋ฏธํ ์ฝ๋ ๋ผ์ธ์ ์ฝ๊ฒ ๋ณผ ์ ์์ต๋๋ค.
Flutter๋ ์ฐ๋ฆฌ๊ฐ ์ง์์ ์ผ๋ก ๋ฐ๋ณตํด์ผ ํ๋ ์์ ๊ฐ์ฒด์ ์ํ๋ฅผ ์ค์ ํ๊ณ ํด์ฒดํด์ผ ํ๋ ์ด๋ฌํ ๊ฒฝ์ฐ๋ก ๊ฐ๋ ์ฐจ ์์ต๋๋ค. ์ด๋ฌํ ๊ฒฝ์ฐ๋ ์กด์ฌํ ํ์๊ฐ ์์ง๋ง ์กด์ฌํ๋ ๋ฒ๊ทธ์ ๋ํ ๋ชจ๋ ์ข ๋ฅ์ ๊ธฐํ๋ฅผ ๋ง๋ญ๋๋ค. ์๋ํ๋ฉด ํ์ฌ๋ก์๋ ์ฐ์ํ ์ ๊ทผ ๋ฐฉ์์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด ์๋ ์ค์ /ํด์ฒด/๋๊ธฐํ ๋ ผ๋ฆฌ๋ฅผ ๊ณต์ ํฉ๋๋ค.
์ค์ ๋ฐ ๋ถํด ๋จ๊ณ๊ฐ ์๊ฑฐ๋ ํญ์ ์ฐ๊ฒฐํด์ผ ํ๋ ์๋ช ์ฃผ๊ธฐ ํํฌ๊ฐ ์๋ ๋ง ๊ทธ๋๋ก _๋ชจ๋ _ ์ํ์์ ์ด ๋ฌธ์ ๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
๋ ์์ ์ ์์ ฏ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ ์ ๊ทผ ๋ฐฉ์์ด๋ผ๋ ๊ฒ์ ์์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ค์ /ํด์ ๊ฐ ๋๋ฌด ์ฑ๊ฐ์๊ณ ์ฅํฉํ๋ฉฐ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ๊ธฐ ๋๋ฌธ์ AnimatorController๋ ๊ฑฐ์ ์ฌ์ฉํ์ง ์์ต๋๋ค. ๋์ ๊ฐ๋ฅํ ๋ชจ๋ ๊ณณ์์ TweenAnimationBuilder๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด ์ ๊ทผ ๋ฐฉ์์ ์ฃผ์ด์ง ๋ณด๊ธฐ์์ ๋ ๋ง์ ์์ ์ํ ์ ์ฅ ๊ฐ์ฒด์ ๋๋ฌํ๋ฏ๋ก ์ค์ ๋ก ์๋ฌด ๊ฒ๋ ํ์ํ์ง ์์ ๊ณณ์ ์ค์ฒฉ ๋ฐ ์์ธํ ์ ๋ณด๋ฅผ ๊ฐ์ํ๋ค๋ ํ๊ณ๊ฐ ์์ต๋๋ค.
@szotp ์ ๋ ํ์ง ์์์ต๋๋ค... ์ฐจ๋ผ๋ฆฌ ์ฐ๋ฆฌ๊ฐ ์๋ฃจ์ ์ ํ๊ฐํ ์ ์๋๋ก ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๋ ํ๋ ์ด์์ ๊ธฐ๋ณธ ์ฑ์ ์ค์ ํ๊ณ ์ถ์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ ์ค์ค๋ก ํ ๊ฒ์ด์ง๋ง ์ฐ๋ฆฌ๊ฐ ํด๊ฒฐํ๋ ค๋ ๊ฒ์ด ์ ํํ ๋ฌด์์ธ์ง ์ดํดํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ๋ด๊ฐ ๊ทธ๊ฒ์ ํ๋ ๊ฒ์ด ์๋ชป๋ ์ฌ๋์ ๋๋ค.
@escamoteur Baseline ์ฑ์ ์ด๋ ค์์ด ์๋ ์๋ฃจ์ ์ ์ค๊ณํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
@esDotDev ์ฐ๋ฆฌ๋ ์ง๊ธ๊น์ง ์ด ๋ฒ๊ทธ์์ ์ด์ ๊ฐ์ ๊ฒฝ์ฐ์ ๋ํด ๋ ผ์ํ์ง๋ง Hooks ์ด์ธ์ ์๋ฃจ์ ์ ์๋ฃจ์ ์ด ํด๊ฒฐํ ์์ ์ ํฌํจ๋์ง ์์ ์ผ๋ถ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ๊ทธ๋ด ๋๋ง๋ค ๊ธฐ๊ฐ๋ฉ๋๋ค. ๋ฐ๋ผ์ ๋ฌธ์ ์ ๋ํ ๊ฐ๋จํ ์ค๋ช ์ ์ ์ฒด ๋ฒ์๋ฅผ ํ์ ํ๊ธฐ์ ์ถฉ๋ถํ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค. ์๋ฅผ ๋ค์ด, "12๊ฐ์ ์ ๋๋ฉ์ดํฐ ์ปจํธ๋กค๋ฌ" ์ฌ๋ก๋ ์ ๋๋ฉ์ด์ ์ปจํธ๋กค๋ฌ ๋ฐฐ์ด๊ณผ Dart์ ๊ธฐ๋ฅ์ ๊ธฐ๋ฅ์ผ๋ก ํด๊ฒฐํ ์ ์์ต๋๋ค. TweenAnimationBuilder๊ฐ ๋ ๋ค๋ฅธ ์๋ฃจ์ ์ด ๋ ์ ์์ต๋๋ค. ๋ ์ค ์ด๋ ๊ฒ๋ Hooks๋ฅผ ํฌํจํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ด๊ฐ ์ ์ํ๋ฉด ๋๊ตฐ๊ฐ ๋ด๊ฐ ๋์น ๊ฒ์ ์ง์ ํ๊ณ "๊ทธ๊ฒ์ ... ๋๋ฌธ์ ์๋ํ์ง ์์ต๋๋ค."๋ผ๊ณ ๋งํ๊ณ (์์ ์ปจํ ์คํธ์์ ์๋ก์ด) ๋ฌธ์ ๋ฅผ ์ ๊ธฐํ ๊ฒ์ด๋ผ๊ณ ํ์ ํฉ๋๋ค. ๋ฐ๋ผ์ ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ๋์ํ๋ ๊ธฐ๋ณธ ์ฑ์ ํ์์ฑ์ ๋ฌธ์ ์ ์ ์ฒด ํ์ฐ์ ํฌ๊ดํฉ๋๋ค.
๋๊ตฐ๊ฐ๊ฐ ์ด๊ฒ์ ์์ผ๋ก ์ถ์งํ๊ณ ์ถ๋ค๋ฉด ๋ด๊ฐ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ์์์ ์ค๋ช ํ ๊ฒ์ ๋๋ค(https://github.com/flutter/flutter/issues/51752#issuecomment-670249755 ๋ฐ https://github.com /flutter/flutter/issues/51752#issuecomment-670232842). ๊ทธ๊ฒ์ ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ์ฐ๋ฆฌ๊ฐ ํด๊ฒฐํ๋ ค๋ ๋ฌธ์ ์ ๋ฒ์๋ฅผ ๋ํ๋ธ๋ค๋ ๋ฐ ๋์ํ ์ ์๋ ์ถ๋ฐ์ ์ ์ ๊ณตํ ๊ฒ์ ๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋ชจ๋ ์๊ตฌ ์ฌํญ(์: @rrousselGit ์ ์ฌ์ฌ์ฉ ํ์์ฑ, @Rudiksz ์ ๊นจ๋ํ ๋น๋ ๋ฐฉ๋ฒ์ ๋ํ ํ์์ฑ ๋ฑ)์ ํด๊ฒฐํ๋ ๋ฐฉ์์ผ๋ก ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์๋ฃจ์ ์ ์ค๊ณํ ์ ์์ผ๋ฉฐ ๊ฐ์ฅ ์ค์ํ ๊ฒ์ ์ด๋ฌํ ์๋ฃจ์ ์ ํ๊ฐํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๊ธฐ๋ณธ ์ฑ์ ์ปจํ ์คํธ์ ๋๋ค.
๋๋ ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ์ด ๋ฌธ์ ์ ๋ํด ์๋นํ ์ฝ๊ฒ ๋์ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
_Streams, AnimatorController ๋ฑ๊ณผ ๊ด๋ จ๋ ์ค์ /ํด์ ์์
์ ๊ณต์ ํ๋ ์ฐ์ํ ๋ฐฉ๋ฒ์ ์์ต๋๋ค. ์ด๋ ๋ถํ์ํ ์ฅํฉํจ, ๋ฒ๊ทธ ๋ฐ์ ๋ฐ ๊ฐ๋
์ฑ ๊ฐ์๋ก ์ด์ด์ง๋๋ค._
๊ทธ๊ฒ์ ๋์ํ์ง ์๋ ์ฌ๋์ด ์์ต๋๊น? ๊ฑฐ๊ธฐ์์ ์์ํ์ฌ ํด๊ฒฐ์ฑ ์ ์ฐพ์ ์์ผ๋ก ๋์๊ฐ๋ฉด ์ ๋ ๊น์? ์ฐ๋ฆฌ๋ ๋จผ์ ์ด๊ฒ์ด ํต์ฌ ๋ฌธ์ ๋ผ๋ ๋ฐ ๋์ํด์ผ ํฉ๋๋ค. ์์ง๊น์ง๋ ๊ทธ๋ ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค.
ํ์ง๋ง ๊ธ์ ์ฐ๋ฉด์ ๋ฌธ์ ์ ์ด๋ฆ์ด ์ ํํ ์ผ์นํ๋ค๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค.
" ์ํ ๋
ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ฌด ์ฅํฉํ๊ฑฐ๋ ๋๋ฌด ์ด๋ ต์ต๋๋ค "
๋์๊ฒ ๊ทธ๊ฒ์ ๋งค์ฐ ๋ช ๋ฐฑํ ๋ฌธ์ ์ด๋ฉฐ, ์ฐ๋ฆฌ๋ ์ ์ํ๊ฒ ํ ๋ก ๋จ๊ณ๋ฅผ ์ง๋์ ๋ฌด์์ด ํจ๊ณผ๊ฐ ์์์ง ๋ธ๋ ์ธ์คํ ๋ฐ์ ๋ค์ด๊ฐ์ผ ํฉ๋๋ค. ์ฌ์ฌ์ฉํ ์ ์๋ ๋ฏธ์ธ ์ํ๊ฐ ํ์ํฉ๋๋ค... ๋ญ๊ฐ ์์๋ผ ์ ์์ ๊ฑฐ๋ผ ํ์ ํฉ๋๋ค. ํ๋ฃจ๊ฐ ๋๋ ๋ ๋ง์ Flutter ๋ณด๊ธฐ๋ฅผ ์ ๋ฆฌํ๊ณ ๋ ๊ฐ๋ ฅํ๊ฒ ๋ง๋ค ๊ฒ์ ๋๋ค.
@Hixie ์ ๋ฐ ํ์ง๋ง. ์ฌ๋๋ค์ ์ด ๋ฌธ์ ์ ๊ด์ฌ์ด ์์ต๋๋ค. ๋๋ ์ฝ ๋ ๋ง์ ๋น์ ๊ณผ ํจ๊ป ์ด์ผ๊ธฐ ํ ๊ฐ์ ์ผ์ ํ์ง๋ง, SwiftUI์ ๋งฅ๋ฝ์์ : https://github.com/szotp/SwiftUI_vs_Flutter
๋น์ ์ SwiftUI ์์ ๋ ๋จ์ํ StatefulWidget ํด๋์ค๋ฅผ ํ์ฅํจ์ผ๋ก์จ ๋ช ์ค์ ์ฝ๋๋ก ๋คํธ์์ ๋ณต์ ๋ ์ ์์ต๋๋ค.
์๋ฆฌ๋ฏธ๋ฅผ ๊ตฌ๋ ํ์ง ์๊ฑฐ๋ ์ธ๋ถ ํธ์ถ์ ์ํํ์ง ์๋ StatefulWidgets๊ฐ ์์ผ๋ฉฐ ์ค์ ๋ก ๋๋ถ๋ถ์ด ๊ทธ๋ ์ต๋๋ค. ๋๋ ์ฝ 100๊ฐ์ ์ฌ์ฉ์ ์ ์ ์์ ฏ์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ(๋ชจ๋ Stateful์ ์๋์ง๋ง) ๊ทธ ์ค 15๊ฐ๋ ์ฌ๊ธฐ ์์ ์์ ์ค๋ช ํ๋ ๋ชจ๋ ์ข ๋ฅ์ "๊ณตํต ์ํ ๋ ผ๋ฆฌ"๊ฐ ์์ต๋๋ค.
์ฅ๊ธฐ์ ์ผ๋ก ๋ช ์ค์ ์ฝ๋(์ผ๋ช ์์ฉ๊ตฌ)๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋ถํ์ํ ์ค๋ฒํค๋๋ฅผ ํผํ๊ธฐ ์ํ ์์ ์ ์ถฉ์์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค์, initState/didUpdate ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผ ํ๋ ์ด ๋ฌธ์ ๋ ๋๋ฌด ๊ณผ์ฅ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ฌ๊ธฐ์ ์ค๋ช ๋ ํจํด ์ค ํ๋๋ฅผ ์ฌ์ฉํ๋ ์์ ฏ์ ๋ง๋ค ๋ ์ฒ์์๋ ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋๋ฅผ "๊ตฌํ"ํ๋ ๋ฐ 5-10๋ถ์ ๋ณด๋ธ ๋ค์ ํด๋น ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋๋ฅผ ๊ฑด๋๋ฆฌ์ง ์์ผ๋ฉด์ ์ค์ ๋ก ์์ ฏ ์์ฒด๋ฅผ ์์ฑํ๊ณ ์ฐ๋งํ๋ ๋ฐ ๋ฉฐ์น ์ ํ ์ ํฉ๋๋ค. ์์ ์์ฉ๊ตฌ ์ค์ /ํด์ฒด ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐ ์๋นํ๋ ์๊ฐ์ ๋ด ์ฑ ์ฝ๋์ ๋นํด ์ ์ต๋๋ค.
๋ด๊ฐ ๋งํ๋ฏ์ด StatefulWidget์ ์ฉ๋์ ๋ํด ๊ฑฐ์ ๊ฐ์ ํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ฐ๋ ฅํ๊ณ ํจ์จ์ ์ ๋๋ค.
์ด ํน์ ์ฌ์ฉ ์ฌ๋ก์ ๋ํด StatefulWidget์ ์๋ธํด๋์ฑํ๋(๋๋ ๊ทธ๋ ์ง ์์) Flutter์ ์๋ก์ด ์ ํ์ ์์ ฏ์ ์ถ๊ฐํ๋ ๊ฒ์ ๊ด์ฐฎ์ง๋ง StatefulWidget ์์ฒด์ ์ ์ฉํ์ง๋ ๋ง์๋ค. ๋๋ "ํํฌ" ์์คํ ์ด๋ ๋ง์ดํฌ๋ก์คํ ์ดํธ์ ํจ๊ป ์ค๋ ์ค๋ฒํค๋๊ฐ ํ์ํ์ง ์์ ์์ ฏ์ ๋ง์ด ๊ฐ์ง๊ณ ์์ต๋๋ค.
@esDotDev ์ผ๋ถ ์ฌ๋๋ค์ด ์ง๋ฉดํ ๋ฌธ์ ๋ผ๋ ๋ฐ ๋์ํฉ๋๋ค. ๋๋ ์ด ๋ฌธ์ ์ ์๋ถ๋ถ์์ ๋ช ๊ฐ์ง ์๋ฃจ์
์ ์ ์ํ๊ธฐ๋ ํ์ต๋๋ค(GitHub์ด ๋ชจ๋ ์ฃผ์์ ํ์ํ๋ ๊ฒ์ ์ข์ํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ค์ํ ๋ฒ์ ์ Property
ํด๋์ค ๊ฒ์, ์ง๊ธ์ ๋ฌปํ ์ ์์). ์ด๋ ค์์ ์ด๋ฌํ ์ ์์ด ํน์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ์์๊ธฐ ๋๋ฌธ์ ๊ธฐ๊ฐ๋์๋ค๋ ๊ฒ์
๋๋ค(์: ํ ๊ฒฝ์ฐ์๋ ํซ ๋ฆฌ๋ก๋๋ฅผ ์ฒ๋ฆฌํ์ง ์์๊ณ ๋ค๋ฅธ ๊ฒฝ์ฐ์๋ didUpdateWidget์ ์ฒ๋ฆฌํ์ง ์์์ต๋๋ค). ๊ทธ๋์ ๋ ๋ง์ ์ ์์ ํ์ง๋ง ๋ค๋ฅธ ๊ฒ์ ์ฒ๋ฆฌํ์ง ์์๊ธฐ ๋๋ฌธ์ ๋ค์ ๊ธฐ๊ฐ๋์์ต๋๋ค(๋ฌด์์ ์์ด๋ฒ๋ ธ๋์ง). ์ด๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ๊ทธ ๋ฌธ์ ์ ๋ํ ์๋ฃจ์
์ ์ฐพ์ ์ ์๋๋ก _์ ์ฒด_ ๋ฌธ์ ๋ฅผ ๋ํ๋ด๋ ๋ฐ ๋์ํ๋ ์ผ์ข
์ ๊ธฐ์ค์ ์ ๊ฐ๋ ๊ฒ์ด ์ค์ํ ์ด์ ์
๋๋ค.
๋ชฉํ๋ ๊ฒฐ์ฝ ๋ณํ์ง ์์์ต๋๋ค. ์ ์๋ ์๋ฃจ์ ์ด ์ ์ฐ์ฑ์ด ๋ถ์กฑํ๋ค๋ ๋นํ์ด ์ ๊ธฐ๋์์ต๋๋ค. ์ด๋ค ์ค ์ด๋ ๊ฒ๋ ๊ตฌํ๋ ์ค๋ํซ ์ธ๋ถ์์ ๊ณ์ ์๋ํ์ง ์์ต๋๋ค.
์ด๊ฒ์ด ์ด ํธ์ ์ ๋ชฉ์ "์ด๋ ค์"์ด ์ธ๊ธ๋ ์ด์ ์ ๋๋ค. ํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ์์ ์ ์ฐ์ฑ์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ทธ๊ฒ์ ๋ณด๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด ๋ฌธ์ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ํ ๋ก์ง์ ์ํด ์์ ฏ ๋ ์ด์ด๋ฅผ ๊ตฌํํด์ผ ํ๋ค๊ณ ์ฃผ์ฅํฉ๋๋ค.
์ ์๋ ์๋ฃจ์
์ "ํ์ง๋ง RenderObject๋ก ํ ์ ์์ต๋๋ค"์
๋๋ค.
_์ฅ๊ธฐ์ ์ผ๋ก, ๋ช ์ค์ ์ฝ๋(์ผ๋ช ์์ฉ๊ตฌ)๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋ถํ์ํ ์ค๋ฒํค๋๋ฅผ ํผํ๊ธฐ ์ํ ์์ ์ ์ถฉ์์ ๋๋ค._
์ด ์ง์ ๊ณผ ํจ๊ป ๋ช ๊ฐ์ง ๋ํธ :
Thing.DOTween()
). 15๋ ์๊ธฐ๋ค์.@esDotDev
๋์๊ฒ ๊ทธ๊ฒ์ ๋งค์ฐ ๋ช ๋ฐฑํ ๋ฌธ์ ์ด๋ฉฐ, ์ฐ๋ฆฌ๋ ์ ์ํ๊ฒ ํ ๋ก ๋จ๊ณ๋ฅผ ์ง๋์ ๋ฌด์์ด ํจ๊ณผ๊ฐ ์์์ง ๋ธ๋ ์ธ์คํ ๋ฐ์ ๋ค์ด๊ฐ์ผ ํฉ๋๋ค.
์์ ฏ ํ์ฅ. ValueNotifier๊ฐ ๊ณตํต ์ฌ์ฉ ํจํด์ ๋จ์ํํ๊ธฐ ์ํด ChangeNotifier๋ฅผ ํ์ฅํ๋ ๋ฐฉ์๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ชจ๋ ์ฌ๋์ ํน์ ์ฌ์ฉ ์ฌ๋ก์ ๋ํด ์์ ๋ง์ StatelessWidget์ ์์ฑํ ์ ์์ต๋๋ค.
์, ๊ทธ๊ฒ์ด ํจ๊ณผ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ด๋ผ๋ ๋ฐ ๋์ํ์ง๋ง ๋ฐ๋ผ๋ ์ ์ด ์์ต๋๋ค. ์ ๋๋ฉ์ดํฐ๊ฐ 1๊ฐ๋ผ๋ฉด TweenAnimationBuilder๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฟจ, ์ฌ์ ํ 5์ค์ ์ฝ๋์ ๋น์ทํ์ง๋ง ๋ฌด์์ด๋ ์๊ด์์ต๋๋ค. ๊ทธ๊ฒ์ ์๋ํฉ๋๋ค ... ๋๋ฌด ๋์์ง ์์ต๋๋ค. ํ์ง๋ง 2~3๊ฐ ์์ผ๋ฉด? ์ด์ ์ ๋ ์ค์ฒฉ ์ง์ฅ์ ์์ต๋๋ค. ์ด๋ค ์ด์ ๋ก cpl ๋ค๋ฅธ ์ํ ์ ์ฅ ๊ฐ์ฒด๊ฐ ์๋ ๊ฒฝ์ฐ ๋ชจ๋ ๋ค์ฌ์ฐ๊ธฐ๊ฐ ์๋ง์ด ๋๊ฑฐ๋ ์์์ ์ค์ , ์ ๋ฐ์ดํธ ๋ฐ ๋ถํด ์ปฌ๋ ์ ์ ์บก์ํํ๋ ๋งค์ฐ ๊ตฌ์ฒด์ ์ธ ์์ ฏ์ ๋ง๋ค๊ณ ์์ต๋๋ค. ๋ ผ๋ฆฌ.
์์ ฏ ํ์ฅ. ValueNotifier๊ฐ ๊ณตํต ์ฌ์ฉ ํจํด์ ๋จ์ํํ๊ธฐ ์ํด ChangeNotifier๋ฅผ ํ์ฅํ๋ ๋ฐฉ์๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ชจ๋ ์ฌ๋์ ํน์ ์ฌ์ฉ ์ฌ๋ก์ ๋ํด ์์ ๋ง์ StatelessWidget์ ์์ฑํ ์ ์์ต๋๋ค.
ํ ๋ฒ์ ํ๋์ ๊ธฐ๋ณธ ํด๋์ค๋ง ํ์ฅํ ์ ์์ต๋๋ค. ๊ทธ๊ฑด ์ค์ผ์ผ์ด ์๋๋ค
๋ฏน์ค์ธ์ ๋ค์ ๋ ผ๋ฆฌ์ ์๋์ ๋๋ค. ๊ทธ๋ฌ๋ OP๊ฐ ์ธ๊ธํ๋ฏ์ด ํ์ฅ๋์ง๋ ์์ต๋๋ค.
@esDotDev
๋๋ ์ค์ , ์ ๋ฐ์ดํธ ๋ฐ ํด์ ๋ ผ๋ฆฌ์ ์์ ์ปฌ๋ ์ ์ ์บก์ํํ๋ ๋งค์ฐ ๊ตฌ์ฒด์ ์ธ ์์ ฏ์ ๋ง๋ค๊ณ ์์ต๋๋ค.
3-4๊ฐ์ง ์ข ๋ฅ์ AnimationController๋ฅผ ์ค์ ํด์ผ ํ๋ ์ผ์ข ์ ์์ ฏ์ ๋งค์ฐ ๊ตฌ์ฒด์ ์ธ ์ฌ์ฉ ์ฌ๋ก์ฒ๋ผ ๋ค๋ฆฌ๋ฉฐ ์ค์ /ํด์ ๋ก์ง์ ์์ ์์ง์ ์ง์ํ๋ ๊ฒ์ ํ์คํ ํ๋ ์์ํฌ์ ์ผ๋ถ๊ฐ ๋์ด์๋ ์ ๋ฉ๋๋ค. ์ฌ์ค ์ด๊ฒ์ด initState/didUpdateWidget ๋ฉ์๋๊ฐ ์ฒ์์ ๋ ธ์ถ๋๋ ์ด์ ์ด๋ฏ๋ก ์ํ๋ ๋๋ก ์ค์ ์ ๋ฌด์์๋ก ์์งํ ์ ์์ต๋๋ค.
๊ฐ์ฅ ๊ธด initState ๋ฉ์๋๋ 5์ค์ ์ฝ๋์ด๋ฉฐ, ์์ ฏ์ ๊ณผ๋ํ ์ค์ฒฉ์ ๊ฒช์ง ์์ผ๋ฏ๋ก ์๊ตฌ ์ฌํญ๊ณผ ์ฌ์ฉ ์ฌ๋ก๊ฐ ํ์คํ ๋ค๋ฆ ๋๋ค. ๋๋ ๋ค๋ฅธ ๊ฐ๋ฐ ์คํ์ผ.
@esDotDev
3. Hooks์ ๊ฐ์ ๊ฒ์ผ๋ก ๋ ผ์ํ ๊ฐ์น๊ฐ ์๋ ์ค๋ฒํค๋๊ฐ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๊ฐ๊ฐ์ ์์์ fxns๊ฐ ์๋ ๊ฐ์ฒด ๋ฐฐ์ด์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์์ต๋๋ค. Dart์์๋ ๋งค์ฐ ๋น ๋ฆ ๋๋ค. ํ์ด ์ด๋ชจ์ ๋๋ค.
์ ์๋ ์๋ฃจ์ ์ด ์์ ํ ์ฌ์ค์ด ์๋ flutter_hooks ํจํค์ง์ ๊ฐ์ ๊ฒ์ด๋ผ๋ฉด. ์, ๊ฐ๋ ์ ์ผ๋ก๋ ํจ์๊ฐ ํฌํจ๋ ๋ฐฐ์ด์ด์ง๋ง ๊ตฌํ์ ์ฌ์ํ๊ฑฐ๋ ํจ์จ์ ์ด์ง ์์ต๋๋ค.
๋ด ๋ง์, ๋ด๊ฐ ํ๋ฆด ์๋ ์์ง๋ง HookElement๊ฐ ์์ฒด ๋น๋ ๋ฉ์๋์์ ์์ฒด์ ์ผ๋ก ๋ค์ ๋น๋ํด์ผ ํ๋์ง ์ฌ๋ถ๋ฅผ ํ์ธํ๋ ๊ฒ์ฒ๋ผ ๋ณด์
๋๋ค!
๋ํ ๋ชจ๋ ๋จ์ผ ์์ ฏ ๋น๋์์ ํํฌ๋ฅผ ์ด๊ธฐํ, ์ฌ์ด๊ธฐํ ๋๋ ํ๊ธฐํด์ผ ํ๋์ง ์ฌ๋ถ๋ฅผ ํ์ธํ๋ ๊ฒ์ ์๋นํ ์ค๋ฒํค๋์ฒ๋ผ ๋ณด์
๋๋ค. ์ณ์ง ์๋ค๊ณ ๋๋ผ๋ฏ๋ก ๋ด๊ฐ ํ๋ ธ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
@brianegan ์ ์ํคํ ์ฒ ์์ ์ค ํ๋๋ฅผ ๋น๊ต๋ฅผ ์ํ ๊ธฐ๋ณธ ์ฑ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ์๋ฏธ๊ฐ ์์ต๋๊น?
๋ด๊ฐ ์ฌ๊ธฐ์ ๋ผ์ด๋ค ์ ์๋ค๋ฉด ์ด๊ฒ์ด ์ด๋ฏธ ๋งํ๋์ง ํ์คํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ React์์ ์ฐ๋ฆฌ๋ ํํฌ๊ฐ ์๋ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์๊ฐํ์ง ์์ต๋๋ค. ์ด๊ฒ์ด ์ปดํฌ๋ํธ/์์ ฏ์ ๊ตฌ์ถํ๋ ๋ฐ ์ต์ํ๋ค๋ฉด ๋ฌด์ญ๊ฒ ๋ค๋ฆด ์๋ ์์ง๋ง, ์ฌ๊ธฐ์์ ์๋ช ์ฃผ๊ธฐ๊ฐ ์ค์ ๋ก ์ค์ํ์ง ์์ ์ด์ ๊ฐ ์์ต๋๋ค.
๋๋ถ๋ถ์ ๊ฒฝ์ฐ props๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ํํ ์ํ ๋๋ ์์ ์ผ๋ก ๊ตฌ์ฑ ์์/์์ ฏ์ ๋น๋ํ ๋ ํด๋น ์ํ/props๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ฌด์ธ๊ฐ๊ฐ ๋ฐ์ํ๊ธฐ๋ฅผ ์ํฉ๋๋ค(์: ์ด ์ค๋ ๋์์ ์ธ๊ธํ ๊ฒ์ฒ๋ผ -userId ์ํ์ด ๋ณ๊ฒฝ๋๋ฉด ์ฌ์ฉ์์ ์ธ๋ถ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์์ ฏ์ ๋ชจ๋ props๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ฐ์ํ๋ ๊ฒ๋ณด๋ค userId ๋ณ๊ฒฝ์ "ํจ๊ณผ"๋ก ์๊ฐํ๋ ๊ฒ์ด ํจ์ฌ ๋ ์์ฐ์ค๋ฝ์ต๋๋ค.
์ ๋ฆฌ์ ๋ํด์๋ ๋ง์ฐฌ๊ฐ์ง์ง๋ง, "๋ชจ๋ props/state๊ฐ ๋ณ๊ฒฝ๋๊ฑฐ๋ ๋ณ๊ฒฝ๋ ๋ X๋ฅผ ์ ๋ฆฌํ๋ ๊ฒ์ ๊ธฐ์ตํด์ผ ํจ์ ๊ธฐ์ตํด์ผ ํฉ๋๋ค. ์ ์ฒด ๊ตฌ์ฑ ์์๊ฐ ํ๊ดด๋ ๋".
์ ๋ Flutter๋ฅผ ํ๋์ ์์ฑํ์ง ์์๊ธฐ ๋๋ฌธ์ ํ์ฌ์ ๋ถ์๊ธฐ๋ ์ด ์ ๊ทผ ๋ฐฉ์์ด ํ์ฌ Flutter ์ฌ๊ณ ๋ฐฉ์์ ๋ฏธ์น ์ ํ ์ฌํญ์ ์๊ณ ์๋ ๊ฒ์ฒ๋ผ ๋ค๋ฆฌ๋ ค๊ณ ํ์ง ์์ต๋๋ค. ์ ๋ ๋ค์ํ ์๊ฒฌ์ ์ด๋ ค ์์ต๋๋ค. ๋๋ React hooks์ ์ต์ํ์ง ์์ ๋ง์ ์ฌ๋๋ค์ด ๋ด๊ฐ ๋ผ์ดํ์ฌ์ดํด ํจ๋ฌ๋ค์์ ๋๋ฌด ๊น์ด ๋ฟ๋ฆฌ๋ฐํ ์๊ธฐ ๋๋ฌธ์ ๋ด๊ฐ ์๊ฐ๋์์ ๋์ ๊ฐ์ ํผ๋์ ๊ฒช๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
@escamoteur @Rudiksz @Hixie ๋๋ ์ฐ๋ฆฌ๊ฐ์ด ์์ ๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์์ํ๋ ๊ณณ์ผ๋ก ์ด๋๋ฐ์ ๊ฒ์ @TimWhiting์ ์ํด ์์ฑ ๋ GitHub์ ํ๋ก์ ํธ๊ฐ ์์๋ค. ๊ฐ ๊ฐ์ธ/๊ทธ๋ฃน์ ๋ฏธ๋ฆฌ ์ ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ง๋ค ์ ์์ต๋๋ค. ํ์ด์ง์ ๊ฐ์ ์์ ํ ๊ธฐ๋ฅ์ ๊ฐ์ถ ์ฑ์ ์๋์ง๋ง ๋ ๋ณต์กํ ์๋ฅผ ๋ณด์ฌ์ฃผ๋ ์ญํ ์ ํ๋ ๊ฒฝ์ฐ ์ฑ์ ์ถ๊ฐํ ์๋ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋ฌธ์ ๋ฅผ ๋ ผ์ํ๊ณ ๋ ๋์ API๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. @TimWhiting ์ ๊ด์ฌ ์๋ ์ฌ๋์ ์ด๋ํ ์ ์์ต๋๋ค.
Jetpack compose ๋ ์ฌ๊ธฐ ์์ react ์ ๋น๊ตํ hook๊ณผ๋ ๋น์ทํฉ๋๋ค.
@satvikpendem @TimWhiting ๋ฉ์ง๋ค์ ! ๊ฐ์ฌํฉ๋๋ค.
@esDotDev
๋งค์ฐ ๊ตฌ์ฒด์ ์ธ ์ฌ์ฉ ์ฌ๋ก์ ์ค์ /ํด์ ๋ก์ง์ ์์ ์์ง ์ง์์ ํ์คํ ํ๋ ์์ํฌ์ ์ผ๋ถ๊ฐ ๋์ด์๋ ์ ๋ฉ๋๋ค.
์ด๊ฒ์ ๊ฐ๊ณ ๋ฆฌ๊ฐ ๋จธ๋ฆฌ๋ฅผ ๋๋ฆฌ๋ ๋ชป์ ๋๋ค. ๊ฐ ์ ํ์ ๊ฐ์ฒด๋ ์์ฒด ์ค์ ๋ฐ ๋ถํด๋ฅผ ๋ด๋นํฉ๋๋ค. ์ ๋๋ฉ์ดํฐ๋ ์คํธ๋ฆผ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ค์ค๋ก๋ฅผ ์์ฑ, ์ ๋ฐ์ดํธ ๋ฐ ํ๊ดดํ๋ ๋ฐฉ๋ฒ์ ์๊ณ ์์ต๋๋ค. Hooks๋ ํนํ ๋ทฐ ์ ์ฒด์ ํฉ์ด์ ธ ์๋ ์ํ ์ค์บํด๋ฉ์ '์์ ์ปฌ๋ ์ ' ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ๋ณด๊ธฐ ์ฝ๋์ ๋๋ถ๋ถ์ด ๋น์ฆ๋์ค ๋ก์ง ๋ฐ ๋ ์ด์์ ํ์ํ์ ์ง์คํ ์ ์๋๋ก ํ์ฌ ์น๋ฆฌํฉ๋๋ค. ๋ชจ๋ ํ๋ก์ ํธ์์ ๋์ผํ ์ผ๋ฐ์ ์ธ ์์ฉ๊ตฌ๋ฅผ ์จ๊ธฐ๊ธฐ ์ํด ์ฌ์ฉ์ ์ง์ ์์ ฏ์ ๋ง๋ค๋๋ก ๊ฐ์ํ์ง ์์ต๋๋ค.
๊ฐ์ฅ ๊ธด initState ๋ฉ์๋๋ 5์ค์ ์ฝ๋์ด๋ฉฐ, ์์ ฏ์ ๊ณผ๋ํ ์ค์ฒฉ์ ๊ฒช์ง ์์ผ๋ฏ๋ก ์๊ตฌ ์ฌํญ๊ณผ ์ฌ์ฉ ์ฌ๋ก๊ฐ ํ์คํ ๋ค๋ฆ ๋๋ค. ๋๋ ๋ค๋ฅธ ๊ฐ๋ฐ ์คํ์ผ.
๋ด ๊ฒ๋. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ initState() + dispose() + didUpdateDependancies()์ด๋ฉฐ ๋ง์ง๋ง 2๊ฐ ์ค ํ๋๊ฐ ๋๋ฝ๋๋ฉด ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
ํ์ค ์๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. 1๊ฐ์ ์คํธ๋ฆผ ์ปจํธ๋กค๋ฌ์ 2๊ฐ์ ์ ๋๋ฉ์ดํฐ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฌ์ฉํ๋ ๋ณด๊ธฐ๋ฅผ ์์ฑํฉ๋๋ค.
๋ด๊ฐ ๋ณผ ์์๋ ํ 3 ๊ฐ์ง ์ต์ ์ด ์์ต๋๋ค.
SingleStreamBuilderDoubleAnimationWidget์ธ ๋ค ๋ฒ์งธ ์ต์ ์ด ์์ ์ ์์ง๋ง ์ด๊ฒ์ ๊ฐ๋ฐ์๋ฅผ ์ํ ์์ ์์ ์ด๋ฉฐ ์ผ๋ฐ์ ์ผ๋ก ๊ฝค ์ฑ๊ฐ์ญ๋๋ค.
๋ํ ์๋ก์ด ๊ฐ๋ฐ์์ ์ธ์ง ๋ถํ 3์ ๋ค๋ฅธ 2๋ณด๋ค ํจ์ฌ ๋ฎ์ต๋๋ค. ๋๋ถ๋ถ์ ์๋ก์ด ๊ฐ๋ฐ์๋ TweenAnimationBuilder์ ์กด์ฌ์กฐ์ฐจ ๋ชจ๋ฅด๊ณ , ๋จ์ํ SingleTickerProvider์ ๊ฐ๋ ์ ๋ฐฐ์ฐ๋ ๊ฒ ์์ฒด๊ฐ ์์ ์ ๋๋ค. "์ ๋๋ฉ์ดํฐ๋ฅผ ์ฃผ์ธ์"๋ผ๊ณ ๋งํ๋ ๊ฒ์ด ๋ ์ฝ๊ณ ๊ฐ๋ ฅํ ์ ๊ทผ ๋ฐฉ์์ ๋๋ค.
๋๋ ์ค๋ ๋ฌด์ธ๊ฐ๋ฅผ ์ฝ๋ฉํ๋ ค๊ณ ๋ ธ๋ ฅํ ๊ฒ์ด๋ค.
2. 2๊ฐ์ TweenAnimationBuilder์ StreamBuilder๋ฅผ ์ฝ 15๊ฐ์ ๋ค์ฌ์ฐ๊ธฐ ์์ค์ ๋ํด ์ฌ์ฉํ์ฌ ๋ณด๊ธฐ ์ฝ๋์ ๋๋ฌํ๊ธฐ ์ ์๋ ์คํธ๋ฆผ์ ๋ํ ์์ฉ๊ตฌ๋ฅผ ๋ง์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ค๋ฅธ์ชฝ. 15๋จ๊ณ ๋ค์ฌ์ฐ๊ธฐ๋ฅผ ์ฌ์ฉํ๋ ์ค์ ์ฝ๋ ์์ ๋ฅผ ๋ณด์ฌ์ฃผ์ธ์.
๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ 30์ค์ ์ฝ๋๋ฅผ 6์ค + ์๋ฐฑ ์ค๋ก ๋์ฒดํ๋ฉด ์ธ์ง ๋ถํ๊ฐ โโ์ด๋ป๊ฒ ๊ฐ์ํฉ๋๊น? ๋ค, ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ๋ "๋ง๋ฒ"์ ๋ฌด์ํ ์ ์์ง๋ง ๊ท์น์ ๋ฌด์ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ํํฌ ํจํค์ง๋ ํํฌ๊ฐ ๋น๋ ๋ฉ์๋์์๋ง ์ฌ์ฉํด์ผ ํ๋ค๋ ๋ถํ์คํ ์ฉ์ด๋ก ์๋ ค์ค๋๋ค. ์ด์ ๊ฑฑ์ ํด์ผ ํ ์ถ๊ฐ ์ ์ฝ ์กฐ๊ฑด์ด ์์ต๋๋ค.
15,000์ค์ ์ฝ๋๊ฐ ์๋ ํ๋ก์ ํธ์์ focusnodes, textcontrollers, singletickerproviders ๋๋ ๋ด statefulwidgets์ ๋ค์ํ ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋๋ฅผ ํฌํจํ๋ ์ฝ๋๊ฐ 200์ค ๋ฏธ๋ง์ผ ๊ฒ์ ๋๋ค. ์ด๋ค ์ธ์ง ๊ณผ๋ถํ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์์ต๋๊น?
@Rudiksz ์๋ ๊ณต๊ฒฉ์ ์ค์งํ์ญ์์ค.
์ฐ๋ฆฌ๋ ์ธ์ฐ์ง ์๊ณ ๋์ํ ์ ์์ต๋๋ค.
ํํฌ ์ ์ฝ ์กฐ๊ฑด์ ๊ฐ์ฅ ์ ์ ๊ฑฑ์ ๊ฑฐ๋ฆฌ์ ๋๋ค.
์ฐ๋ฆฌ๋ ํํฌ์ ๋ํด ๊ตฌ์ฒด์ ์ผ๋ก ๋งํ๋ ๊ฒ์ด ์๋๋ผ ๋ฌธ์ ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์์ต๋๋ค.
ํ์ํ๋ค๋ฉด ๋ค๋ฅธ ํด๊ฒฐ์ฑ
์ ์ ์ํ ์ ์์ต๋๋ค.
์ค์ํ ๊ฒ์ ์ฐ๋ฆฌ๊ฐ ํด๊ฒฐํ๊ณ ์ ํ๋ ๋ฌธ์ ์ ๋๋ค.
๋ํ ์์ ฏ์ ๋น๋ ๋ด์์๋ง ๋ฌด์กฐ๊ฑด์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ทธ๊ฒ์ ํํฌ ์ ์ฝ ์กฐ๊ฑด๊ณผ ๋์ผํ์ง๋ง ์ฌ๋๋ค์ด ๊ทธ๊ฒ์ ๋ํด ๋ถํํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ํ ์์ ฏ์ ๋น๋ ๋ด์์๋ง ๋ฌด์กฐ๊ฑด์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ทธ๊ฒ์ ํํฌ ์ ์ฝ ์กฐ๊ฑด๊ณผ ๋์ผํ์ง๋ง ์ฌ๋๋ค์ด ๊ทธ๊ฒ์ ๋ํด ๋ถํํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
์๋์ค, ๋์ผํ์ง ์์ต๋๋ค. ์ฌ๊ธฐ์ ์ ์๋ ๋ฌธ์ ๋ _prepares_ ์์ ฏ์ด _before_ (์ฌ)๋น๋๋๋ ์ฝ๋์ ๊ด๋ จ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ํ, ์ข
์์ฑ, ์คํธ๋ฆผ, ์ปจํธ๋กค๋ฌ ๋ฑ์ ์ค๋นํ๊ณ ํธ๋ฆฌ ๊ตฌ์กฐ์ ๋ณ๊ฒฝ ์ฌํญ์ ์ฒ๋ฆฌํฉ๋๋ค. ๋จ์ผ ํจ์ ํธ์ถ ๋ค์ ์จ๊ฒจ์ ธ ์๋๋ผ๋ ์ด๋ค ์ค ์ด๋ ๊ฒ๋ ๋น๋ ๋ฉ์๋์ ์์ด์๋ ์ ๋ฉ๋๋ค.
ํด๋น ๋
ผ๋ฆฌ์ ์ง์
์ ์ ๋น๋ ๋ฉ์๋์ ์์ด์๋ ์ ๋ฉ๋๋ค.
์ด๋ค ์ข ๋ฅ์ ์ด๊ธฐํ ๋ ผ๋ฆฌ๋ฅผ ๋น๋ ๋ฉ์๋์ ๋ฃ๋๋ก ๊ฐ์ํ๋ ๊ฒ์ ๋น๋ ๋ฉ์๋์์ ์์ ฏ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๋๋ก "๊ฐ์ "ํ๋ ๊ฒ๊ณผ ๊ฐ์ง ์์ต๋๋ค. ๋น๋ ๋ฐฉ๋ฒ์ ์ ์ฒด ์ด์ ๋ ๊ธฐ์กด ์ํ(๋ณ์ ์งํฉ)๋ฅผ ๊ฐ์ ธ์์ ๊ทธ๋ ค์ง๋ ์์ ฏ ํธ๋ฆฌ๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋๋ค.
๋ฐ๋๋ก, ๋๋ initState/didUpdateWidget ๋ฉ์๋ ๋ด๋ถ์ ์์ ฏ์ ๋น๋ํ๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋๋ก ๊ฐ์ํ๋ ๊ฒ๋ ๋ฐ๋ํฉ๋๋ค.
ํ์ฌ์ โโ๊ฐ์ด statefulwidget ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋๋ ๋งค์ฐ ๋ช ํํ ์ญํ ์ ํ๋ฉฐ ์์ ํ ๋ค๋ฅธ ๊ด์ฌ์ฌ๋ก ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ๋ ๊ฒ์ ๋งค์ฐ ์ฝ๊ณ ๊ฐ๋จํ๊ฒ ๋ง๋ญ๋๋ค.
๊ฐ๋ ์ ์ผ๋ก ์ฌ๊ธฐ์์ ์ค๋ช ํ๋ ๋ฌธ์ ๋ฅผ ์ดํดํ๊ธฐ ์์ํ์ง๋ง ์ฌ์ ํ ์ค์ ๋ฌธ์ ๋ก ๋ณด์ง ๋ชปํฉ๋๋ค. ์นด์ดํฐ ์ฑ์ด ์๋ ์ค์ ์๊ฐ ๋ง์์ ๋ฐ๊พธ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
์ฐธ๊ณ ๋ก ์ ๊ฐ ์ต๊ทผ์ ์คํํ Riverpod ์๋ ์ ์ฝ์ด ์๋ ๋งค์ฐ ๊ฐ๊ณ ๋ฆฌ ๊ฐ์ ์์ด๋์ด๊ฐ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์์ ํด๊ฒฐํฉ๋๋ค.
Consumer(
provider: provider,
builder: (context, value) {
return Consumer(
provider: provider2,
builder: (context, value2) {
return Text('$value $value2');
},
);
},
)
๋ค์์ ํจ์ผ๋ก์จ:
Consumer(
builder (context, watch) {
final value = watch(provider);
final value2 = watch(provider2);
},
)
watch
๋ฅผ ์กฐ๊ฑด๋ถ๋ก ํธ์ถํ ์ ์๋ ๊ณณ:
Consumer(
builder: (context, watch) {
final value = watch(provider);
if (something) {
final value2 = watch(provider2);
}
},
)
์ฌ์ฉ์ ์ ์ StatelessWidget
/ StatefulWidget
๊ธฐ๋ณธ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ Consumer
์์ ํ ์ ๊ฑฐํ ์๋ ์์ต๋๋ค.
class Example extends ConsumerStatelessWidget {
<strong i="21">@override</strong>
Widget build(ConsumerBuildContext context) {
final value = context.watch(provider);
final value2 = context.watch(provider2);
}
}
์ฃผ์ ๋ฌธ์ ๋ ์ด๊ฒ์ด ํ ์ข ๋ฅ์ ๊ฐ์ฒด์๋ง ํด๋น๋๋ฉฐ ๊ฐ์ฒด ์ธ์คํด์ค๊ฐ ์ฌ๊ตฌ์ถ ๊ฐ์ ์ผ๊ด๋ hashCode๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ ์ฌ์ค์ ์์กดํ์ฌ ์๋ํ๋ค๋ ๊ฒ์ ๋๋ค.
๊ทธ๋์ ์ฐ๋ฆฌ๋ ์ฌ์ ํ hooks์ ์ ์ฐ์ฑ๊ณผ๋ ๊ฑฐ๋ฆฌ๊ฐ ๋ฉ๋ค.
@rrousselGit ๋ด๊ฐ ํ์ฅํ์ง ์๊ณ ์๊ฐ StatelessWidget
/ StatefulWidget
์์
์ํ๊ณ ConsumerStatelessWidget ๊ฐ์ ๊ฒ์ ๋ง๋ค์ด, ๊ฐ์ ๊ฒ์ ๊ฐ์ง ์ ์์ต๋๋ค context.watch
์ ํ์ฅ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ฌ BuildContext
ํด๋์ค๋ฅผ ๋ง๋ค๊ณ ๊ณต๊ธ์๊ฐ InheritedWidgets์ ํจ๊ป watch ๊ธฐ๋ฅ์ ์ ๊ณตํ๋๋ก ํฉ๋๋ค.
๊ทธ๊ฑด ๋ค๋ฅธ ์ฃผ์ ์ ๋๋ค. ํ์ง๋ง ์ด ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ ์ผ๋ก InheritedWidgets์ ์์กดํ ์๋ ์์ต๋๋ค. https://github.com/flutter/flutter/issues/30062
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด InheritedWidgets๋ฅผ ์ฌ์ฉํ๋ฉด https://github.com/flutter/flutter/issues/12992 ๋ฐ https://github.com/flutter/flutter/pull/33213 ๋๋ฌธ์ ์ฐจ๋จ๋ฉ๋๋ค.
๊ฐ๋ ์ ์ผ๋ก ์ฌ๊ธฐ์์ ์ค๋ช ํ๋ ๋ฌธ์ ๋ฅผ ์ดํดํ๊ธฐ ์์ํ์ง๋ง ์ฌ์ ํ ์ค์ ๋ฌธ์ ๋ก ๋ณด์ง ๋ชปํฉ๋๋ค.
Flutter๋ฅผ SwiftUI์ ๋น๊ตํ๋ฉด ์ค์ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ด ๋ถ๋ช ํฉ๋๋ค.
Flutter์ ๋ค๋ฅธ ์ฌ๋๋ค์ด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ด์ฌํ ์ผํ๊ธฐ ๋๋ฌธ์ ๋ณด๊ธฐ๊ฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค. AnimatedBuilder, StreamBuilder, Consumer, AnimatedOpacity ๋ฑ ๊ฐ ํน์ ์ฌ๋ก์ ๋ํ ๋ํผ๊ฐ ์์ต๋๋ค. StatefulWidget์ ์ด๋ฌํ ์์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ ํธ๋ฆฌํฐ๋ฅผ ๊ตฌํํ๋ ๋ฐ ํ๋ฅญํ๊ฒ ์๋ํ์ง๋ง ๋๋ฌด ๋ฎ์ ์์ค์ ๋๋ค. ์ฌ์ฌ์ฉํ ์ ์๋ ๋๋ฉ์ธ ํน์ ๊ตฌ์ฑ ์์์ ๊ฒฝ์ฐ ๋ค์์ ํ ์คํธ ์ปจํธ๋กค๋ฌ, ์ ๋๋ฉ์ด์ ๋๋ ๋น์ฆ๋์ค ๋ก์ง์ด ์๊ตฌํ๋ ๋ชจ๋ ๊ฒ์ด ์์ ์ ์์ต๋๋ค. ์ผ๋ฐ์ ์ธ ํด๊ฒฐ์ฑ ์ ์ด์์ ๊นจ๋ฌผ๊ณ ๋ชจ๋ ์์ฉ๊ตฌ๋ฅผ ์์ฑํ๊ฑฐ๋ ์ ์คํ๊ฒ ๊ตฌ์ฑ๋ ๊ณต๊ธ์ ๋ฐ ์ฒญ์ทจ์ ํธ๋ฆฌ๋ฅผ ๋ง๋๋ ๊ฒ์ ๋๋ค. ์ด๋ค ์ ๊ทผ ๋ฐฉ์๋ ๋ง์กฑ์ค๋ฝ์ง ์์ต๋๋ค.
@rrousselGit์ด ๋งํ๋ ๊ฒ๊ณผ
์ํ ์ ์ง์ ๊ฒฝ์ฐ ๋ฌธ์ ๋ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ์๋ํ๋ ์ ์๋ ์ง๋ฃจํ๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด ์์
์
๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฑด ๊ทธ๋ ๊ณ , ํํฌ๊ฐ ์ด๊ฒ์ ์ ํ ํด๊ฒฐํ์ง ๋ชปํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ํํฌ๋ flutter์ ๋ด๋ถ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ๊ฐ๋ฅํ ์ ์ผํ ์ ๊ทผ ๋ฐฉ์์ผ ๋ฟ์ ๋๋ค.
StatefulWidget์ ์ด๋ฌํ ์์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ ํธ๋ฆฌํฐ๋ฅผ ๊ตฌํํ๋ ๋ฐ ํ๋ฅญํ๊ฒ ์๋ํ์ง๋ง, ๋ค์์ ํ ์คํธ ์ปจํธ๋กค๋ฌ, ์ ๋๋ฉ์ด์ ๋๋ ๋น์ฆ๋์ค ๋ก์ง์ด ์๊ตฌํ๋ ๋ชจ๋ ๊ฒ์ด ์์ ์ ์๋ ์ฌ์ฌ์ฉ ๋ถ๊ฐ๋ฅํ ๋๋ฉ์ธ ํน์ ๊ตฌ์ฑ ์์์๋ ๋๋ฌด ๋ฎ์ ์์ค์ ๋๋ค.
์ฌ์ฌ์ฉํ ์ ์๋ ๋๋ฉ์ธ ํน์ ๊ตฌ์ฑ ์์๋ฅผ ๋น๋ํ๋ ค๋ฉด ๋์ ์์ค์ ์์ ฏ์ด ํ์ํ๋ค๊ณ ๋งํ ๋ ํผ๋์ค๋ฝ์ต๋๋ค. ๋ณดํต์ ์ ๋ฐ๋์ ๋๋ค.
AnimatedBuilder, StreamBuilder, Consumer, AnimatedOpacity๋ ๋ชจ๋ ํน์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๊ตฌํํ๋ ์์ ฏ์ ๋๋ค. ํน์ ๋ ผ๋ฆฌ๊ฐ ์์ด์ ์ด๋ฌํ ์์ ์์ค ์์ ฏ์ ์ฌ์ฉํ ์ ์๋ ์์ ฏ์ด ํ์ํ ๊ฒฝ์ฐ์๋ ํ์ ์์ค API๋ก ๋๋กญ๋ค์ดํ์ฌ ๋๋ง์ ํน์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์์ ์์ฉ๊ตฌ๋ผ๊ณ ํ๋ ๊ฒ์ ๋ด ๊ณ ์ ํ ์์ ฏ์ด ์คํธ๋ฆผ, ๋คํธ์ํฌ ํธ์ถ, ์ปจํธ๋กค๋ฌ ๋ฑ์ ๊ณ ์ ํ ์กฐํฉ์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๊ตฌํํ๋ ๊ฒ์ ๋๋ค.
ํํฌ, ํํฌ์ ๊ฐ์ ๋์ ๋๋ ์ฌ์ง์ด "์๋ํ"๋ฅผ ์นํธํ๋ ๊ฒ์ ์์ ์์ฉ๊ตฌ ์ฝ๋๋ฅผ ์์ฑํ์ง ์๊ณ ๋ ๋๊ตฌ๋ ๊ฐ๊ณ ์ถ์ดํ๋ ์ฌ์ฌ์ฉํ ์ ์๋ ๋์ ์์ค์ ๋ ผ๋ฆฌ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ๋ฎ์ ์์ค์ ์์ ฏ์ด ํ์ํ๋ค๊ณ ๋งํ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
์ํ ์ ์ง์ ๊ฒฝ์ฐ ๋ฌธ์ ๋ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ์๋ํ๋ ์ ์๋ ์ง๋ฃจํ๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด ์์ ์ ๋๋ค.
๋ค์. ๋ค์์ ํ ์คํธ ์ปจํธ๋กค๋ฌ, ์ ๋๋ฉ์ด์ ๋๋ ๋น์ฆ๋์ค ๋ก์ง์์ ์๊ตฌํ๋ ๋ชจ๋ "__!
@rrousselGit์ด ๋งํ๋ ๊ฒ๊ณผ
์ ๋ 6-7๋ ์ ์ ios์ android ๊ฐ๋ฐ์ ํ์ต๋๋ค(Android๊ฐ ๋จธํฐ๋ฆฌ์ผ ๋์์ธ์ผ๋ก ์ ํํ์ ๋). ๊ทธ๋ฆฌ๊ณ ์ด ๊ด๋ฆฌ ๋ฐ ์ฌํ์ฉ ๋ณด๊ธฐ ์ค ์ด๋ค ๊ฒ๋ ๋ฌธ์ ๊ฐ ๋์๋ ๊ธฐ์ต์ด ์์ผ๋ฉฐ Flutter๊ฐ ๋ ์ข๊ฑฐ๋ ๋์๊ฒ ๋ณด์ด์ง ์์ต๋๋ค. ๋๋ ํ์ฌ์ ์ผ์ ๋ํด ๋งํ ์ ์๋ค. ๋๋ Swift์ Kotlin์ด ์ถ์๋์์ ๋ ๊ทธ๋ง๋๋ค.
StatefulWidgets์ ๊ฐ์ ๋ก ์์ฑํด์ผ ํ๋ ์์ฉ๊ตฌ๋ ์ฝ๋ ๊ธฐ๋ฐ์ ์ฝ 1%์ ๋๋ค. ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด๊ฐ์? ์ฝ๋์ ๋ชจ๋ ๋ผ์ธ์ ์ ์ฌ์ ์ธ ๋ฒ๊ทธ ์์ค์ด๋ฏ๋ก ํ์คํฉ๋๋ค. ๋ฒ๊ฑฐ๋กญ๋์? 15000์์ 200์ค์ ์ฝ๋๊ฐ ๋์ค๋์? ๋๋ ์ ๋ง๋ก ๊ทธ๋ ๊ฒ ์๊ฐํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ๋จ์ง ์ ์๊ฐ์ผ ๋ฟ์ ๋๋ค. Flutter์ ํ ์คํธ/์ ๋๋ฉ์ด์ ์ปจํธ๋กค๋ฌ์ธ focusnodes์๋ ๋ชจ๋ ๊ฐ์ ํ ์ ์๋ ๋ฌธ์ ๊ฐ ์์ง๋ง ์ฅํฉํ ๊ฒ์ ์๋๋๋ค.
๋๋ ์ฌ๋๋ค์ด ๋ฌด์์ ๊ฐ๋ฐํ์ฌ ๋๋ฌด ๋ง์ ์์ฉ๊ตฌ๋ฅผ ํ์๋ก ํ๋์ง ์ ๋ง ๊ถ๊ธํฉ๋๋ค.
์ฌ๊ธฐ ์ฃผ์ ์ค ์ผ๋ถ๋ฅผ ๋ค์ผ๋ฉด 1์ค ๋์ 5์ค์ ์ฝ๋๋ฅผ ๊ด๋ฆฌํ๋ ๊ฒ์ด 5๋ฐฐ ๋ ์ด๋ ค์ด ๊ฒ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค. ๊ทธ๋ ์ง ์๋ค.
์๋ฅผ ๋ค์ด ๊ฐ AnimationController์ ๋ํด initState ๋ฐ dispose๋ฅผ ์ค์ ํ๋ ๋์ ์ ํ ๋ฒ๋ง ์ํํ๊ณ ํด๋น ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ์ต๋๋ค. ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๊ฐ์ ์๋ฆฌ, ์ฌ์ฌ์ฉ์ฑ. ๋๋ ๋น๋ ๊ธฐ๋ฅ์ ํํฌ๋ฅผ ๋ฃ๋ ๊ฒ์ด ๋ฌธ์ ๊ฐ ์๋ค๋ ๋ฐ ๋์ํ์ง๋ง ๋ถ๋ช ํ ๋ ๋์ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
์ฌ๊ธฐ์ ๋ฌธ์ ๋ฅผ ๋ณด๋ ์ฌ๋๊ณผ ๋ณด์ง ๋ชปํ๋ ์ฌ๋์ ์ฐจ์ด์ ์ ์ ์๋ React, Swift, Kotlin๊ณผ ๊ฐ์ด ์ด์ ์ ํํฌ์ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๊ณ ํ์๋ ์์ Java์์ ์์ ํ๋ ๊ฒ๊ณผ ๊ฐ์ด ์ฌ์ฉํ์ง ์์๋ค๋ ๊ฒ์ ๋๋ค. ๋๋ ์๋๋ก์ด๋. ๋ด ๊ฒฝํ์ ๋ฐ๋ฅด๋ฉด ํ์ ํ ์ ์๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ํํฌ๋ฅผ ์๋ํ๊ณ ํ์ค ๋ฐฉ์์ผ๋ก ๋์๊ฐ ์ ์๋์ง ํ์ธํ๋ ๊ฒ์ ๋๋ค. ์ข ์ข ๋ง์ ์ฌ๋๋ค์ด ์ ๊ฒฝํ์ ๊ทธ๋ ๊ฒ ํ ์ ์์ต๋๋ค. ์ฌ์ฉํด๋ณด๋ฉด ์๋๋ค.
์ด๋ฅผ ์ํด ์ ๋ ์์ ํ๋ก์ ํธ์ ๋ํด flutter_hooks๋ฅผ ์ฌ์ฉํ๊ณ ์ด๋ป๊ฒ ์๋ํ๋์ง ํ์ธํ ๋ค์ ๊ธฐ๋ณธ ๋ฐฉ์์ผ๋ก ๋ค์ ์คํํ๋ ๋ฐ ํ์์ ์ธ ์ฌ๋๋ค์ ๊ถ์ฅํฉ๋๋ค. @Hixie ์ ์ ์์ฒ๋ผ ์ฝ์ ์ ์๋ ์ฑ ๋ฒ์ ์ ๋ง๋๋ ๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ต๋๋ค(๋ฌผ๋ก ๊ทธ๋ ๊ฒ ํ ๊ฒ์ด์ง๋ง). ์ ๋ ๊ฐ ์ฌ๋์ด ์ฐจ์ด์ ์ ํ์ธํ๊ธฐ ์ํด ์ง์ ํํฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๊ณ ๋ฏฟ์ต๋๋ค.
@Hixie ์ ์ ์์ฒ๋ผ ์ฝ์ ์ ์๋ ์ฑ ๋ฒ์ ์ ๋ง๋๋ ๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ต๋๋ค(๋ฌผ๋ก ๊ทธ๋ ๊ฒ ํ ๊ฒ์ด์ง๋ง). ์ ๋ ๊ฐ ์ฌ๋์ด ์ฐจ์ด์ ์ ํ์ธํ๊ธฐ ์ํด ์ง์ ํํฌ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๊ณ ๋ฏฟ์ต๋๋ค.
๋๋ ๊ณต๊ธ์๋ฅผ ์๋ํ๋ ๋ฐ ๋ฉฐ์น ์ ๋ญ๋นํ๊ณ ๋ธ๋ก์ ์๋ํ๋ ๋ฐ ๋ ๋ง์ ๋ ์ ๋ณด๋์ต๋๋ค. ๋๋ ๊ทธ ์ค ์ด๋ ๊ฒ๋ ์ข์ ์๋ฃจ์ ์ด๋ผ๋ ๊ฒ์ ์ฐพ์ง ๋ชปํ์ต๋๋ค. ๊ทธ๊ฒ์ด ๋น์ ์ ์ํด ์๋ํ๋ค๋ฉด, ์ข์ต๋๋ค.
๋ ์ฌ์ง์ด ๋น์ ์ด ๊ฒช๊ณ ์๋ ๋ฌธ์ ์ ์ ์ ๋ ์๋ฃจ์ ์ ์๋ํ๊ธฐ ์ํด์๋, ๋น์ ์ ๊ทธ๊ฒ์ ์ด์ ์ ์ฆ๋ช ํด์ผํฉ๋๋ค. ํ๋ฌํฐ ํํฌ๊ฐ ์๋ ์์ ๋ฅผ ์ดํด๋ณด๊ณ ๊ตฌํ์ ์ดํด๋ณด์์ต๋๋ค. ๊ทธ๋ฅ ์ซ๋ค.
์ด๋ค ์์ฉ๊ตฌ ๊ฐ์ ์ฝ๋๊ฐ ํ๋ ์์ํฌ์ ์ถ๊ฐ๋๋๋ผ๋ Stateful/StatelessWidget์ด ๋ณ๊ฒฝ๋์ง ์์ ์ํ๋ก ์ ์ง๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ์ด ๋ํ์ ๋ ์ด์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
ํํฌ์ ๋ํ ์ด์ผ๊ธฐ โโ์์ด Dart๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ ๊ฐ์์ ์ธ๊ณ์์ ๋ค์ ์์ํ๊ฒ ์ต๋๋ค.
๋ ผ์๋ ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
Widget build(context) {
return ValueListenableBuilder<String>(
valueListenable: someValueListenable,
builder: (context, value, _) {
return StreamBuilder<int>(
stream: someStream,
builder: (context, value2) {
return TweenAnimationBuilder<double>(
tween: Tween(...),
builder: (context, value3) {
return Text('$value $value2 $value3');
},
);
},
);
},
);
}
์ด ์ฝ๋๋ ์ฝ์ ์ ์์ต๋๋ค.
๊ตฌ๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํ๋ ์ ํค์๋๋ฅผ ๋์ ํ์ฌ ๊ฐ๋ ์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค.
Widget build(context) {
final value = keyword ValueListenableBuilder(valueListenable: someValueListenable);
final value2 = keyword StreamBuilder(stream: someStream);
final value3 = keyword TweenAnimationBuilder(tween: Tween(...));
return Text('$value $value2 $value3');
}
์ด ์ฝ๋๋ ํจ์ฌ ๋ ์ฝ๊ธฐ ์ฝ๊ณ ํํฌ์ ๊ด๋ จ์ด ์์ผ๋ฉฐ ์ ํ ์ฌํญ์ด ์์ต๋๋ค.
๊ฐ๋
์ฑ ํฅ์์ ์ค ์๊ฐ ์๋๋ผ ์์ ๋ฐ ๋ค์ฌ์ฐ๊ธฐ์ ๊ดํ ๊ฒ์
๋๋ค.
์์:
Widget build(context) {
return Scaffold(
body: StreamBuilder(
stream: stream,
builder: (context, value) {
return Consumer<Value2>(
builder: (context, value2, child) {
return Text('${value.data} $value2');
},
);
},
),
);
}
์ฐ๋ฆฌ๋ ๋ค์์ ๊ฐ์ง ์ ์์ต๋๋ค:
Widget build(context) {
return Scaffold(
body: {
final value = keyword StreamBuilder(stream: stream);
final value2 = keyword Consumer<Value2>();
return Text('${value.data} $value2');
}
);
}
์ด๊ฒ์ด ๊ด๋ จ๋ ์ด์ ๋ ๋น๋๊ฐ ๊ธฐ์ ์ ์ผ๋ก ์ํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ๋ฌ๋ ๋ฌธ์ ๋ https://github.com/flutter/flutter/issues/51752#issuecomment -669626522 ์ฃผ์๊ณผ ๊ฐ์ด _๋ง์_ ๋น๋๋ฅผ ์ฌ์ฉํ ๊ณํ์ด๋ผ๋ฉด ์ฝ๋๋ฅผ ์ฝ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ ๋ค๋ ๊ฒ์ ๋๋ค.
์ด ์๋ก์ด ๊ตฌ๋ฌธ์ผ๋ก ๊ฐ๋ ์ฑ ๋ฌธ์ ๋ฅผ ์์ ํ์ต๋๋ค. ๋ฐ๋ผ์ ๋ ๋ง์ ๊ฒ์ ๋น๋๋ก ์ถ์ถํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์ด ์ฃผ์์ ์ธ๊ธ๋ useFilter
๋ ๋ค์๊ณผ ๊ฐ์ ์ ์์ต๋๋ค.
FilterBuilder(
debounceDuration: const Duration(seconds: 2),
builder: (context, filter) {
return TextField(onChange: (value) => filter.value = value);
}
)
๊ทธ๋ฐ ๋ค์ new ํค์๋์ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค.
class ChatScreen extends HookWidget {
const ChatScreen({Key key}) : super(key: key);
<strong i="15">@override</strong>
Widget build(BuildContext context) {
final filter = keyword FilterBuilder(debounceDuration: const Duration(seconds: 2));
final userId = keyword Consumer(authProvider).userId;
final chatId = keyword Consumer(selectedChatProvider);
final chat = keyword QueryBuilder(ChatQuery(userId: userId, chatId: chatId, filter: filter.value));
return Column(
children: [
Searchbar(onChanged: (value) => filter.value = value),
Expanded(
child: ChatList(chat: chat),
),
],
);
}
}
ํจ์์์ Builders ์กฐํฉ์ ์ถ์ถํ์ฌ ์ด๋ฌํ ํค์๋๋ก ๋์ผํ ์์ ์ ์ํํ ์ ์์ต๋๋ค.
Builder<Chat> ChatBuilder() {
final filter = keyword FilterBuilder(debounceDuration: const Duration(seconds: 2));
final userId = keyword Consumer(authProvider).userId;
final chatId = keyword Consumer(selectedChatProvider);
final chat = keyword QueryBuilder(ChatQuery(userId: userId, chatId: chatId, filter: filter.value));
return Builder(chat);
}
class ChatScreen extends HookWidget {
const ChatScreen({Key key}) : super(key: key);
<strong i="21">@override</strong>
Widget build(BuildContext context) {
final chat = keyword ChatBuilder();
return Column(
children: [
Searchbar(onChanged: (value) => filter.value = value),
Expanded(
child: ChatList(chat: chat),
),
],
);
}
}
๋ถ๋ช ํ, ๊ทธ๋ฌํ ๊ตฌ๋ฌธ์ ๋ชจ๋ ์๋ฏธ์ ๋ํด ๋ง์ ์๊ฐ์ด ์ฃผ์ด์ง์ง ์์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ๊ธฐ๋ณธ์ ์ธ ์๊ฐ์ ๋๋ค.
ํํฌ๊ฐ ์ด ๊ธฐ๋ฅ์
๋๋ค.
ํํฌ์ ํ๊ณ๋ ์ธ์ด ๊ธฐ๋ฅ์ด ์๋ ํจํค์ง๋ก ๊ตฌํ๋๊ธฐ ๋๋ฌธ์ ์กด์ฌํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ํค์๋๋ use
keyword StreamBuilder
๊ฐ use StreamBuilder
๊ฐ ๋๋ use
์ด๋ฉฐ ๊ถ๊ทน์ ์ผ๋ก useStream
๋ก ๊ตฌํ๋ฉ๋๋ค.
์ด ์ฝ๋๋ ํจ์ฌ ๋ ์ฝ๊ธฐ ์ฝ์ต๋๋ค.
์ด๊ฒ์ ์๊ฒฌ์ ๋ฌธ์ ๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ค ์ฌ๋๋ค์ ๋น์ ์ด ์ค๋ช ํ๋ ๋ฒ์ ์ด ๋ ์ฝ๊ธฐ ์ฝ๋ค๊ณ ์๊ฐํ๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. ๊ฐ์ธ์ ์ผ๋ก ๋๋ ํจ์ฌ ๋ ๋ช ์์ ์ธ ๋ง๋ฒ์ด ์๋ ๋ฒ์ ์ ์ ํธํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ๋ ๋ฒ์งธ ์คํ์ผ์ ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ๋ฐ ๋ฐ๋ํ์ง ์์ต๋๋ค.
์ฆ, ๋ค์ ๋จ๊ณ๋ @TimWhiting ์ ์ฑ(https://github.com/TimWhiting/local_widget_state_approaches/blob/master/lib/stateful/counter.dart)์์ ์์ ํ์ฌ ๋ชจ๋ ๋ฌธ์ ๊ฐ ์๋ ์ฑ์ผ๋ก ๋ง๋๋ ๊ฒ์ ๋๋ค. ํด๊ฒฐํ๊ณ ์ ํฉ๋๋ค.
๊ทธ ๊ฐ์น๋ฅผ ์ํด https://github.com/flutter/flutter/issues/51752#issuecomment -670959424 React์ Hooks์ ๋ํ ์๊ฐ๊ณผ ๊ฑฐ์ ์ ์ฌํฉ๋๋ค. Builder ํจํด์ React์์ ๋๋ฆฌ ์ฌ์ฉ๋์๋ Render Props ํจํด๊ณผ ๋์ผํด ๋ณด์ด์ง๋ง ์ ์ฌํ๊ฒ ๊น์ ํธ๋ฆฌ๋ก ์ด์ด์ก์ต๋๋ค. ๋์ค์ @trueadm ์ Render Props์ ๋ํ ๊ตฌ๋ฌธ ์คํ ์ ์ ์ํ์ผ๋ฉฐ ๋์ค์ Hooks๋ก ์ด์ด์ก์ต๋๋ค(๋ถํ์ํ ๋ฐํ์ ์ค๋ฒํค๋ ์ ๊ฑฐ).
`Widget build(context) {
return ValueListenableBuilder<String>(
valueListenable: someValueListenable,
builder: (context, value, _) {
return StreamBuilder<int>(
stream: someStream,
builder: (context, value2) {
return TweenAnimationBuilder<double>(
tween: Tween(...),
builder: (context, value3) {
return Text('$value $value2 $value3');
},
);
},
);
},
);
}`
๊ฐ๋ ์ฑ๊ณผ ๋ค์ฌ์ฐ๊ธฐ๊ฐ ๋ฌธ์ ์ธ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ๋ค์ ์์ฑํ ์ ์์ต๋๋ค.
<strong i="8">@override</strong>
Widget build(context) {
return ValueListenableBuilder<String>(
valueListenable: someValueListenable,
builder: (context, value, _) => buildStreamBuilder(value),
);
}
StreamBuilder<int> buildStreamBuilder(String value) => StreamBuilder<int>(
stream: someStream,
builder: (context, value2) => buildTweenAnimationBuilder(value, value2),
);
Widget buildTweenAnimationBuilder(String value, AsyncSnapshot<int> value2) =>
TweenAnimationBuilder<double>(
duration: Duration(milliseconds: 500),
tween: Tween(),
builder: (context, value3, _) => Text('$value $value2 $value3'),
);
๊ธฐ๋ฅ์ด ํ์ํ์ง ์๊ฑฐ๋ ์ฌ์ฌ์ฉ์ด ํ์ํ ๊ฒฝ์ฐ ์์ ฏ์ผ๋ก ์ถ์ถํ์ญ์์ค.
class NewWidget extends StatelessWidget {
var someValueListenable;
var someStream;
<strong i="12">@override</strong>
Widget build(context) {
return ValueListenableBuilder<String>(
valueListenable: someValueListenable,
builder: (context, value, _) {
return MyStreamedWidget(value, someStream);
},
);
}
}
class MyStreamedWidget extends StatelessWidget {
const MyStreamedWidget(
this.value,
this.someStream, {
Key key,
}) : super(key: key);
final String value;
final Stream someStream;
<strong i="13">@override</strong>
Widget build(BuildContext context) {
return StreamBuilder<int>(
stream: someStream,
builder: (context, value2) => MyAnimatedWidget(value, value2),
);
}
}
class MyAnimatedWidget extends StatelessWidget {
final String value;
final AsyncSnapshot<int> value2;
const MyAnimatedWidget(
this.value,
this.value2, {
Key key,
}) : super(key: key);
<strong i="14">@override</strong>
Widget build(BuildContext context) {
return TweenAnimationBuilder<double>(
tween: Tween(),
builder: (context, value3, _) {
return Text('$value $value2 $value3');
},
);
}
}
๊ทํ์ ์์๋ ์๋ก์ด ํค์๋ ๋๋ ๊ธฐ๋ฅ์ ๋ณด์ฆํ๋ ํญ๋ชฉ์ด ์์ต๋๋ค.
๋ฌด์จ ๋ง์ ํ๋ ค๋์ง ์๊ณ ์์ต๋๋ค. '๊ฐ' ๋ณ์๋ ๋ชจ๋ ์์ ฏ/ํจ์ ํธ์ถ์ ํตํด ์ ๋ฌ๋์ด์ผ ํ์ง๋ง ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ค๊ณํ ๋ฐฉ๋ฒ์ ๊ฒฐ๊ณผ์ผ ๋ฟ์ ๋๋ค. ์ฌ์ฉ ์ฌ๋ก์ ๋ฐ๋ผ "๋น๋" ๋ฉ์๋์ ์ฌ์ฉ์ ์ง์ ์์ ฏ์ ๋ชจ๋ ์ฌ์ฉํ์ฌ ์ฝ๋๋ฅผ ๋ถ๋ฆฌํ๊ณ ๋์ผํ ๋ณ์๋ฅผ ์ธ ๋ฒ์ ํธ์ถ ์ฒด์ธ์ ์ ๋ฌํ ํ์๊ฐ ์์ต๋๋ค.
์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ฝ๋๋ ์ธ๋ถ ๋ถ์์ฉ(์: InheritedWidgets ๋๋ (๋ฐ)์ ์ญ ์ํ)์ ๊ฐ๋ฅํ ํ ์ ๊ฒ ์์กดํ ๋ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
@Rudiksz ์ฌ๊ธฐ ํ ๋ก ์ ์๋ฌด ๊ฒ๋ ์ถ๊ฐํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํ๋ฃจ ์ข ์ผ ์ํํ๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ์ํํ๊ธฐ ์ํ ์ ๋ต์ ์๊ณ ์์ต๋๋ค. ๋ฌธ์ ๊ฐ ๋์ง ์๋๋ค๊ณ ์๊ฐ๋๋ฉด ๊ทธ๋๋ก ๊ณ์ ์ฌ์ฉํ๋ฉด ๋๋ฉฐ ์ด๋ ์ ํ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค.
์ด๊ฒ์ ๊ทผ๋ณธ์ ์ธ ๊ณ ํต์ผ๋ก ๋ณด๋ ๋ง์ ์ฌ๋๋ค์ด ๋ถ๋ช ํ ์์ผ๋ฉฐ ์๋ค๋ก ์ํํ๋ ๊ฒ์ ๋ฌด์๋ฏธํฉ๋๋ค. ๋น์ ์ ๋ค์ํ ์ฃผ์ฅ์ ํตํด ์ฌ๋๋ค์ด ์ํ๋ ๊ฒ์ ์ํ์ง ์๊ฑฐ๋ ๋ค๋ฅธ ์ฌ๋์ ๋ง์์ ๋ฐ๊พธ์ง ์๋๋ค๋ ๊ฒ์ ์ค๋ํ์ง ์์ ๊ฒ์ ๋๋ค. ์ด ํ ๋ก ์ ์ฐธ์ฌํ๋ ๋ชจ๋ ์ฌ๋๋ค์ ๋ถ๋ช ํ Flutter์์ ์๋ฐฑ ๋๋ ์์ฒ ์๊ฐ์ ์์ ์ ๋ฒจํธ ์๋์ ๋๊ณ ์์ผ๋ฉฐ, ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ์ด์ ๋ํด ๋์ํด์ผ ํ๋ค๊ณ ๊ธฐ๋ํ์ง ์์ต๋๋ค.
์ด๊ฒ์ ์๊ฒฌ์ ๋ฌธ์ ๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ค ์ฌ๋๋ค์ ๋น์ ์ด ์ค๋ช ํ๋ ๋ฒ์ ์ด ๋ ์ฝ๊ธฐ ์ฝ๋ค๊ณ ์๊ฐํ๋ค๋ ๋ฐ ๋์ํฉ๋๋ค. ๊ฐ์ธ์ ์ผ๋ก ๋๋ ํจ์ฌ ๋ ๋ช ์์ ์ธ ๋ง๋ฒ์ด ์๋ ๋ฒ์ ์ ์ ํธํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ๋ ๋ฒ์งธ ์คํ์ผ์ ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ๋ฐ ๋ฐ๋ํ์ง ์์ต๋๋ค.
์๊ฒฌ์ ๋ฌธ์ ๋ผ๋ฉด ์๋นํ ํ์ชฝ์ผ๋ก ์น์ฐ์ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
value1
๋ฐ value2
์ธ ํธ๋ฆฌ์์ ๋์ค์ ์ฌ์ฉ๋ ๋งค์ฐ ์ค์ํ ๋ณ์ ์ด๋ฆ์ ๋๋
ํํ๊ณ ๋ค๋ฅธ ํ๋๋ ๋น๋ ๋งจ ์๊ณผ ์ค์์ ์์ต๋๋ค. ์ด๊ฒ์ ๋ช
ํํ ๊ตฌ๋ฌธ ๋ถ์ / ์ ์ง ๊ด๋ฆฌ์ ์น๋ฆฌ์
๋๋ค.์ผ๋ฐ์ ์ธ ์๋ฏธ์์ ๋๋ ์ด๊ฒ์ด ์๋ง๋ ์ทจํฅ์ ๋ฌธ์ ๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ Flutter๋ ํนํ ์ผ๋ฐ์ ์ผ๋ก ๋ผ์ธ ์, ๋ค์ฌ์ฐ๊ธฐ ๋ฐ ์ ํธ: ์ก์ ๋น์จ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๋๋ Dart ์ฝ๋์์ ์ ์ธ์ ์ผ๋ก ํธ๋ฆฌ๋ฅผ ํ์ฑํ๋ ๊ธฐ๋ฅ์ ์ ๋์ ์ผ๋ก _์ฌ๋_ํ์ง๋ง, ํนํ ์ฌ๋ฌ ๊ณ์ธต์ ๋ํ๋ ๋น๋์ ์์กดํ ๋ ๋งค์ฐ ์ฝ๊ธฐ ์ด๋ ต๊ณ ์ฅํฉํ ์ฝ๋๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ฐ๋ฆฌ๊ฐ ์ด ์ธ์์ ๊ณ์ํ๊ณ ์๋ Flutter ์์ฒด์ ๋งฅ๋ฝ์์ ์ด๋ฌํ ์ข ๋ฅ์ ์ต์ ํ๋ ๋ค์ ๋ง์ฐํ ์ผ๋ฐ์ ์ธ ์ฅํฉํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์ ๋ง ํ๋ฅญํ ๋๊ตฌ๋ฅผ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ ํฌ๋ฌ ๊ธฐ๋ฅ์ ๋๋ค.
TL;DR - Flutter์์ ๋ค์ฌ์ฐ๊ธฐ์ ์ค ์๋ฅผ ํฌ๊ฒ ์ค์ธ ๋ชจ๋ ๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก Flutter ๊ณ ์ ์ ์ค ์์ ๋ค์ฌ์ฐ๊ธฐ๊ฐ ๋ง๊ธฐ ๋๋ฌธ์ ๋ ๋ฐฐ๋ก ๊ฐ์น๊ฐ ์์ต๋๋ค.
@Rudiksz ์ฌ๊ธฐ ํ ๋ก ์ ์๋ฌด ๊ฒ๋ ์ถ๊ฐํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํ๋ฃจ ์ข ์ผ ์ํํ๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ์ํํ๊ธฐ ์ํ ์ ๋ต์ ์๊ณ ์์ต๋๋ค. ๋ฌธ์ ๊ฐ ๋์ง ์๋๋ค๊ณ ์๊ฐ๋๋ฉด ๊ทธ๋๋ก ๊ณ์ ์ฌ์ฉํ๋ฉด ๋๋ฉฐ ์ด๋ ์ ํ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค.
ํต์ฌ ํ๋ ์์ํฌ์ ๋ณ๊ฒฝ ์ฌํญ์ธ ๊ฒฝ์ฐ๋ฅผ ์ ์ธํ๊ณ ์ ์๊ฒ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๊น?
์ด๊ฒ์ ๊ทผ๋ณธ์ ์ธ ๊ณ ํต์ผ๋ก ๋ณด๋ ๋ง์ ์ฌ๋๋ค์ด ๋ถ๋ช ํ ์์ผ๋ฉฐ ์๋ค๋ก ์ํํ๋ ๊ฒ์ ๋ฌด์๋ฏธํฉ๋๋ค. ๋น์ ์ ๋ค์ํ ์ฃผ์ฅ์ ํตํด ์ฌ๋๋ค์ด ์ํ๋ ๊ฒ์ ์ํ์ง ์๊ฑฐ๋ ๋ค๋ฅธ ์ฌ๋์ ๋ง์์ ๋ฐ๊พธ์ง ์๋๋ค๋ ๊ฒ์ ์ค๋ํ์ง ์์ ๊ฒ์ ๋๋ค. ์ด ํ ๋ก ์ ์ฐธ์ฌํ๋ ๋ชจ๋ ์ฌ๋๋ค์ ๋ถ๋ช ํ Flutter์์ ์๋ฐฑ ๋๋ ์์ฒ ์๊ฐ์ ์์ ์ ๋ฒจํธ ์๋์ ๋๊ณ ์์ผ๋ฉฐ, ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ์ด์ ๋ํด ๋์ํด์ผ ํ๋ค๊ณ ๊ธฐ๋ํ์ง ์์ต๋๋ค.
๋ง์์ ์ด ๋ง์ ์ด๋ฏธ ์์์ด ๋ง๊ณ ์ฃฝ์์ผ๋ ๋์ด์ ๋๊ธ์ ๋ต๊ธ ๋ฌ์ง ์๊ฒ ์ต๋๋ค.
๋น๋๋ ๊ธฐ์ ์ ์ผ๋ก ์ํ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ๋ฌธ์ ๋ ์ฝ๋๋ฅผ ์ ์ฝ์ง ๋ชปํ๊ฒ ๋ง๋ ๋ค๋ ๊ฒ์ ๋๋ค.
์ด๊ฒ์ ๊ทธ๊ฒ์ ์๋ฒฝํ๊ฒ ์ง์ ํฉ๋๋ค. Flutter ์ฉ์ด๋ก ์๊ฐํ๋ ค๋ฉด ๋จ์ผ ๋ผ์ธ ๋น๋๊ฐ ํ์ํฉ๋๋ค.
์์ญ ๊ฐ์ ํญ๊ณผ ์ค์ด ํ์ํ์ง ์์ง๋ง ์ผ๋ถ ์ฌ์ฉ์ ์ ์ ์์ฉ๊ตฌ๊ฐ ์์ ฏ ์๋ช ์ฃผ๊ธฐ์ ์ฐ๊ฒฐ๋๋๋ก ํ์ฉํ๋ ๋น๋.
"๋ชจ๋ ๊ฒ์ด ์์ ฏ์ด๋ค"๋ผ๋ ์ฃผ๋ฌธ์ ํนํ ์ฌ๊ธฐ์ ์ข์ ๊ฒ์ด ์๋๋๋ค. ๋น๋์ ๊ด๋ จ ์ฝ๋๋ ์ผ๋ฐ์ ์ผ๋ก ์ค์ ์ํ๊ณผ ๋น๋ fxn์ ํ์ํ ์ํ๋ฅผ ๋ฐํํ๋ ๊ฒ์ ๋๋ค. ๋ชจ๋ ๋จ์ผ ์ค ๋ฐ๊ฟ๊ณผ ํญ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฌด์๋ฏธํฉ๋๋ค.
ํต์ฌ ํ๋ ์์ํฌ์ ๋ณ๊ฒฝ ์ฌํญ์ธ ๊ฒฝ์ฐ๋ฅผ ์ ์ธํ๊ณ ์ ์๊ฒ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๊น?
@Rudiksz ์๋ฌด๋ ์ฐ๋ฆฌ๊ฐ Stateful ์์ ฏ์ ๋ณ๊ฒฝํ์๊ณ ์ ์ํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ํ๋ ๊ฒฝ์ฐ ํญ์ ํ์ฌ ํํ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ์๊ฐํด ๋ผ ์ ์๋ ์๋ฃจ์
์ด ๋ฌด์์ด๋ ๋ณ๊ฒฝ ์์ด Stateful ์์ ฏ์ ์ฌ์ฉํ๊ฑฐ๋ ์์ ํ ๋ค๋ฅธ ์ ํ์ ์์ ฏ์ ์ฌ์ฉํฉ๋๋ค. Stateful ์์ ฏ์ด ๋์๋ค๊ณ ๋งํ๋ ๊ฒ์ด ์๋๋ผ ๋ ๊ตฌ์ฑ ๊ฐ๋ฅํ ์์ ฏ ์ํ๋ฅผ ํ์ฉํ๋ ๋ค๋ฅธ ์ ํ์ ์์ ฏ์ ์ํ๋ค๋ ๊ฒ์
๋๋ค. ์ฐ๊ฒฐ๋ ํ๋์ ์ํ ๊ฐ์ฒด ๋์ ์ฌ๋ฌ ์ํ ๊ฐ์ฒด์ ๋ณ๊ฐ์ด์ง๋ง ํด๋น ์ํ ๊ฐ์ฒด์ ์ก์ธ์คํ ์ ์๋ ํ๋์ ๋น๋ ๊ธฐ๋ฅ์ ํฌํจํ๋ ์ํ ์ ์ฅ ์์ ฏ์ผ๋ก ์๊ฐํ์ญ์์ค. ์ด๋ฐ ์์ผ๋ก initState
๋ฐ dispose
์ด๋ฏธ ๊ตฌํ๋์ด ์๋ ์ผ๋ฐ ์ํ ๋นํธ(ํด๋น ์ํ์ ์ฐ๊ฒฐ๋ ์ํ ๋
ผ๋ฆฌ์ ํจ๊ป)๋ฅผ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ณธ์ง์ ์ผ๋ก ๋ณด๋ค ๋ชจ๋ํ๋ ์ํ๋ก, ๋ค์ํ ์ํฉ์์ ๋ค์ํ ๋ฐฉ์์ผ๋ก ๊ตฌ์ฑ๋ ์ ์์ต๋๋ค. ๋ค์ ๋งํ์ง๋ง, ์ด๊ฒ์ ๊ตฌ์ฒด์ ์ธ ์ ์์ด ์๋๋ผ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ์๊ฐํ ์๋ ์์ต๋๋ค. ์๋ง๋ flutter
์ ๊ฐ์ ์๋ฃจ์
์ผ๋ก ๋ฐ๋ ์ ์์ง๋ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
์ฆ, ๋ค์ ๋จ๊ณ๋ @TimWhiting ์ ์ฑ(https://github.com/TimWhiting/local_widget_state_approaches/blob/master/lib/stateful/counter.dart)์์ ์์ ํ์ฌ ๋ชจ๋ ๋ฌธ์ ๊ฐ ์๋ ์ฑ์ผ๋ก ๋ง๋๋ ๊ฒ์ ๋๋ค. ํด๊ฒฐํ๊ณ ์ ํฉ๋๋ค.
์ด ๋ฌธ์ ๋ ๋ณธ์ง์ ์ผ๋ก ์์ฒ ์ปท์ ์ฃฝ์ ์ค ํ๋์ด๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๊น๋ค๋กญ์ต๋๋ค. ๊ทธ๊ฒ์ ๋จ์ง ๋ถํ๋ฆผ์ ์ถ๊ฐํ๊ณ ์ฝ๋๋ฒ ์ด์ค ์ ์ฒด์์ ๊ฐ๋ ์ฑ์ ๊ฐ์์ํต๋๋ค. ์ ์ฒด ํด๋์ค๊ฐ 100์ค ๋ฏธ๋ง์ด๊ณ ์ ๋ฐ์ด ์ ๋๋ฉ์ดํฐ ์ปจํธ๋กค๋ฌ๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์์ ์์ ฏ์์ ๊ทธ ์ํฅ์ด ๊ฐ์ฅ ์ฌํ๊ฒ ๋๊ปด์ง๋๋ค. ๋ฐ๋ผ์ ์ด ์์ ์ค 30๊ฐ๋ฅผ ๋ณด๋ ๊ฒ์ด ๋ฌด์์ ๋ณด์ฌ์ค์ง ๋ชจ๋ฅด์ง๋ง 1๊ฐ๋ ๊ทธ๋ ์ง ์์ต๋๋ค.
์ค์ ๋ก ์ด๊ฒ์ ์ฐจ์ด์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
<strong i="10">@override</strong>
Widget build(BuildContext context) {
final controller = get AnimationController(vsync: this, duration: widget.duration);
//do stuff
}
์ด:
AnimationController _controller;
<strong i="14">@override</strong>
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: widget.duration);
}
<strong i="15">@override</strong>
void didUpdateWidget(Example oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.duration != oldWidget.duration) {
_controller.duration = widget.duration;
}
}
<strong i="16">@override</strong>
void dispose() {
_controller.dispose();
super.dispose();
}
<strong i="17">@override</strong>
Widget build(BuildContext context) {
//Do Stuff
}
์ด๊ฒ๋ณด๋ค ๋ ์ ์ค๋ช ํ ์ ์๋ ๋ฐฉ๋ฒ์ ์์ต๋๋ค. ์ด ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋ชจ๋ ์ปจํธ๋กค๋ฌ ์ ํ ๊ฐ์ฒด๋ก ํ์ฅํ ์ ์์ต๋๋ค. AnimatorController, FocusController ๋ฐ TextEditingController๋ ์๋ง๋ ์ผ์์ ์ธ ์ฌ์ฉ์์ ๊ด๋ฆฌํ๊ธฐ ๊ฐ์ฅ ์ผ๋ฐ์ ์ด๊ณ ์ฑ๊ฐ์ ๊ฒ๋ค์ผ ๊ฒ์ ๋๋ค. ์ด์ ์ด ์ค 50๊ฐ ๋๋ 100๊ฐ๋ฅผ ๋ด ์ฝ๋ ๊ธฐ๋ฐ ์ ์ฒด์ ๋ฟ๋ ธ์ต๋๋ค.
๋ฌผ๋ก ์ด๊ฒ์ ์ปค์คํ ์ปจํธ๋กค๋ฌ๋ก ํ์ฅํ ์๋ ์์ต๋๋ค. ์ปจํธ๋กค๋ฌ๋ฅผ ์ฌ์ฉํ๋ ์ ์ฒด ๊ฐ๋ ์ Flutter์์ ๊ทธ๋ค์ง ๋งค๋ ฅ์ ์ด์ง ์์ต๋๋ค. ์ด๋ฌํ ๋ฐฉ์์ผ๋ก ์ปจํธ๋กค๋ฌ๋ฅผ ๋ถํธ์คํธ๋ฉ, ๊ด๋ฆฌ ๋ฐ ํ๊ดดํด์ผ ํ๋ค๋ ๊ฒ์ ์๊ณ ์๊ธฐ ๋๋ฌธ์ ์ฑ๊ฐ์๊ณ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ์ต๋๋ค. ์ง์ ๋ง๋๋ ๊ฒ์ ํผํ๊ณ ๋์ ๋ง์ถคํ StatefulWidget/Builder๋ฅผ ์์ฑํ๋๋ก ํฉ๋๋ค. ๋น๋์ ๊ฐ๋ ์ฑ ๋ฌธ์ ๊ฐ ์๊ฑฐ๋ ์ต์ํ ํจ์ฌ ๋ ์ฅํฉํ๊ณ ๊ณต๋ฐฑ์ด ๋ง๊ธฐ ๋๋ฌธ์ ์ปจํธ๋กค๋ฌ ์ ํ ๊ฐ์ฒด๊ฐ ์ฌ์ฉํ๊ธฐ ์ฝ๊ณ ๋ ๊ฐ๋ ฅํ๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
๊น๋ค๋กญ๋ค
๋ค, API ๋์์ธ์ ๊น๋ค๋กญ์ต๋๋ค. ๋ด ์ธ์์ ์ค์ ๊ฒ์ ํ์ํฉ๋๋ค.
๋ฐ๋ผ์ ์ด ์์ ์ค 30๊ฐ๋ฅผ ๋ณด๋ ๊ฒ์ด ๋ฌด์์ ๋ณด์ฌ์ค์ง ๋ชจ๋ฅด์ง๋ง 1๊ฐ๋ ๊ทธ๋ ์ง ์์ต๋๋ค.
๋์์ด ๋ ๊ฒ์ 30๊ฐ์ ์์ ๊ฐ ์๋๋ผ "์, ๋ฌผ๋ก , ์ด ์์ ์์๋ ์๋ํ์ง๋ง _real_ ์์ ์์๋ ๊ทธ๋ ์ง ์์ต๋๋ค"๋ผ๊ณ ๋งํ ์ ์๋ ๋ฐฉ์์ผ๋ก ๋จ์ํํ ์ ์์ ๋งํผ ์ถฉ๋ถํ ์ ๊ตํ ์์ ์ ๋๋ค.
๋์์ด ๋๋ ๊ฒ์ 30๊ฐ์ ์์ ๊ฐ ์๋๋ผ "๊ธ์, ๋ฌผ๋ก , ์ด ์์ ์์๋ ์๋ํ์ง๋ง ์ค์ ์์ ์์๋ ๊ทธ๋ ์ง ์์ต๋๋ค"๋ผ๊ณ ๋งํ ์ ์๋ ๋ฐฉ์์ผ๋ก ๋จ์ํํ ์ ์์ ๋งํผ ์ถฉ๋ถํ ์ ๊ตํ ์์ ์ ๋๋ค.
์ด๋ฏธ ๋ช ๋ฒ ๋งํ์ง๋ง ํ
์ ํ๋จํ๋ ๋ฐฉ์์ ๋ถ๊ณตํํ๋ค.
Hooks๋ ์ด์ ์ ๋ถ๊ฐ๋ฅํ๋ ๊ฒ์ ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ๊ฒ์ด ์๋๋๋ค. ์ด๋ฐ ์ข
๋ฅ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ผ๊ด๋ API๋ฅผ ์ ๊ณตํ๋ ๊ฒ์
๋๋ค.
๋ค๋ฅด๊ฒ ๋จ์ํํ ์ ์๋ ๊ฒ์ ๋ณด์ฌ์ฃผ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฒญํ๋ ๊ฒ์ ๋๋ฌด๋ฅผ ์ค๋ฅด๋ ๋ฅ๋ ฅ์ผ๋ก ๋ฌผ๊ณ ๊ธฐ๋ฅผ ํ๋จํ๋ ๊ฒ์ ๋๋ค.
์ฐ๋ฆฌ๋ ๋จ์ง ํํฌ๋ฅผ ํ๋จํ๋ ค๊ณ ํ๋ ๊ฒ์ด ์๋๋ผ ๋ชจ๋ ์ฌ๋์ ์๊ตฌ๋ฅผ ํด๊ฒฐํ๋ ์๋ฃจ์ ์ด ์๋์ง ํ์ธํ๊ธฐ ์ํด ๋ค์ํ ์๋ฃจ์ ์ ํ๊ฐํ๋ ค๊ณ ํฉ๋๋ค.
(๊ฐ ์ ์์์ ์ค์ ๋ก ์ ์ฒญ์๋ฅผ ์์ฑํ๊ณ ๋น๊ตํ์ง ์๋๋ค๋ฉด ์ฌ๊ธฐ์์ ๋ค๋ฅธ ์ ์์๋ฅผ ์ด๋ป๊ฒ ํ๊ฐํ ๊ฒ์ธ์ง ๊ถ๊ธํฉ๋๋ค. ๋์ ์ด๋ค ํ๊ฐ ์งํ๋ฅผ ์ ์ํ์๊ฒ ์ต๋๊น?)
์ด ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ ์ ํ๋จํ๋ ์ ์ ํ ๋ฐฉ๋ฒ์ ์์ฉ ํ๋ก๊ทธ๋จ์ด ์๋๋๋ค(API์ ๊ฐ ๊ฐ๋ณ ์ฌ์ฉ์ ์ฌ๊ธฐ์ ์๋ ์์ ๊ฐ์ด ๋ฌด์๋ฉ๋๋ค).
์ ์๋ ์๋ฃจ์ ์ ํ๋จํด์ผ ํ๋ ์ฌํญ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด ๊ทธ๋ฆฌ๋์์ ํ๊ฐํ ๋ Property
/ addDispose
์ ์์๋ "๊ฒฐ๊ณผ ์ฝ๋๊ฐ ๋ ์ข์ต๋๊น?" ๊ทธ๋ฌ๋ ์ฌ์ฌ์ฉ์ฑ๊ณผ ์ ์ฐ์ฑ ๋ชจ๋์ ๋ํด ๋ฎ์ ํ๊ฐ๋ฅผ ๋ฐ์์ต๋๋ค.
์ค์ ์ฌ์ฉ๋๋ ๊ฐ ์ ์์ ์ค์ ๋ก ๋ณด์ง ์๊ณ ์ด๋ฌํ ์ง๋ฌธ์ ๋ตํ๋ ๋ฐฉ๋ฒ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
์์?
์ด ์ ์์ด ์ง์ ์ผ๋ก ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ฝ๋๋ฅผ ์์ฑํ๊ณ ๋ง์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์ด๋ ค์์ ๊ฒช์ ๊ฒ์์ ์๊ธฐ ์ํด Property
๋ฅผ ์ฌ์ฉํ์ฌ ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ง๋ค ํ์๊ฐ ์์์ต๋๋ค.
๊ธฐ์กด *Builder๋ฅผ ์ฌ์ฉํ์ฌ ์ ์๋ ์๋ฃจ์
์ ์ฌ์ฉํ์ฌ ๋ค์ ๊ตฌํํ ์ ์์ต๋๋ค.
์ด ์ค๋ ๋์ ๋์ด๋ ํํฌ ๋๋ React ์ปค๋ฎค๋ํฐ์์ ๋ง๋ ์ผ๋ถ ํํฌ๋ฅผ ์๋ํ๊ณ ๋ค์ ๊ตฌํํ ์๋ ์์ต๋๋ค(์จ๋ผ์ธ์์ ์ฌ์ฉํ ์ ์๋ ํํฌ ํธ์ง์ด ๋ง์ด ์์).
์ด ์ ์์ด ์ง์ ์ผ๋ก ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ฝ๋๋ฅผ ์์ฑํ๊ณ ๋ง์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์ด๋ ค์์ ๊ฒช์ ๊ฒ์์ ์๊ธฐ ์ํด
Property
๋ฅผ ์ฌ์ฉํ์ฌ ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ง๋ค ํ์๊ฐ ์์์ต๋๋ค.
๋ถํํ๋, ๋๋ ์ฌ๊ธฐ์ ๋น์ ์ ๋ณธ๋ฅ์ ๊ณต์ ํ์ง ์์ต๋๋ค(๋น์ ์ด ๊ฐ์น๋ฅผ ์ฒ๋ฆฌํด์ผ ํ๋ค๊ณ ๋งํ ๋๊น์ง Property (https://github.com/flutter/flutter/issues/51752#issuecomment-667737471)๊ฐ ํ๋ฅญํ๊ฒ ์๋ํ๋ค๊ณ ์๊ฐํ๋ค๋ ์ฌ์ค์์ ์ ์ ์๋ฏ์ด) ๋์ผํ API๋ฅผ ์ฌ์ฉํ๋ ์์ ฏ๊ณผ ๋ก์ปฌ ์ํ์์ ๋ชจ๋ ๊ฐ์ ธ์ค๊ธฐ ์ ๊น์ง๋ ์ ์ฝ ์กฐ๊ฑด์ด๋ผ๋ ์ฌ์ค์ ๋ชฐ๋์ต๋๋ค). ํด๋น ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ Property ๋ฒ์ ๋ ์ ๊ณตํ๋ฉด ํ์คํ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ ๊ฒ์ ๋๊น, ์๋๋ฉด ๋ค๋ฃจ์ง ์๋ ์๋ก์ด ๋ฌธ์ ๊ฐ ์์ต๋๊น? ๋ชฉํ๊ฐ ์์ผ๋ฉด ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ๋ชฉํ๋ผ๋ ๋ฐ ๋์ํฉ๋๋ค. ์ฐ๋ฆฌ๊ฐ ์๋ฃจ์ ์ ์ค๊ณํ๋ ๋์์ด ๋ฌด์์ธ์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๊ธฐ์กด *Builder๋ฅผ ์ฌ์ฉํ์ฌ ์ ์๋ ์๋ฃจ์ ์ ์ฌ์ฉํ์ฌ ๋ค์ ๊ตฌํํ ์ ์์ต๋๋ค.
๋ถ๋ช ํ _์๋ฌด๋_ ์๋๋๋ค. ์๋ฅผ ๋ค์ด, ๋น์ ์ OP์์ ํ๋๋ฅผ ์ฃผ์๊ณ , ๋ด๊ฐ ์ฒซ ๋ฒ์งธ Property ์ ์์ ํ ๋ (https://github.com/flutter/flutter/issues/51752#issuecomment-664787791) ๋ค์์์ ์ค๋ช ํ์ง ์์ ๋ฌธ์ ๋ฅผ ์ง์ ํ์ต๋๋ค. ์ค๋ฆฌ์ง๋ ๋น๋.
์ด ์ค๋ ๋์ ๋์ด๋ ํํฌ ๋๋ React ์ปค๋ฎค๋ํฐ์์ ๋ง๋ ์ผ๋ถ ํํฌ๋ฅผ ์๋ํ๊ณ ๋ค์ ๊ตฌํํ ์๋ ์์ต๋๋ค(์จ๋ผ์ธ์์ ์ฌ์ฉํ ์ ์๋ ํํฌ ํธ์ง์ด ๋ง์ด ์์).
๋๋ ์ฐ๋ฆฌ๊ฐ ์ด๋์์ ์์ํ๋์ง ์๊ดํ์ง ์์ต๋๋ค. ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๊ณ ํํฌ๋ฅผ ์ฌ์ฉํ๋ค๊ณ ์๊ฐํ๋ ํนํ ์ข์ ์๊ฐ ์๋ค๋ฉด ํ๋ฅญํฉ๋๋ค. @TimWhiting ์ ์ ์ฅ์์ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค. ์์ ์ ๋์ผํ ๊ฒ์ ์ฌ๋ฌ ๊ฐ์ง ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ๊ตฌํํ๋ ๊ฒ์ ๋๋ค. ์์ด๋์ด๊ฐ ์ด๋์์ ์๋์ง ์๊ดํ์ง ์์ต๋๋ค.
๋์์ด ๋ ๊ฒ์ 30๊ฐ์ ์์ ๊ฐ ์๋๋ผ "์, ๋ฌผ๋ก , ์ด ์์ ์์๋ ์๋ํ์ง๋ง _real_ ์์ ์์๋ ๊ทธ๋ ์ง ์์ต๋๋ค"๋ผ๊ณ ๋งํ ์ ์๋ ๋ฐฉ์์ผ๋ก ๋จ์ํํ ์ ์์ ๋งํผ ์ถฉ๋ถํ ์ ๊ตํ ์์ ์ ๋๋ค.
์ฝ์ ์ ์๋ ๋น๋๋ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด ์๋ช ์ฃผ๊ธฐ ์์ฉ๊ตฌ ์์ด AnimatorController(๋๋ ์๊ฐํ ์ ์๋ ๋ค๋ฅธ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ํ ์ ์ฅ ๊ตฌ์ฑ ์์)๋ฅผ ์ฌ์ฉํ๋ ค๋ ๋จ์ํ ์๊ตฌ๋ณด๋ค ๋ ์ ๊ตํ ๊ฒ์ ์์ ๊ฒ์ ๋๋ค.
๋ฒ์ฉ ๋ฐฉ์์ผ๋ก ์์ฒญ๋ ๊ฐ๋ ์ฑ ๋ฐ ๊ฒฌ๊ณ ์ฑ ์ด์ ์ ํด๊ฒฐํ๋ ์๋ฃจ์ ์ด ์ ์๋์ง ์์์ต๋๋ค.
๋๋ _any_ builder๊ฐ ํ ๊ฒ์ด๋ผ๋ ์ฌ์ค์ ์ฃผ์ฅํฉ๋๋ค. ์ด ๋ฌธ์ ๋ "We need syntax sugar for Builders"๋ก ์ด๋ฆ์ด ๋ฐ๋๊ณ ๋์ผํ ํ ๋ก ์ผ๋ก ์ด์ด์ง ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
AnimationController
์์ฑ ๋ฐ ์ญ์ ์ ๊ฐ์ ๋ค๋ฅธ ๋ชจ๋ ์ธ์๋ ๋น๋๋ก ์ถ์ถ๋ ์ ์๋ค๋ ๊ฒ์ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค.
Widget build(context) {
return AnimationControllerBuilder(
duration: Duration(seconds: 2),
builder: (context, animationController) {
}
);
}
๊ฒฐ๊ตญ ์๋ฒฝํ ์๋ StreamBuilder๋ฅผ ์์ ํ ๋ค์ ๊ตฌํํ๊ณ ๋ค์ํ ์๋๋ฆฌ์ค์์ ํ ์คํธํ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
Widget
์์ ์ต๋๋ค."์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ์คํธ๋ฆผ์ด ๋ณ๊ฒฝ๋ ์ ์์"์ ๋ํด ๊ฐ ๊ฐ๋ณ ์ฌ๋ก๋ฅผ ํ ์คํธํ์ฌ ๋ค์๊ณผ ๊ฐ์ด ํ์ญ์์ค.
์ด๊ฒ์ ํ์ฌ Property
๋๋ onDispose
ํด๊ฒฐํ ์ ์์ต๋๋ค.
@esDotDev "์์ฒญ๋ ๊ฐ๋ ์ฑ ๋ฐ ๊ฒฌ๊ณ ์ฑ ์ด์ "์ ์ด๊ฑฐํ ์ ์์ต๋๊น? ๋๊ตฐ๊ฐ๊ฐ ์ด๋ฌํ ๊ฐ๋ ์ฑ๊ณผ ๊ฒฌ๊ณ ์ฑ ์ด์ ์ผ๋ก AnimationController๋ฅผ ์ฒ๋ฆฌํ๋ ์ ์์ ํ๋ฉด ์ฌ๊ธฐ์ ๋์ธ๊ฐ์?
@rrousselGit ๋๋ ๋น์ ์ด ๋น์ ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ๋ชปํ๋ค๊ณ ์ ์ ๋งํ๋ฏ์ด Property๋ฅผ ์นํธํ๋ ๊ฒ์ด ์๋๋๋ค. ๊ทธ๋ฌ๋ ๋๊ตฐ๊ฐ๊ฐ StreamBuilder๊ฐ ํ๋ ๋ชจ๋ ์์ ์ ์ํํ์ง๋ง ๋ค์ฌ์ฐ๊ธฐ๊ฐ ์๋ ์๋ฃจ์ ์ ๋ง๋ค๋ฉด ๊ทธ๊ฒ ๋ ๊น์? ๋น์ ์ ํ๋ณตํ ๊น์?
๊ทธ๋ฌ๋ ๋๊ตฐ๊ฐ๊ฐ StreamBuilder๊ฐ ํ๋ ๋ชจ๋ ์์ ์ ์ํํ์ง๋ง ๋ค์ฌ์ฐ๊ธฐ๊ฐ ์๋ ์๋ฃจ์ ์ ๋ง๋ค๋ฉด ๊ทธ๊ฒ ๋ ๊น์? ๋น์ ์ ํ๋ณตํ ๊น์?
๋๋ถ๋ถ ๊ทธ๋ ์ต๋๋ค.
๋ฌผ๋ก ์ด ์๋ฃจ์ ์ ๋ค๋ฅธ ์๋ฃจ์ ๊ณผ ๋น๊ตํด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ์์ฉ ๊ฐ๋ฅํ ์์ค์ ๋๋ฌํ ๊ฒ์ ๋๋ค.
@esDotDev "์์ฒญ๋ ๊ฐ๋ ์ฑ ๋ฐ ๊ฒฌ๊ณ ์ฑ ์ด์ "์ ์ด๊ฑฐํ ์ ์์ต๋๊น?
์ข ์์ฑ ๋ฐ ์๋ช ์ฃผ๊ธฐ์ ๋ํ ์์ฉ๊ตฌ๋ฅผ ์์ ํ ์บก์ํํ ์ ์๋ค๋ ์ ์์ ๊ฒฌ๊ณ ํฉ๋๋ค. ์ฆ. ๋๋ fetchUser์๊ฒ ๋งค๋ฒ id๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ค์ ๋น๋ํด์ผ ํ๋ค๊ณ ๋งํ ํ์๊ฐ ์์ผ๋ฉฐ ๋ด๋ถ์ ์ผ๋ก ๊ทธ๋ ๊ฒ ํ๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. Animation์ด ๋ถ๋ชจ ์์ ฏ์ด ํ๊ธฐ๋ ๋๋ง๋ค ์ค์ค๋ก ํ๊ธฐํ๋๋ก ์ง์ํ ํ์๋ ์์ต๋๋ค. (Property๊ฐ ์ด ์์ ์ ์ํํ ์ ์๋์ง ์ฌ๋ถ๋ฅผ ์์ ํ ์ดํดํ์ง ๋ชปํฉ๋๋ค) ์ด๊ฒ์ ๊ฐ๋ฐ์๊ฐ ์ฝ๋ ๊ธฐ๋ฐ ์ ์ฒด์์ ๋ฐ๋ณต์ ์ธ ์์ ์ ๋ํ ์ค์๋ฅผ ์ ์ง๋ฅด๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค(ํ์ฌ ๋น๋๋ฅผ ์ฌ์ฉํ๋ ์ฃผ์ ์ด์ ์ค ํ๋).
๊ฐ๋ ์ฑ์ ๋ค์ฌ์ฐ๊ธฐ๋์ง ์์ ํ ์ค์ ์ฝ๋๋ก ์ํ ์ ์ฅ ํญ๋ชฉ์ ์ป์ ์ ์๊ณ ํด๋น ํญ๋ชฉ์ ๋ํ ๋ณ์๊ฐ ํธ์ด์คํธ๋๊ณ ๋ช ํํ๊ฒ ํ์๋๋ค๋ ๊ฒ์ ๋๋ค.
@esDotDev ๋๊ตฐ๊ฐ๊ฐ AnimationController๋ฅผ ์ด๋ฌํ ๊ฐ๋ ์ฑ๊ณผ ๊ฒฌ๊ณ ์ฑ ์ด์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ์ ์์ ํ๋ค๋ฉด ์ฌ๊ธฐ์ ๋์ธ๊ฐ์?
๊ตฌ์ฒด์ ์ผ๋ก AnimationController ๋ฒํธ๋ฅผ ์๋ฏธํ๋ค๋ฉด. AnimationController/FocusController/TextEditingController์ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ์๋ฏธํ๋ค๋ฉด ๊ทธ๋ ์ต๋๋ค.
๋ช ํํ์ง ์์ ์ ์๋ ์๋ช ์ด ์๋ ๊ฐ์ ๋ฐํํ๋ ํจ์์ ๊ฐ์ API๋ฅผ ๊ฐ๋ ๊ฒ์
์ด๊ฒ์ ์ค์ํ ์คํด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ํํฌ์ ์๋ช ์ ์ ์์ ๋ฐ๋ผ ํ์ ์ํ์ด๊ธฐ ๋๋ฌธ์ ๋ช ํํฉ๋๋ค. ๊ทธ๊ฒ๋ค์ ๊ทธ๊ฒ๋ค์ "์ฌ์ฉ"ํ๋ ๊ตญ๊ฐ์ ์ผ์ ๋์ _ํญ์_ ์กด์ฌํฉ๋๋ค. ์ค์ ๋ก ๋ ๋ช ํํ ์ ์์ต๋๋ค. ๊ตฌ๋ฌธ์ด ์ด์ํ๊ณ ์์ํ ์ ์์ง๋ง ๋ช ํ์ฑ์ด ๋ถ์กฑํ ๊ฒ์ ์๋๋๋ค.
TweenAnimationBuilder()์ ์๋ช ๋ ๋ช ํํฉ๋๋ค. ๋ถ๋ชจ๊ฐ ๋ ๋๋ฉด ์ฌ๋ผ์ง๋๋ค. ํ์ ์์ ฏ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ํ์ ์ํ์ ๋๋ค. ๊ทธ๊ฒ๋ค์ ์์ ํ ๋ ๋ฆฝ์ ์ธ ์ํ "๊ตฌ์ฑ ์์"์ด๋ฉฐ, ์ฝ๊ฒ ์กฐํฉํ๊ณ ์ฌ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ๋ฒ๊ทธ๊ฐ ์๋ ๊ธฐ๋ฅ์ด ์ ์ธ๋ ์ํ์ ์์ฐ์ค๋ฝ๊ฒ ๋ฐ์ธ๋ฉ๋๊ธฐ๋ฅผ ์ํ๊ธฐ ๋๋ฌธ์ ์๋ช ์ ๋ช ์์ ์ผ๋ก ๊ด๋ฆฌํ์ง ์์ต๋๋ค.
@esDotDev
๋ฑ
๋ ์์ธํ๊ฒ ์๊ธฐํด ์ฃผ ์๊ฒ ์ด์? (์ด๊ฒ์ด ๋ด๊ฐ ๋ชจ๋ ๊ธฐ๋ฐ์ ๋ค๋ฃจ๋ ๋ฐ๋ชจ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ ์ํ ์ด์ ์ ๋๋ค. ๊ณ์ํด์ ์ด๊ฒ์ด ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.) ๊ตฌ์ฑ์ด ๋ณ๊ฒฝ๋์ด ์๋์ผ๋ก ์ญ์ ๋์ง ์๋ ํ ์ด๊ธฐํ ํ๋ก๊ทธ๋จ์ ํธ์ถํ๋ ๊ฒ ์ธ์ ์ค์ํ ๊ธฐ๋ฅ์ด ์์ต๋๊น? ํธ์คํธ ์์๊ฐ ์ญ์ ๋ ๋ ํ ๋น๋ ๋ฆฌ์์ค?
TextEditingController์ ์ ์ฌํ ๊ฐ์ฒด
๋ ์์ธํ๊ฒ ์๊ธฐํด ์ฃผ ์๊ฒ ์ด์? TextEditingController๋ ์ด๋ค ๋ฉด์์ AnimationController๋ณด๋ค ๋ ์ ๊ตํฉ๋๊น?
@rrousselGit
๊ทธ๋ฌ๋ ๋๊ตฐ๊ฐ๊ฐ StreamBuilder๊ฐ ํ๋ ๋ชจ๋ ์์ ์ ์ํํ์ง๋ง ๋ค์ฌ์ฐ๊ธฐ๊ฐ ์๋ ์๋ฃจ์ ์ ๋ง๋ค๋ฉด ๊ทธ๊ฒ ๋ ๊น์? ๋น์ ์ ํ๋ณตํ ๊น์?
๋๋ถ๋ถ ๊ทธ๋ ์ต๋๋ค.
๋ค์์ ๋ค์ฌ์ฐ๊ธฐ ์์ด StreamBuilder๊ฐ ์ํํ๋ ๋ชจ๋ ์์ ์ ์ํํ๋ ์๋ฃจ์ ์ ๋๋ค.
Widget build(context) {
var result = Text('result:');
var builder1 = (BuildContext context, AsyncSnapshot<int> snapshot) {
return Row(children: [result, Text(snapshot.data)]);
};
result = StreamBuilder(stream: _stream1, builder: builder1);
var builder2 = (BuildContext context, AsyncSnapshot<int> snapshot) {
return Column(children: [result, Text(snapshot.data)]);
};
result = StreamBuilder(stream: _stream2, builder: builder2);
}
๊ทธ๋ฌ๋ ์ด๊ฒ์ด ๋ค๋ฅธ ์ ์ฝ ์กฐ๊ฑด์ ์๋ฐํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ ์ ๋ฌธ์ ์ ๋ํ ์ ์ฒด ์ค๋ช ์ด ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ๋์ํ ์ ์๋ ๊ฒ์ ์ ํธํฉ๋๋ค.
๋น๋๊ฐ @Hixie๋ฅผ ๊ฐ๋ ๊ฒ๊ณผ ๋์ผํ ์ ์ฝ ์กฐ๊ฑด์
๋ ์์ธํ๊ฒ ์๊ธฐํด ์ฃผ ์๊ฒ ์ด์? TextEditingController๋ ์ด๋ค ๋ฉด์์ AnimationController๋ณด๋ค ๋ ์ ๊ตํฉ๋๊น?
์๋์, ํ์ง๋ง init/dispose์์ ๋ค๋ฅธ ์์ ์ ์ํํ๊ฑฐ๋ ๋ค๋ฅธ ์์ฑ์ ๋ฐ์ธ๋ฉ๋๋ฉฐ ํน์ ์์ฉ๊ตฌ๋ฅผ ์บก์ํํ๊ณ ์ถ์ต๋๋ค.
@esDotDev ๊ทธ๋์ ๋น๋์ ๊ฐ์ ๊ฒ์ ์ํ์ง๋ง ๋ค์ฌ์ฐ๊ธฐ ์์ด ํ ์ค๋ก(์๋ง๋ ๋น๋ ์ฝ๋ฐฑ ์์ฒด ์ ์ธ)? ๋ด๊ฐ ๋ฐฉ๊ธ ๊ฒ์ํ ์์ (https://github.com/flutter/flutter/issues/51752#issuecomment-671004483)๋ ์ค๋๋ ๋น๋์์ ๊ทธ๋ ๊ฒ ํ๋ฏ๋ก ์๋ง๋ ๊ทธ ์ด์์ ์ถ๊ฐ ์ ์ฝ์ด ์์ ๊ฒ์ ๋๋ค.
(FWIW, ๋น๋ ๋๋ ๋น๋์ ๊ฐ์ ๊ฒ์ด ์๋๋ผ ํ ์ค์ ์๋ ๊ฒ์ด ์ข์ ์๋ฃจ์ ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ๊ฐ ๋ฐ์ดํฐ ์ ํ์ ์์ฒด ๋น๋๊ฐ ์์ฑ๋์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฆ์์์ ๋น๋ํ๋ ์ข์ ๋ฐฉ๋ฒ์ ์์ต๋๋ค. .)
(FWIW, ๋น๋ ๋๋ ๋น๋์ ๊ฐ์ ๊ฒ์ด ์๋๋ผ ํ ์ค์ ์๋ ๊ฒ์ด ์ข์ ์๋ฃจ์ ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ๊ฐ ๋ฐ์ดํฐ ์ ํ์ ์์ฒด ๋น๋๊ฐ ์์ฑ๋์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฆ์์์ ๋น๋ํ๋ ์ข์ ๋ฐฉ๋ฒ์ ์์ต๋๋ค. .)
์ด๊ฒ ๋ฌด์จ ๋ป์ธ์ง ์ดํด๊ฐ ๋์ง ์์ต๋๋ค. ๋น์ ์ ๊ทธ๊ฒ์ ๋ค์ ๋งํ ์ ์์ต๋๊น? ๐
Animations์ฉ โโAnimationBuilder์ Streams์ฉ StreamBuilder ๋ฑ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค. ๋จ์ผ ๋น๋๋ฅผ ๊ฐ์ง๊ณ StatefulWidget์ ์์ฑํ ๋ "์ฌ๊ธฐ์ ์ ๋น๋๋ฅผ ์ป๋ ๋ฐฉ๋ฒ, ํ๊ธฐํ๋ ๋ฐฉ๋ฒ, ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค"๋ผ๊ณ ๋งํ๋ ๋์ .
๊ทธ๋ฌ๋ ์ด๊ฒ์ด ๋ค๋ฅธ ์ ์ฝ ์กฐ๊ฑด์ ์๋ฐํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ ์ ๋ฌธ์ ์ ๋ํ ์ ์ฒด ์ค๋ช ์ด ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ๋์ํ ์ ์๋ ๊ฒ์ ์ ํธํฉ๋๋ค.
๋๋ ๊ทธ๊ฒ์ด ๊ถ๊ทน์ ์ผ๋ก ์ฌ๊ธฐ์ ๋ชฉํ์ธ ์ฝ์ ์ ์๋ ์ฝ๋์ ๋ํ ์์ฒญ์ ๋ถ๋ช ํ ์๋ฐํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ฐ๋ฆฌ ๋ชจ๋๋ ๋ฐฑ๋ง ๊ฐ์ ํน์ ์ ํ์ ๋น๋๋ฅผ ์ฌ์ฉํ๊ณ ์์ํ ์ค์ฒฉํ๊ณ ํ๋ฃจ๋ผ๊ณ ๋ถ๋ฆ ๋๋ค.
๋๋ ์์ฒญ๋๋ ๊ฒ์ด ๋ค์๊ณผ ๊ฐ๋ค๊ณ ์๊ฐํฉ๋๋ค.
Widget build(context) {
var snapshot1 = get AsyncSnapshot<int>(stream1);
var snapshot2 = get AsyncSnapshot<int>(stream2);
return Column(children: [Text(snapshot1.data), Text(snapshot2.data)]);
}
์ด๊ฒ์ด ๋ชจ๋ ์ฝ๋์ ๋๋ค. ์คํธ๋ฆผ์ด ์ฐ๋ฆฌ๋ฅผ ์ํด ์์ฑ๋๊ณ , ์คํธ๋ฆผ์ด ์ฐ๋ฆฌ๋ฅผ ์ํด ํ๊ธฐ๋๊ณ , ์ฐ๋ฆฌ๋ ๋ฐ์ ๋ค์ฌ๋์ ์ ์์ผ๋ฉฐ ์ฝ๋๊ฐ ํจ์ฌ ๋ ์ฝ๊ธฐ ์ฝ์ต๋๋ค.
Animations์ฉ โโAnimationBuilder์ Streams์ฉ StreamBuilder ๋ฑ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
๋๋ ๊ทธ๊ฒ์ ๋ฌธ์ ๋ก ๋ณด์ง ์๋๋ค. ์ฐ๋ฆฌ๋ ์ด๋ฏธ RestorableInt ๋ RestorableString ๋ RestorableDouble์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ ๋ค๋ฆญ์ ๋ค์์ ํด๊ฒฐํ ์ ์์ต๋๋ค.
GenericBuilder<Stream<int>>(
create: (ref) {
var controller = StreamController<int>();
ref.onDispose(controller.close);
return controller.stream;
}
builder: (context, Stream<int> stream) {
}
)
๋ง์ฐฌ๊ฐ์ง๋ก Flutter ๋๋ Dart๋ ์ค์ ๋ก ๋ฌธ์ ๊ฐ ๋๋ ๊ฒฝ์ฐ Disposable
์ธํฐํ์ด์ค๋ฅผ ํฌํจํ ์ ์์ต๋๋ค.
@esDotDev
์์ฒญ๋๋ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด๋ ๋ค๋ฅธ ์ฌ๋๋ค์ด ๋์ดํ ๊ฝค ํฉ๋ฆฌ์ ์ธ ์ ์ฝ ์กฐ๊ฑด(์: @Rudiksz)์ ์๋ฐํ๋ ๊ฒ์ ๋๋ค. ์ฆ, ๋น๋ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๋์ ์ด๊ธฐํ ์ฝ๋๊ฐ ๋ฐ์ํ์ง ์๋๋ก ๋ณด์ฅํฉ๋๋ค.
@rrousselGit
๋๋ ๊ทธ๊ฒ์ ๋ฌธ์ ๋ก ๋ณด์ง ์๋๋ค. ์ฐ๋ฆฌ๋ ์ด๋ฏธ RestorableInt ๋ RestorableString ๋ RestorableDouble์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ AnimationBuilder์ StreamBuilder ๋ฑ์ด ์์ต๋๋ค. ๊ทธ๋ ์ต๋๋ค. ๋ ๊ฒฝ์ฐ ๋ชจ๋ ๋ถํํฉ๋๋ค.
์ ๋ค๋ฆญ ๋น๋
๊ทธ๊ฒ์ ๋ด๊ฐ Property์ ๋ํด ์ ์ํ ๊ฒ๊ณผ ์ ์ฌํ์ง๋ง, ๊ฑฐ๊ธฐ์์ ๊ทํ์ ์ฐ๋ ค ์ฌํญ์ ์ดํดํ๋ค๋ฉด ๋๋ฌด ์ฅํฉํ๋ค๊ณ ์๊ฐํ ๊ฒ์ ๋๋ค.
์ด์ ์ ๋๊ตฐ๊ฐ StreamBuilder๊ฐ ํ๋ ๋ชจ๋ ์์ ์ ์ํํ์ง๋ง ๋ค์ฌ์ฐ๊ธฐ๊ฐ ์๋ ์๋ฃจ์ ์ ๋ง๋ค๋ฉด ๋ง์กฑํ ๊ฒ์ด๋ผ๊ณ ๋งํ์ต๋๋ค. ๋ด ์๋์ ๋ํด ์ธ๊ธํ์ง ์์ผ์ จ์ต๋๋ค(https://github.com/flutter/flutter/issues/51752#issuecomment-671004483). ๊ทธ ์๋ฃจ์ ์ ๋ง์กฑํ์ญ๋๊น?
@esDotDev
์์ฒญ๋๋ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด๋ ๋ค๋ฅธ ์ฌ๋๋ค์ด ๋์ดํ ๊ฝค ํฉ๋ฆฌ์ ์ธ ์ ์ฝ ์กฐ๊ฑด(์: @Rudiksz)์ ์๋ฐํ๋ ๊ฒ์ ๋๋ค. ์ฆ, ๋น๋ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๋์ ์ด๊ธฐํ ์ฝ๋๊ฐ ๋ฐ์ํ์ง ์๋๋ก ๋ณด์ฅํฉ๋๋ค.
์ด ์ฝ๋๊ฐ ๋น๋์ ์๋ ๊ฒ์ ์ค์ํ์ง ์์ต๋๋ค. ์ค์ํ ๋ถ๋ถ์
์ด๊ฒ์ ๋๋ผ์ด ๊ฒ์ ๋๋ค:
AsyncSnapshot<int> snapshot1 = createLifecycleState(widget.stream1);
AsyncSnapshot<int> snapshot2 = createLifecycleState(widget.stream2);
AniamtorController animator = createLifecycleState(duration: Duration(seconds: 1), (a)=>a.forward());
Widget build(context) {
return Opacity(opacity: animator.value, child: Column(children: [Text(snapshot1.data), Text(snapshot2.data)]));
}
๋๋ ๊ฐ๊ฒฐํ์ง๋ ์์ง๋ง ๋น๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ์ฌ์ ํ ์ฝ๊ธฐ ์ฝ๊ณ ์ง์ ์ํํ๋ ๊ฒ๋ณด๋ค ์ฅํฉํ๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ์ต๋๋ค.
AsyncSnapshot<int> stream1;
AsyncSnapshot<int> stream2;
<strong i="18">@override</strong>
void initState(){
snapshot1 = createLifecycleState(widget.stream1);
snapshot2 = createLifecycleState(widget.stream2);
super.initState();
}
Widget build(context) {
return Column(children: [Text(snapshot1.data), Text(snapshot2.data)]);
}
์ ์ฐ๋ฆฌ๊ฐ ๊ณ์ ์ฅํฉํ๊ฒ ๋์๊ฐ๋์ง ์ดํด๊ฐ ๋์ง ์์ต๋๋ค.
๋๋ ๊ทธ๊ฒ์ด ๋ฌธ์ ๊ฐ ์๋๋ฉฐ ๋ฌธ์ ๋ ์ฌ์ฌ์ฉ์ฑ ๋ ๊ฐ๋
์ฑ ๋ ์ ์ฐ์ฑ์ด๋ผ๊ณ ์ฌ๋ฌ ๋ฒ ๋ช
์์ ์ผ๋ก ๋งํ์ต๋๋ค.
์๋ฃจ์ https://github.com/flutter/flutter/issues/51752#issuecomment -671000137 ๋ฐ ํ ์คํธ ์ผ์ด์ค https://github.com/flutter/flutter/issues/51752#issuecomment ๋ฅผ ํ๊ฐํ๊ธฐ ์ํด ๊ทธ๋ฆฌ๋๋ ๋ง๋ค์์ต๋๋ค. 671002248
์ด์ ์ ๋๊ตฐ๊ฐ StreamBuilder๊ฐ ํ๋ ๋ชจ๋ ์์ ์ ์ํํ์ง๋ง ๋ค์ฌ์ฐ๊ธฐ๊ฐ ์๋ ์๋ฃจ์ ์ ๋ง๋ค๋ฉด ๋ง์กฑํ ๊ฒ์ด๋ผ๊ณ ๋งํ์ต๋๋ค. ๋ด ์๋์ ๋ํด ์ธ๊ธํ์ง ์์ผ์ จ์ต๋๋ค(#51752(๋๊ธ)). ๊ทธ ์๋ฃจ์ ์ ๋ง์กฑํ์ญ๋๊น?
์ด๋ ํ์ฉ ๊ฐ๋ฅํ ์ต์ ์์ค์ ์ ์ฐ์ฑ์ ๋๋ฌํฉ๋๋ค.
https://github.com/flutter/flutter/issues/51752#issuecomment -671000137์ ๋ฐ๋ผ ํ๊ฐํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
Widget build(context) {
// this builder is not highlighted, but you can hover over it to see how often it rebuilds, how heavy were those rebuilds, and when was the last rebuild
var snapshot1 = keyword StreamBuilder(stream1);
// this builder will be highlighted because it triggered the rebuild
var constraints = keyword LayoutBuilder();
// <-- I had a breakpoint here and parent constraint changed, breakpoints got reached.
return Column(children: [Text(snapshot1.data), Text(snapshot2.data)]);
}
๋ํ @Hixie
์ด๋ ๋ค๋ฅธ ์ฌ๋๋ค์ด ๋์ดํ ๊ฝค ํฉ๋ฆฌ์ ์ธ ์ ์ฝ ์กฐ๊ฑด(์: @Rudiksz)์ ์๋ฐํ๋ ๊ฒ์ ๋๋ค. ์ฆ, ๋น๋ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๋์ ์ด๊ธฐํ ์ฝ๋๊ฐ ๋ฐ์ํ์ง ์๋๋ก ๋ณด์ฅํฉ๋๋ค.
์ฐ๋ฆฌ๋ ์ด๋ฏธ *Builders๋ฅผ ์ฌ์ฉํ์ฌ ์์์ ์ผ๋ก ๊ทธ๋ ๊ฒ ํ๊ณ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ๋ค์ ๋ค์ฌ ์ฐ๊ธฐ ์ํด ๋ฌธ๋ฒ ์คํ์ด ํ์ํฉ๋๋ค. async/wait ๋ฐ future์ ๋งค์ฐ ์ ์ฌํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
@esDotDev ์ค๋ช ํ๋ ๋ด์ฉ์ ์ด์ ์ ๋ด๊ฐ Property๋ก ์ ์ํ ๋ด์ฉ๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค(์: https://github.com/flutter/flutter/issues/51752#issuecomment-664787791 ๋๋ https://github.com/flutter/flutter/ ์ฐธ์กฐ). ๋ฌธ์ /51752#issuecomment-667737471). ์ด๋ฌํ ์ข ๋ฅ์ ์๋ฃจ์ ์ด ํจํค์ง๋ก ์์ฑ๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ ๊ฒ์ด ์์ต๋๊น? ์ฆ, ์ด๋ฌํ ์ข ๋ฅ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ ค๋ฉด ํต์ฌ ํ๋ ์์ํฌ์์ ์ด๋ค ๋ณ๊ฒฝ์ ํด์ผ ํฉ๋๊น?
@rrousselGit Shawn๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก
๊ทธ๋ฆฌ๋์ ๋ํ ๋ฌธ์ ๋ ์ง๊ธ๊น์ง ์๋ฃจ์ ์ ์ ์ฉํ๋ฉด ์ป์ ์ ์๋ ๊ฒ๊ณผ๋ ๋งค์ฐ ๋ค๋ฅธ ๊ฒ์ผ๋ก ๊ฐ์ ํ๋ค๋ ๊ฒ์ ๋๋ค.
์คํ ์ดํธํ ์์ ฏ
์์ฑ์ ๋ํ ๋ณํ
๋น๋์ ๋ณํ
ํํฌ์ ๊ฐ์ ์๋ฃจ์
์ ์ฐ๋ฆฌ๊ฐ ๊ณ์ ์ฅํฉํ๊ฒ ๋์๊ฐ๋์ง ์ดํด๊ฐ ๋์ง ์์ต๋๋ค.
๋๋ ๊ทธ๊ฒ์ด ๋ฌธ์ ๊ฐ ์๋๋ฉฐ ๋ฌธ์ ๋ ์ฌ์ฌ์ฉ์ฑ ๋ ๊ฐ๋ ์ฑ ๋ ์ ์ฐ์ฑ์ด๋ผ๊ณ ์ฌ๋ฌ ๋ฒ ๋ช ์์ ์ผ๋ก ๋งํ์ต๋๋ค.
์ฃ์กํฉ๋๋ค. ์์ฑ์ด ๋๋ฌด ์ฅํฉํ๋ค๊ณ ๋งํ ์ฌ๋์ด ๋๊ตฌ์ธ์ง ์๋ชป ๊ธฐ์ตํ์ต๋๋ค. ๋ค ๋ง์ด ๋ง์, ๋น์ ์ ์ฐ๋ ค๋ ์ด์ ์ ๋์ด๋์ง ์์ ์๋ก์ด ์ฌ์ฉ ์ฌ๋ก๊ฐ ์์ด์ ์ฒ๋ฆฌํ์ง ๋ชปํ๋ค๋ ๊ฒ์ ๋๋ค. ํ์ง๋ง Property๋ฅผ ํ์ฅํ์ฌ ํด๋น ์ฌ์ฉ ์ฌ๋ก๋ ์ฒ๋ฆฌํ๋ ๊ฒ์ ์ฌ์ํ ์ผ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค(๋๋ ์๋ํ์ง ์์์ง๋ง ์๊ตฌ ์ฌํญ์ด ์กฐ์ ๋ ๋ ๋ฐ๋ณต์ ์ผ๋ก ๋ฐ๋ณตํด์ผ ํ๋ ๊ฒ๋ณด๋ค ๋ฌธ์ ๋ฅผ ํ ๋ฒ์ ํด๊ฒฐํ ์ ์๋๋ก ๋ช ํํ ๋ฐ๋ชจ ์ฑ์ด ๋์ฌ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ์ด ๋ ๋์ ๊ฒ ๊ฐ์ต๋๋ค.
@szotp
- ์ด ๊ธฐ๋ฅ IMO๋ ์๋ฅผ ๋ค์ด LayoutBuilder๋ฅผ ํฌํจํ ๋ชจ๋ ๋น๋ ์์ ฏ์ผ๋ก ํ์ฅ๋ ์ ์์ต๋๋ค.
LayoutBuilder๋ ๋๋ถ๋ถ์ ๋น๋์ธ FWIW์๋ ๋งค์ฐ ๋ค๋ฅธ ์์ ฏ์ ๋๋ค. ์ง๊ธ๊น์ง ๋ ผ์๋ ์ ์ ์ค ์ด๋ ๊ฒ๋ LayoutBuilder์ ์ ์ฌํ ๋ฌธ์ ์ ๋ํด ์๋ํ์ง ์์ผ๋ฉฐ ๊ทํ์ ์๊ฒฌ ์ ์ ์ค๋ช ๋ ์๊ตฌ ์ฌํญ์๋ LayoutBuilder๊ฐ ํฌํจ๋์ด ์์ง ์์ต๋๋ค. ์ด ์๋ก์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ LayoutBuilder๋ฅผ ์ฒ๋ฆฌํด์ผ ํ๋์ง๋ ์์์ผ ํฉ๋๋ค. @TimWhiting ๊ณผ
- ๋ฆฌ์ค๋์ ๋นํ์ฑํํ๋ ๋ฐฉ๋ฒ์ด ํ์ํฉ๋๋ค. ๊ทธ๋์ผ 10x ์ปจํธ๋กค๋ฌ๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผ ๋ฆฌํ์ ์ ๋ฌํ์ฌ ๋ค์ ๋น๋ํ๊ฑฐ๋ flutter๊ฐ ๋น๋์์ ์ป์ ๊ฐ์ ํธ๋ฆฌ์ ์ด๋ ๋ถ๋ถ์์ ์ฌ์ฉํ๋์ง ์ ์ ์์ด์ผ ํฉ๋๋ค.
์ด๊ฒ์ด ์ ํํ ๋ฌด์์ ์๋ฏธํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๋ด๊ฐ ๋งํ ์ ์๋ ํ ์ค๋์ ๋ฆฌ์ค๋์ ๋น๋๋ฅผ ์ฌ์ฉํ์ฌ ์ด ์์ ์ ์ํํ ์ ์์ต๋๋ค(์: ์ ํํ ์ด ์์ ์ ์ํํ๊ธฐ ์ํด ์์ ์ธ์ฉํ ์ฑ์์ ValueListenableBuilder๋ฅผ ์ฌ์ฉํฉ๋๋ค).
์ด๋ ๋ค๋ฅธ ์ฌ๋๋ค์ด ๋์ดํ ๊ฝค ํฉ๋ฆฌ์ ์ธ ์ ์ฝ ์กฐ๊ฑด(์: @Rudiksz)์ ์๋ฐํ๋ ๊ฒ์ ๋๋ค. ์ฆ, ๋น๋ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๋์ ์ด๊ธฐํ ์ฝ๋๊ฐ ๋ฐ์ํ์ง ์๋๋ก ๋ณด์ฅํฉ๋๋ค.
์ฐ๋ฆฌ๋ ์ด๋ฏธ *Builders๋ฅผ ์ฌ์ฉํ์ฌ ์์์ ์ผ๋ก ๊ทธ๋ ๊ฒ ํ๊ณ ์์ต๋๋ค.
์ ํํ์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋น๋์ ๋ฐ๋ผ ๋ค๋ฅด์ง๋ง ์ผ๋ถ๋ initState, didChangeDependencies, didUpdateWidget ๋ฐ ๋น๋ ๋ก์ง์ ๋ถ๋ฆฌํ๊ธฐ ์ํด ๋งค์ฐ ์ด์ฌํ ์ผํ๋ฏ๋ก ์ต์ํ์ ์ฝ๋๋ง ๋ณ๊ฒฝ๋ ์ฌํญ์ ๊ธฐ๋ฐ์ผ๋ก ๊ฐ ๋น๋๋ฅผ ์คํํ๋ฉด ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ValueListenableBuilder๋ ์ฒ์ ์์ฑ๋ ๋๋ง ๋ฆฌ์ค๋๋ฅผ ๋ฑ๋กํ๋ฉฐ, ํด๋น ๋น๋๋ ์์ ๋๋ ๋น๋ ์ฌ์คํ์ initState ์์ด ์ฌ์คํ๋ ์ ์์ต๋๋ค. ์ด๊ฒ์ Hooks๊ฐ ํ ์ ์๋ ์ผ์ด ์๋๋๋ค.
@esDotDev ๋น์ ์ด ์ค๋ช ํ๋ ๊ฒ์ ๋ด๊ฐ ์ด์ ์ Property๋ก ์ ์ํ ๊ฒ๊ณผ ๋งค์ฐ ์ ์ฌํ๊ฒ ๋ค๋ฆฝ๋๋ค( ์: #51752(comment) ์ฐธ์กฐ ).
๋ด๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๋ค๋ฉด, UserId์ ๋ํ DidDependancyChange ๋๋ AnimationProperty
๋๋ ํด๋น ์ ํ์ ๋ํ init/update/dispose๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ํ์ํ ๋ค๋ฅธ ์์ฑ์ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ UserProperty
๋ฅผ ๋ง๋ค ์ ์์ต๋๊น? ๊ทธ๋ฌ๋ฉด ์ด๊ฒ์ ๋์๊ฒ ์ข์ ๊ฒ ๊ฐ์ต๋๋ค. ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋น ๋ฅด๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
๋๋ฅผ ์ค๋ง์ํค๋ ์ ์ผํ ๊ฒ์ ์ฌ๊ธฐ ๋ฏธ๋์ ๊ฑด์ถ๊ฐ์ ๋๋ค. ํ์ง๋ง ์ด๊ฒ์ ๋จ์ง ๋น์ ์ด ์ ํํ ์ ๋๋ฌธ์ด๋ผ๊ณ ์๊ฐํฉ๋๊น?
์๋ฅผ ๋ค์ด ์ด๊ฒ์ ๋ง๋ค ์ ์์ต๋๊น?
class _ExampleState extends State<Example> with PropertyManager {
AnimationProperty animProp1;
AnimationProperty animProp2;
<strong i="15">@override</strong>
void initProperties() {
super.initProperties();
anim1= register(anim1, AnimationProperty (
AnimationController(duration: Duration(seconds: 1)),
initState: (animator) => animator.forward()
// Not dealing with updates or dispose here, cause AnimationProperty handles it
));
anim2 = register(anim2, AnimationProperty(
AnimationController(duration: Duration(seconds: 2))..forward(),
));
}
<strong i="16">@override</strong>
Widget build(BuildContext context) {
return Column(children: [
FadeTransition(opacity: anim1, child: ...),
FadeTransition(opacity: anim2, child: ...),
])
}
}
๊ทธ๋ ๋ค๋ฉด ์ด๊ฒ์ ์์ ํ LGTM์ ๋๋ค! ํ๋ ์์ํฌ์ ์ถ๊ฐํ๋ค๋ ์ ์์ 1๊ธ ๊ตฌ๋ฌธ ์ ๊ทผ ๋ฐฉ์์ผ๋ก ์น๊ฒฉ๋์ด์ผ ํ๋์ง(1๋ ์ ๋๋ฉด ์ผ๋ฐ ๊ดํ์ด ๋จ์ ์๋ฏธํจ), ์๋๋ฉด ๊ฐ๋ฐ์์ ํ ์๋ฆฌ ์ ๋น์จ์ด ํ๋ฌ๊ทธ์ธ์ผ๋ก ์กด์ฌํ๋์ง ์ฌ๋ถ์ ๋๋ค. ์ฌ์ฉํ๋ค.
์ฅํฉํ๊ณ (์ฝ๊ฐ?) ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด ์์ ๋ฅผ ๋ ๊ฐ๊ฒฐํ ๊ตฌ๋ฌธ์ผ๋ก ์ ๋ฐ์ดํธํ ์ ์๋์ง ์ฌ๋ถ์ ๋ฌธ์ ์ ๋๋ค. ์์ฑ์ ์๋์ผ๋ก ๋๊ธฐํํ๊ณ ํญ๋ชฉ์ ์๋์ผ๋ก dispose()ํด์ผ ํ๋ ๊ฒ์ ๋ฒ๊ทธ์ ์ธ์ง ๋ถํ๋ก ์ด์ด์ง๋๋ค.
๊ฐ๋ฐ์๊ฐ ๋ ๋ฒ ์๊ฐํ ํ์ ์์ด ์ ์ ํ didUpdate ๋ฐ dispose ๋ฐ debugFillProperties ๋ฐ ์ ์ฒด ์๋๊ณผ ํจ๊ป ์ ๋๋ฉ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์ ๋๋ค. ๋ชจ๋ ๊ฐ๋ฐ์๋ Animator๋ฅผ ์๋์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ๋ณด๋ค ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉํฉ๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด๊ฒ์ ์์ ํ LGTM์ ๋๋ค! ํ๋ ์์ํฌ์ ์ถ๊ฐํ๋ค๋ ์ ์์ 1๊ธ ๊ตฌ๋ฌธ ์ ๊ทผ ๋ฐฉ์์ผ๋ก ์น๊ฒฉ๋์ด์ผ ํ๋์ง(1๋ ์ ๋๋ฉด ์ผ๋ฐ ๊ดํ์ด ๋จ์ ์๋ฏธํจ), ์๋๋ฉด ๊ฐ๋ฐ์์ ํ ์๋ฆฌ ์ ๋น์จ์ด ํ๋ฌ๊ทธ์ธ์ผ๋ก ์กด์ฌํ๋์ง ์ฌ๋ถ์ ๋๋ค. ์ฌ์ฉํ๋ค.
Property
๊ฐ ์ผ๋ง๋ ์ฌ์ํ์ง ๊ฐ์ํ ๋, ๊ทธ ์คํ์ผ์ ์ข์ํ๋ ์ฌ๋์๊ฒ ์ถ์ฒํ๋ ๊ฒ์ ์์ ๋ง์ ์ฝ๋๋ฅผ ๋ง๋ค๊ณ (๋์์ด๋๋ค๋ฉด ๋ด ์ฝ๋๋ก ์์ํ๋ ๊ฒ์ผ ์๋ ์์) ์ ์ ํ๋ค๊ณ ์๊ฐํ๋ ๋๋ก ์ฑ์์ ์ง์ ์ฌ์ฉํ๊ณ ์กฐ์ ํ๋ ๊ฒ์
๋๋ค. ๊ทธ๋ค์ ํ์๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด. ๋ง์ ์ฌ๋๋ค์ด ์ข์ํ๋ค๋ฉด ํจํค์ง๋ก ๋ง๋ค ์๋ ์์ง๋ง ์ฌ์ํ ์ผ์ ๋ํด์๋ ์ฝ๋์ ๋ณต์ฌํ๊ณ ํ์์ ๋ฐ๋ผ ์กฐ์ ํ๋ ๊ฒ์ด ์ผ๋ง๋ ์ ์ตํ์ง ๋ช
ํํ์ง ์์ต๋๋ค.
๋๋ฅผ ์ค๋ง์ํค๋ ์ ์ผํ ๊ฒ์ ์ฌ๊ธฐ ๋ฏธ๋์ ๊ฑด์ถ๊ฐ์ ๋๋ค. ํ์ง๋ง ์ด๊ฒ์ ๋จ์ง ๋น์ ์ด ์ ํํ ์ ๋๋ฌธ์ด๋ผ๊ณ ์๊ฐํฉ๋๊น?
@rrousselGit์ด ์ ๊ณตํ ์์ ๋ฅผ
์๋ฅผ ๋ค์ด ์ด๊ฒ์ ๋ง๋ค ์ ์์ต๋๊น?
AnimationController ์์ฑ์๋ฅผ ๋งค๋ฒ ํธ์ถํ๋ ๋์ ํธ์ถ๋๋ ํด๋ก์ ๋ก ์ฎ๊ธฐ๊ณ ์ถ์ ๊ฒ์
๋๋ค. ์๋ํ๋ฉด initProperties
๋ ์๋ก์ด ํด๋ก์ ๋ฅผ ์ป๊ธฐ ์ํด ํซ ๋ฆฌ๋ก๋ ์ค์ ํธ์ถ๋์ง๋ง ์ผ๋ฐ์ ์ผ๋ก ์์ฑํ๊ณ ์ถ์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค. ํซ ๋ฆฌ๋ก๋ ์ค ์ ์ปจํธ๋กค๋ฌ(์: ์ ๋๋ฉ์ด์
์ ์ฌ์ค์ ํจ). ํ์ง๋ง ๋ค, ๊ทธ ์ธ์๋ ๊ด์ฐฎ์ ๊ฒ ๊ฐ์ต๋๋ค. ๋น์ ์ ํ ์์๋ AnimationControllerProperty
์์ AnimationController
์์ฑ์ ์ธ์๋ฅผ ๊ทธ๋ค๊ณผ ํจ๊ป ์ฌ๋ฐ๋ฅธ ์ผ์ (๊ฐ ๋ณ๊ฒฝ๋์์ ๊ฒฝ์ฐ๋ ์๋ฅผ ๋ค์ด ๋จ๊ฑฐ์ด ๋ค์๋ก๋์ ์๊ฐ์ ์
๋ฐ์ดํธ).
๊ฐ๋ฐ์๊ฐ ๋ ๋ฒ ์๊ฐํ ํ์ ์์ด ์ ์ ํ didUpdate ๋ฐ dispose ๋ฐ debugFillProperties ๋ฐ ์ ์ฒด ์๋๊ณผ ํจ๊ป ์ ๋๋ฉ์ดํฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ฉด ์ข์ ๊ฒ์ ๋๋ค. ๋ชจ๋ ๊ฐ๋ฐ์๋ Animator๋ฅผ ์๋์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ๋ณด๋ค ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉํฉ๋๋ค.
๊ฐ๋ฐ์๊ฐ ๊ทธ๊ฒ์ ๋ํด ์๊ฐํ์ง ์๋ ๊ฒ์ ๋ํ ๋์ ๊ฑฑ์ ์ ํ ๋น ๋ฐ ํ๊ธฐ ์์ ์ ๋ํด ์๊ฐํ์ง ์์ผ๋ฉด ํญ์ ํ์ํ์ง ์์ ๋ง์ ๊ฒ์ ํ ๋นํ๊ฑฐ๋ ๊ทธ๋ ์ง ์์ ๋ ผ๋ฆฌ๋ฅผ ์คํํ๊ฒ ๋ ๊ฐ๋ฅ์ฑ์ด ๋ ๋๋ค๋ ๊ฒ์ ๋๋ค. ์คํํด์ผ ํ๊ฑฐ๋ ๋ ํจ์จ์ ์ธ ์ฝ๋๋ก ์ด์ด์ง๋ ๋ค๋ฅธ ์์ ์ ์ํํด์ผ ํฉ๋๋ค. ์ด๊ฒ์ด ๋ด๊ฐ ์ด๊ฒ์ ๊ธฐ๋ณธ ๊ถ์ฅ ์คํ์ผ๋ก ๋ง๋ค๊ธฐ๋ฅผ ๊บผ๋ฆฌ๋ ์ด์ ์ค ํ๋์ ๋๋ค.
AnimationController ์์ฑ์ ์ธ์๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฐ๋ฅธ ์์ ์ ์ํํ๋ AnimationControllerProperty๋ฅผ ๋ง๋ค ์๋ ์์ต๋๋ค(์: ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ ํซ ๋ฆฌ๋ก๋ ์ ์ง์ ์๊ฐ ์ ๋ฐ์ดํธ).
@Hixie ๊ฐ์ฌํฉ๋๋ค. ์ ๋ง ๋ฉ์ง๊ณ ๋ฌธ์ ๋ฅผ ์ ํด๊ฒฐํ ๊ฒ ๊ฐ์ต๋๋ค.
๊ฐ๋ฐ์๊ฐ ์ด๋ฌํ ๊ฒ์ ๋ํด ์๊ฐํด์๋ ์ ๋๋ค๊ณ ์ ์ํ๋ ๊ฒ์ ์๋์ง๋ง 99% ์ฌ์ฉ ์ฌ๋ก๋ ๊ฑฐ์ ํญ์ ์ฌ์ฉ๋๋ StatefulWidget์ ๋ฐ์ธ๋ฉ๋์ด ์๊ณ ๊ทธ ์ด์ธ์ ๋ค๋ฅธ ์์ ์ ์ํํ๋ฉด ์ด๋ฏธ ์ค๊ฐ ๊ฐ๋ฐ์ ์์ญ์ผ๋ก ์ด๋ํ๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ค์ ๋งํ์ง๋ง ์ด๊ฒ์ด ์์ AnimatorController๋ณด๋ค TweenAnimationBuilder๋ฅผ ๊ถ์ฅํ๋ ๊ฒ๊ณผ ๊ทผ๋ณธ์ ์ผ๋ก ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๊ทธ๊ฒ์ ๊ธฐ๋ณธ์ ์ผ๋ก์ด ๋ค๋ฅธ ์ํ์์ ๊ด๋ฆฌ ์ํ ์ง๋ถ์ ํฌํจ์ / ์ํ๋ (๊ทธ๋ฆฌ๊ณ ๋น์ ์ด ์ํ๋ ๋ณดํต) ๊ฒฝ์ฐ, ๋ค์์ด ๋ฐฉ๋ฒ์ ๊ฐ๋จํ๊ณ ๊ฐ๋ ฅํ์ ํ ์ ์๋ค๋ ์๊ฐ์ด๋ค.
์ด ์์ ์์ ์ฐ๋ฆฌ๋ ํตํ๋ฅผ ์กฐ์งํ๊ณ ๋ค์ํ ์ดํด ๊ด๊ณ์์ ํจ๊ป ๋
ผ์ํด์ผ ํฉ๋๋ค.
๊ฐ์ ์ง๋ฌธ์ ๊ณ์ํด์ ๋ตํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด ํ ๋ก ์ด ์งํ๋์ง ์๊ณ ์์ต๋๋ค.
๋๋ ๊ทธ๋ ๊ฒ ๊ธด ํ ๋ก ๊ณผ ๋ง์ ๋ ผ์ ๋์ ์ด๋ป๊ฒ StatefulWidget์ ๋นํด ๋น๋๊ฐ ์ค์๋ฅผ ํผํ์ง ์๊ฑฐ๋ ํํฌ๊ฐ ์์ StatefulWidget๋ณด๋ค ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ์ง ์๋ค๊ณ ์ฃผ์ฅํ ์ ์๋์ง ์ดํดํ์ง ๋ชปํฉ๋๋ค.
๋ชจ๋ ์ฃผ์ ์ ์ธ์ ํ๋ ์์ํฌ(React, Vue, Swift UI, Jetpack Compose)์ ์ด ๋ฌธ์ ๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๋ค๋ ์ ์ ๊ณ ๋ คํ๋ฉด ํนํ ์ค๋ง์ค๋ฝ์ต๋๋ค.
Flutter๋ง์ด ์ด ๋ฌธ์ ๋ฅผ ๊ณ ๋ คํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
@esDotDev IMHO๊ฐ AnimationBuilder, TweenAnimationBuilder ๋๋ ValueListenableBuilder๋ฅผ ์ฌ์ฉํ๋ ์ฃผ๋ ์ด์ ๋ ํธ์คํธ ์์ ฏ์ ๋๋จธ์ง ๋ถ๋ถ์ ๋ค์ ๋น๋ํ์ง ์๊ณ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง ๋ค์ ๋น๋ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฑ๋ฅ ๋ฌธ์ ์ ๋๋ค. ์์ธํ ์ ๋ณด๋ ์ฝ๋ ์ฌ์ฌ์ฉ์ ๊ดํ ๊ฒ์ด ์๋๋๋ค. ๋ด ๋ง์, ๊ทธ๋ฌํ ์ด์ ๋ก ๊ทธ๊ฒ๋ค์ ์ฌ์ฉํ๋ ๊ฒ๋ ๊ด์ฐฎ์ต๋๋ค. ๊ทธ๋ฌํ ์ด์ ๋ก ์ ์ฉํ๋ค๊ณ ์๊ฐํ๋ค๋ฉด ์ ์ด๋ ์ ์๊ฒ๋ ๊ทธ๊ฒ์ด ์ฃผ์ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์๋๋๋ค. ๋ํ Property(๋๋ Hooks)๊ฐ ์ ๊ณตํ์ง ์๋ ๊ฒ์ ๋๋ค. ๊ทธ๊ฒ๋ค์ ์ฌ์ฉํ๋ฉด ๋ฌด์ธ๊ฐ๊ฐ ๋ณ๊ฒฝ๋ ๋ _entire_ ์์ ฏ์ ๋ค์ ๋น๋ํ๊ฒ ๋๋ฉฐ, ์ด๋ ์ฑ๋ฅ์ ์ข์ง ์์ต๋๋ค.
@rrousselGit
Flutter๋ง์ด ์ด ๋ฌธ์ ๋ฅผ ๊ณ ๋ คํ์ง ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ ๋ ์ด๋ฒ ์ฃผ๋ง์ ๋ฌธ์ ๊ทธ๋๋ก ๋ช ์๊ฐ์ ๋ณด๋์ต๋๋ค. ๊ทธ ์ ์๋ Google์์ ๋ณด๋ธ ๋ง์ ์๊ฐ์ ๋งํ ๊ฒ๋ ์๊ณ , ์ด ๋ฌธ์ ๋ฅผ ๊ณ ๋ คํ๊ณ ๊ฐ๋ฅํ ์๋ฃจ์ ์ ์ค๋ช ํ๊ณ ์ฐ๋ฆฌ๊ฐ ํด๊ฒฐํ๋ ค๋ ๊ฒ์ ์ ํํ๊ฒ ๋์ถํ๋ ค๊ณ ๋ ธ๋ ฅํ์ต๋๋ค. ์ดํด์ ๋ถ์กฑ๊ณผ ๊ณ ๋ ค๋ฅผ ๊ฑฐ๋ถํ๋ ๋ฌธ์ ๋ฅผ ํผ๋ํ์ง ๋ง์ญ์์ค. ํนํ ์ด ๋ฌธ์ ๋ฅผ ๊ณ์ ์งํํ๊ธฐ ์ํด ํ ์ ์๋ ์ต์ ์ ๋ฐฉ๋ฒ์ ์ด๋ฏธ ์ค๋ช ํ ๊ฒฝ์ฐ(๋ฌธ์ ์ ๋ชฉ์ ์ธ์ฉํ๊ฑฐ๋ ์ฌ์ฌ์ฉํ๊ธฐ์๋ "๋๋ฌด ์ฅํฉํ๊ฑฐ๋ ๋๋ฌด ์ด๋ ค์ด" ์ํ ๋ ผ๋ฆฌ๋ฅผ ๋ชจ๋ ํฌํจํ๋ ๋ฐ๋ชจ ์ฑ ๋ง๋ค๊ธฐ) ์ด ๋ฒ๊ทธ์ ๋ํ ๋ค๋ฅธ ์ฌ๋๋ค์ด ์์ ์ ๋งก์๊ณ ๊ทํ๊ฐ ์ฐธ์ฌ๋ฅผ ๊ฑฐ๋ถํ์ต๋๋ค.
The main reason IMHO to use an AnimationBuilder or TweenAnimationBuilder or ValueListenableBuilder is that they rebuild only when the value changes, without rebuilding the rest of their host widget. It's a performance thing.
ํฅ๋ฏธ๋ก์ด. ์ฐ๋ฆฌ๋ ์ค์ ๋ก ์ด์ ๊ฐ์ ์๊ท๋ชจ ์ฌ๊ตฌ์ถ์ ์ ์ฅํจ์ผ๋ก์จ ์ฑ๋ฅ ํฅ์์ ์ธก์ ํ๊ฑฐ๋ ๊ด์ฐฐํ ์ ์ด ์์ต๋๋ค. 2์ฃผ๋ง๋ค ์๋ฐฑ ๊ฐ์ ํด๋์ค ํ์ผ์ ์ ๊ฑฐํ ๋ ๋ฐ์ํ ์ ์๋ ์ผ์์ ์ธ ์ค๋ฅ ์์ด ์ฝ๋๋ฅผ ๊ฐ๊ฒฐํ๊ณ ๊ฐ๋ ์ฑ ์๊ฒ ์ ์งํ๋ ๊ฒ์ด ๋๊ท๋ชจ ์ฑ ์ฝ๋ ๊ธฐ๋ฐ๋ณด๋ค ํจ์ฌ ๋ ์ค์ํฉ๋๋ค.
RepaintBoundaries๋ฅผ ์๋์ ์ผ๋ก ์ ์ํ์ง ์๋ ํ ์ ์ฒด ํธ๋ฆฌ์ ๋ฐ์ํ๋ ๊ฒ์ผ๋ก ๋ณด์ด๋ ํฝ์ ๋ค์ ๊ทธ๋ฆฌ๊ธฐ ๋น์ฉ์ ๋ถ๋ถ ์์ ฏ ๋ ์ด์์ ๋น์ฉ๋ณด๋ค ์ค์ ์ฑ๋ฅ์์ ํจ์ฌ ๋ ์ค์ํ ์์์ ๋๋ค. ํนํ 4k ๋ชจ๋ํฐ ๋ฒ์์ ๋ค์ด๊ฐ ๋.
๊ทธ๋ฌ๋ ์ด๊ฒ์ ๊ฑด์ถ์ ์๊ฐ ์ค์ ๋ก ์ด๋ฐ ์ข ๋ฅ์ ์ผ์ ์ดํดํ๋ ์ข์ ์์ ๋๋ค. ํ์ ์ปจํ ์คํธ๋ฅผ ๋ง๋ค๊ณ ์ถ๋ค๋ฉด ๋น๋๊ฐ ์๋ฏธ๊ฐ ์์ผ๋ฉฐ ๊ฑฐ๊ธฐ์ ๋๋ฌํ๋ ์ข์ ๋ฐฉ๋ฒ์ ๋๋ค.
์ฐ๋ฆฌ๋ ๊ทธ๋ ๊ฒ ํ์ง ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์ด ๊ฒฝ์ฐ Builder๋ ํด๋ฌํฐ๋ฅผ ์ถ๊ฐํ ๋ฟ์ด์ง๋ง ๋์์ ๋ค๋ฅธ ์ ํ์ ํด๋ฌํฐ์ผ ๋ฟ์ด๋ฏ๋ก ํ์ฉํฉ๋๋ค. ์ ์ด๋ Builder์์๋ ๋ฒ๊ทธ๊ฐ ๊ฑฐ์ ์์์ด ๋ณด์ฅ๋ฉ๋๋ค. ์ ์ฒด ๋ณด๊ธฐ๊ฐ ๋ค์ ๋น๋๋๊ฑฐ๋ ๋ฐ๋์ ๋ณด๊ธฐ๋ฅผ ๋ค์ ๋น๋ํ ํ์๊ฐ ์ ํ ์๋ ๊ฒฝ์ฐ(TextEditingController, FocusController) ๋น๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ฑฐ์ ์๋ฏธ๊ฐ ์์ผ๋ฉฐ ๋ชจ๋ ๊ฒฝ์ฐ์ ์์ฉ๊ตฌ๋ฅผ ์์ผ๋ก ๊ตด๋ฆฌ๋ ๊ฒ์ ๊ธฐ๋ณธ์ ์ผ๋ก DRY๊ฐ ์๋๋๋ค.
์ฑ๋ฅ ๋ฌธ์ ๊ฐ ์์ฃผ ๋ฐ์ํ๋ฏ๋ก ํ์คํ ์ํฉ์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. ๋๋ ์ฌ๋๋ค์ด ๊ทธ๋ฐ ์คํ์ผ์ ์ข์ํ๋ค๋ฉด Hooks๋ Property ๊ฐ์ ๊ฒ์ ์ฌ์ฉํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๊ฒ์ ์ค๋๋ ๊ฐ๋ฅํ๋ฉฐ ํ๋ ์์ํฌ์์ ์ถ๊ฐ๋ก ํ์ํ ๊ฒ์ด ์๋ ๊ฒ ๊ฐ์ต๋๋ค(๊ทธ๋ฆฌ๊ณ Property์์ ์ ์ ์๋ฏ์ด ์ค์ ๋ก ๋ง์ ์ฝ๋๊ฐ ํ์ํ์ง ์์ต๋๋ค).
์๋์, ํ์ง๋ง ์ปค๋ฎค๋ํฐ์ TweenAnimationBuilder ๋ฐ ValueListenableBuilder๋ฅผ ๋น๋ํ๋๋ก ์์ฒญํ๊ณ ๋น๋ํ StatefulWidget์ ์ ๊ณตํ์ง ์๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
๋น์ ์ด ๋ฌป๋ ๊ฒ์ ์๋์ง๋ง ์ด๋ฌํ ์ ํ์ ์ํคํ ์ฒ์ ์ฃผ์ ์ด์ ์ค ํ๋๋ ์ฝ๊ฒ ๊ณต์ ํ ์ ์๋ ์์ฃผ ์์ ๊ตฌ์ฑ ์์์ ์์ฐ์ค๋ฝ๊ฒ ์ ํฉํ๋ค๋ ๊ฒ์ ๋๋ค. ์์ ๊ธฐ์ด ์กฐ๊ฐ์ ์ ์๋ฆฌ์ ๋ฐฐ์นํ๋ฉด ...
StatefulWidget์ Property์ ๋นํด _lot_ ๋ง์ ์ฝ๋์ด๋ฉฐ ์ค์ํ์ง ์์ต๋๋ค(๋๋ถ๋ถ ๊ธ๋ฃจ ์ฝ๋์ธ Property์ ๋ฌ๋ฆฌ). ์ฆ, Property๊ฐ ๊ด๋ฒ์ํ๊ฒ ์ฌ์ฌ์ฉํ ์ ์๋ ๊ฒ์ด๋ผ๋ฉด(์ ํํ ํ์์ ๋ฐ๋ผ ๊ฐ ์์ฉ ํ๋ก๊ทธ๋จ์ด๋ ํ์ ๋ํ ๋ง์ถคํ ๋ฒ์ ์ ๋ง๋๋ ๊ฒ๊ณผ๋ ๋์กฐ์ ์ผ๋ก), ๋๋ ๊ทธ ์ฌ์ฉ์ ์นํธํ๋ ๋๊ตฐ๊ฐ์๊ฒ ํจํค์ง๋ฅผ ๋ง๋ค์ด ์
๋ก๋ํ๋๋ก ๊ถ์ฅํฉ๋๋ค. pub
. ์ค์ ๋ก Hooks์๋ ๋์ผํ๊ฒ ์ ์ฉ๋ฉ๋๋ค. ์ปค๋ฎค๋ํฐ๊ฐ ์ข์ํ๋ ๊ฒ์ด๋ผ๋ฉด Provider์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ง์ด ์ฌ์ฉ๋ฉ๋๋ค. ํ๋ ์์ํฌ ์์ฒด์ ๊ทธ๋ฐ ๊ฒ์ ๋ฃ์ด์ผ ํ๋ ์ด์ ๋ ๋ช
ํํ์ง ์์ต๋๋ค.
์ด๊ฒ์ ๋ณธ์ง์ ์ผ๋ก ํ์ฅ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ณต๊ธ์๋ ์๋๋๋ค. ๋จ์ํ ๋๊ตฌ์ผ ๋ฟ์ ๋๋ค. ์ด๊ฒ์ StatefulWidget๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก StatefulComponent๋ฅผ ์ํด ํ์ฅ๋๋๋ก ๋ง๋ค์ด์ง ๊ฒ์ ๋๋ค. ์๋์ ์ผ๋ก ์ฌ์ํ๋ค๋ ์ฌ์ค์ด ๋ฐ๋์ ๋ฐ๋๋์ด์ผ ํ๋ ๊ฒ ์๋๊ฐ?
"์ด ์คํ์ผ์ ์ ํธํ๋ ์ฌ๋๋ค"์ ๋ํ ๋ฉ๋ชจ. 3๊ฐ์ ์ฌ์ ์์ 15-30์ค์ ์ ์ฅํ ์ ์๋ค๋ฉด ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๊ฐ๋ ์ฑ์ด ํฅ์๋ ๊ฒ์ ๋๋ค. ๊ฐ๊ด์ ์ผ๋ก ๋งํ์๋ฉด. ๋ํ ๊ฐ๊ด์ ์ผ๋ก 2๊ฐ์ง ์ ์ฒด ์ค๋ฅ ํด๋์ค๋ฅผ ์ ๊ฑฐํฉ๋๋ค(์ฌ๋ฌผ ์ฒ๋ฆฌ๋ฅผ ์๊ฑฐ๋ deps ์ ๋ฐ์ดํธ๋ฅผ ์์).
๋ฉ์ง ํ ๋ก ์ ๋ํด ์ ๋ง ๊ฐ์ฌํฉ๋๋ค. ์ด๊ฒ์ด ์ด๋๋ก ๊ฐ๋์ง ๋ณด๊ณ ํฅ๋ถ๋ฉ๋๋ค. ์ ๋ ํ์คํ ์ฌ๊ธฐ์ ๋จ๊ธธ ๊ฒ์ ๋๋ค. :)
์ด ์ค๋ ๋๊ฐ ๋ด๊ฐ ์์ ์ค์ธ ๋ค๋ฅธ ํ๋ก์ ํธ๋ฅผ ๋ง์น ๋ ๊ณํํ๋ ํ๋ฌํฐ์ ๋ค์ ๋น ์ ธ๋๋ ๊ฒ์ ํ๋ฉธ์ค๋ฝ๊ฒ ๋ง๋ ๋ค๊ณ ๋งํ๋ ๊ฒ์ ์ ๊ฐ์ค๋ฝ๊ฒ ์๊ฐํฉ๋๋ค. ๋๋ฌธ์ ์ข์ ๋ ๋๋๋ค.
๋ชจ๋ ์ฃผ์ ์ ์ธ์ ํ๋ ์์ํฌ(React, Vue, Swift UI, Jetpack Compose)์ ์ด ๋ฌธ์ ๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๋ค๋ ์ ์ ๊ณ ๋ คํ๋ฉด ํนํ ์ค๋ง์ค๋ฝ์ต๋๋ค.
์ด ์ค๋ ๋์์ ๋ฌธ์ ๊ฐ ๋ฐ๋ณตํด์ ๋ช
ํํ๊ฒ ์ค๋ช
๋์๊ธฐ ๋๋ฌธ์ Flutter ์์ ์ฑ์ ๊ตฌ์ถํ๋ ๋ฐ ์๊ฐ์ ํ ์ ํด์๋ ์ ๋๋ค๊ณ ์๊ฐํ๋ค๋ ์ ์์
๋ํ ์ฑ์ ์์ฑํ๋ ค๋ฉด ์๋ฃจ์
์ด ํ์ํ๊ธฐ ๋๋ฌธ์ ์๋ฃจ์
์ ์ฐพ๊ณ ์๋ค๋ฉด ํ๋ฌํฐ๋ก ์ฑ์ ์์ฑํ ์ ์์ต๋๋ค. ์ด ๋ํ์ ํ๋ฌํฐ ์ฌ๋๋ค์ ์ต์ํ ํํฌ๋ฅผ ์ข์ํ์ง ์๋๋ค๋ ๊ฒ์ด ๊ฝค ๋ถ๋ช
ํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ Flutter์๋ OP์ ์ค๋ช
๋ ๋๋ก ๋ฌธ์ ์ ๋ํ ๋ค๋ฅธ ์๋ฃจ์
์ด ์์ต๋๋ค. ์ด๋ป๊ฒ ์์ฑํด์ผํฉ๋๋ค.
(์ ์ด๋ ๋์๊ฒ๋) ์ด๊ฒ์ด ์ฌ๊ฐํ๊ฒ ๋ฐ์๋ค์ฌ์ง์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. @Hixie ์ฃ์กํฉ๋๋ค. We understand the problem and want to solve it
์๋ฏธ์์ ์ฌ๊ฐํ๊ฒ ๋ฐ์๋ค์ด์ง ์๋๋ค๋ ๋ป์
๋๋ค. ๋ค๋ฅธ ์ ์ธ์ ํ๋ ์์ํฌ์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ถ๋ช
ํ ์๋ฃ๋ ๊ฒ ๊ฐ์ต๋๋ค.
๋ ๋ค๋ฅธ ์ข
๋ฅ์ ๋์ผํ ๋ฉ๋ชจ์ ๋ค์๊ณผ ๊ฐ์ ๋ด์ฉ์ด ์์ต๋๋ค.
์ฐ๊ธฐ๊ฐ ๋ ์ฝ๋์?
๊ฐ๋ฐ์๋ ์๋ก์ด ๊ฐ๋ ์ธ ํํฌ๋ฅผ ์์ฑํ๋ ๋ฒ์ ๋ฐฐ์์ผ ํ๋ฏ๋ก ๋ ์ด๋ ต์ต๋๋ค.
๋๋ฅผ ์ฌํ๊ฒ ๋ง๋ค์ด. ์ ๊ฐ์ ํ๊ฑฐ๋ ๋ณ๊ฒฝํฉ๋๊น? ๋น์ ์ ๋ฌด์จ ์ผ์ด ์์ด๋ ํญ์ ๊ทธ ์ฃผ์ฅ์ ํ ์ ์์ต๋๋ค. ์๋ก์ด ์๋ฃจ์ ์ด ํ ๋ฒ ๋ฐฐ์ฐ๋ฉด ํจ์ฌ ์ฝ๊ณ ์ฆ๊ฒ๋๋ผ๋. ํด๋น ๋ช ๋ น๋ฌธ์ ํํฌ๋ฅผ ๋ง์ ๊ฒ์ผ๋ก ๋์ฒดํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ ์๋ง๋ 30๋ ์ ์ ์ ์๋ ์ธ์ง์ ๋ํด ๊ทธ๋ฐ ๋ง์ ์ฌ์ฉํ์ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋ฌธ์ฅ์์ "hooks"๋ฅผ "flutter" ๋๋ "dart"๋ก ๋ฐ๊พธ๋ฉด ๋์ผํ๊ฒ ์๋ํฉ๋๋ค.
์ฐ๊ธฐ๊ฐ ๋ ์ฝ๋์?
๋๊ฐ์ผ๋ ์ฐ๊ธฐ๋ ์ฝ๋ค์.
is it easier to write?
(๋ถ์ธ ๋ต๋ณ ์ง๋ฌธ)์์ @rrousselGit์ด ์๋ฏธํ๋ ๋ฐ๋ ๋์ผํ๋ค๋ฉด ๋๋ต์ด false
/ undefined
๊ฐ ์๋๋ผ๋ ๊ฒ์
๋๋ค.
๋๋ ์ฐ๋ฆฌ๊ฐ ๋ฌธ์ ๊ฐ ์๋ค๋ ๊ฒ์ ๋์ํ์ง๋ ์๊ณ ๋จ์ง ๋ง์ ์ฌ๋๋ค์ด ์ด๊ฒ์ ๋ฌธ์ ๋ก ์ฌ๊ธด๋ค๋ ์ฌ์ค์ ๋์ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ด๋ป๊ฒ ์ฐ๋ฆฌ๊ฐ ์ด๋๊ฐ์ ๋๋ฌํ ์ ์์์ง ์ ์ ์์ต๋๋ค. ์:
๊ทธ๊ฒ์ ํ์คํ ์ฌ๋๋ค์ด ์ ๊ธฐํ ๊ฒ์ ๋๋ค. ๊ทธ๊ฒ์ ๋ด๊ฐ ๋ณธ๋ฅ์ ์ผ๋ก ๊ฒฝํํ ๊ฒ์ด ์๋๋๋ค. Flutter๋ก ๋ด ์์ ์ ์ฑ์ ์์ฑํ ๋ ๋ฌธ์ ๋ผ๊ณ ๋๋ ๊ฒ์ ์๋๋๋ค. ๊ทธ๋ ๋ค๊ณ ํด์ ์ผ๋ถ ์ฌ๋๋ค์๊ฒ ์ค์ ๋ฌธ์ ๊ฐ ๋์ง ์๋๋ค๋ ์๋ฏธ๋ ์๋๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ง์ ์ฌ๋๋ค์ด OP์ ๋ํ ์๋ฃจ์
์ด ํต์ฌ์ ์์ด์ผ ํ๋ ์ด์ ์ ๋ํด ์ฌ๋ฌ ๋ฒ ๋ง์ ์ฃผ์ฅ์ ํ์์๋ ๋ถ๊ตฌํ๊ณ .
์๋ฅผ ๋ค์ด, ์ 3์๊ฐ ์ค๋๋ ์์ ฏ์ ์ฌ์ฉํ๊ณ ์์ฑํ๋ ๊ฒ์ฒ๋ผ ์ฝ๊ณ ์์ฐ์ค๋ฝ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ ค๋ฉด ํต์ฌ์ด ๋์ด์ผ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค๋ฅธ ์ฌ๋ฌ ์ด์ . ๋งํธ๋ผ๋ ํจํค์ง์ ๋ฃ๋ ๊ฒ๋ฟ์ธ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฏธ ํํฌ์ ๊ฐ์ ํจํค์ง๊ฐ ์์ต๋๋ค. ๊ทธ๊ฒ์ด ํด๊ฒฐ ๋ ๊ฒ์ด๋ผ๋ฉด ์ค๋ ๋๋ฅผ ๋ซ์ผ์ญ์์ค.
@rrousselGit์ ์ ์์ ์ฃผ์ ํด
์ด์จ๋ , ๋๋ ์ด ์ค๋ ๋๊ฐ ์ด๋๋ก ๊ฐ๋์ง ๋ณด์ด์ง ์๊ธฐ ๋๋ฌธ์ ์ด ์ค๋ ๋๋ฅผ ๋ผ์ด๋ธ ํ๋ก์ฐํ๋ ๊ฒ์ด ์กฐ๊ธ ์ฌํ๊ธฐ ๋๋ฌธ์ ์ง๊ธ ๊ตฌ๋ ์ ์ทจ์ํ๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด ์ค๋ ๋๊ฐ ๋ฌธ์ ๊ฐ ์๋ค๋ ๋ฐ ๋์ํ๋ ์ํ์ ๋๋ฌํ์ฌ OP์ ๋ํ ๊ฐ๋ฅํ ์๋ฃจ์ ์ ์ง์คํ ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. @Hixie๊ฐ ์๋ง๋ ๋์
์ฌ๋๋ค์ด ์ํ์ง๋ง ํ๋ฌํฐ๊ฐ ์ด ๋ฌธ์ ๋ฅผ ํต์ฌ์ ์ผ๋ก ํด๊ฒฐํด์๋ ์ ๋๋ค๊ณ ๋จํธํ๊ฒ ๋งํจ์ผ๋ก์จ ์ด ์ค๋ ๋๋ฅผ ๋๋ด๋ ๋ฐ ํ์ด์ด ์๊ธฐ๋ฅผ ์ง์ฌ์ผ๋ก ๋ฐ๋๋๋ค. ๋๋ ํด๊ฒฐ์ฑ ์ ์ฐพ๋ ๊ฒ์ ๋๋ค. ๐
LayoutBuilder๋ ๋๋ถ๋ถ์ ๋น๋์ธ FWIW์๋ ๋งค์ฐ ๋ค๋ฅธ ์์ ฏ์ ๋๋ค. ์ง๊ธ๊น์ง ๋ ผ์๋ ์ ์ ์ค ์ด๋ ๊ฒ๋ LayoutBuilder์ ์ ์ฌํ ๋ฌธ์ ์ ๋ํด ์๋ํ์ง ์์ผ๋ฉฐ ๊ทํ์ ์๊ฒฌ ์ ์ ์ค๋ช ๋ ์๊ตฌ ์ฌํญ์๋ LayoutBuilder๊ฐ ํฌํจ๋์ด ์์ง ์์ต๋๋ค. ์ด ์๋ก์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ LayoutBuilder๋ฅผ ์ฒ๋ฆฌํด์ผ ํ๋์ง๋ ์์์ผ ํฉ๋๋ค. @TimWhiting ๊ณผ
@Hixie ์, ํ์คํ ์ํ์ด ํ์ํฉ๋๋ค. ๋๋ ๋ญ๊ฐ๋ฅผ ์ค๋นํ ๊ฒ์ด๋ค(๊ทธ๋ฌ๋ ๋๋ ์ฌ์ ํ ์ปดํ์ผ๋ฌ ๋ณ๊ฒฝ์ด ํ์ํ๋ฏ๋ก ์ํ์ด ๋ถ์์ ํ ์ ์๋ค๊ณ ์๊ฐํ๋ค). ์ผ๋ฐ์ ์ธ ์์ด๋์ด๋ - ๋น๋๋ฅผ ํ๋ฉดํํ๊ณ ๋น๋๊ฐ ๊ตฌํ๋๋ ๋ฐฉ๋ฒ์ ๋ํด ์ ๊ฒฝ ์ฐ์ง ์๋ ๊ตฌ๋ฌธ ์คํ์ ๋๋ค.
๊ทธ๋๋ Flutter ํ์ ์ด๋ ๋๊ตฌ๋ SwiftUI๋ฅผ ์์ธํ ์ดํด๋ณด์ง ์์๋ค๋ ์ธ์์ ๋ฐ๊ณ ์์ต๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ฐ๋ฆฌ์ ์ฐ๋ ค๊ฐ ์ดํดํ๊ธฐ ์ฌ์ธ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ํ๋ ์์ํฌ์ ๋ฏธ๋๋ฅผ ์ํด์๋ ๋ค๋ฅธ ํ๋ซํผ์์ ๋ง์ด๊ทธ๋ ์ด์ ํ๋ ์ฌ๋๋ค์ด ์ต๋ํ ์ํํ๊ฒ ํ๋ ๊ฒ์ด ์ค์ํ๋ฏ๋ก ๋ค๋ฅธ ํ๋ซํผ์ ๋ํ ์ถฉ๋ถํ ์ดํด์ ์ฅ๋จ์ ์ ๋ํ ์ง์์ด ํ์ํฉ๋๋ค. Flutter์ ๋จ์ ์ค ์ผ๋ถ๋ฅผ ์์ ํ ์ ์๋์ง ํ์ธํฉ๋๋ค. ๋ถ๋ช ํ Flutter๋ React์์ ๋ง์ ์ข์ ์์ด๋์ด๋ฅผ ์ป์๊ณ ์ ๋ ์๋ก์ด ํ๋ ์์ํฌ๋ก ๋๊ฐ์ด ํ ์ ์์ต๋๋ค.
@emanuel-lundman
(์ ์ด๋ ๋์๊ฒ๋) ์ด๊ฒ์ด ์ฌ๊ฐํ๊ฒ ๋ฐ์๋ค์ฌ์ง์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. @Hixie ์ฃ์กํฉ๋๋ค.
We understand the problem and want to solve it
์๋ฏธ์์ ์ฌ๊ฐํ๊ฒ ๋ฐ์๋ค์ด์ง ์๋๋ค๋ ๋ป์ ๋๋ค. ๋ค๋ฅธ ์ ์ธ์ ํ๋ ์์ํฌ์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ถ๋ช ํ ์๋ฃ๋ ๊ฒ ๊ฐ์ต๋๋ค.
๋ฌธ์ ๋ฅผ ์ดํดํ์ง ๋ชปํ๋ค๋ ๋ฐ ์ ์ ์ผ๋ก ๋์ํฉ๋๋ค. ๊ทธ๊ฒ์ด ๋ด๊ฐ ์ด ๋ฌธ์ ์ ๊ณ์ ๊ด์ฌํ๊ณ ์ดํดํ๋ ค๊ณ ๋ ธ๋ ฅํ๋ ์ด์ ์ ๋๋ค. ์ด๊ฒ์ด ์ ๊ฐ ๋ฌธ์ ๋ฅผ ์บก์ํํ๋ ๋ฐ๋ชจ ์ฑ์ ๋ง๋ค ๊ฒ์ ์ ์ํ ์ด์ ์ ๋๋ค. ๊ฒฐ๊ตญ ์ฐ๋ฆฌ๊ฐ ํ๋ ์์ํฌ๋ฅผ ๊ทผ๋ณธ์ ์ผ๋ก ๋ณ๊ฒฝํ์ฌ ์์ ํ๊ธฐ๋ก ๊ฒฐ์ ํ ๋ฌธ์ ์ธ์ง, ํ๋ ์์ํฌ์ ์์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ฑฐ๋, ํจํค์ง๋ก ์์ ํ๊ฑฐ๋, ์ ํ ์ฌ์ฉํ์ง ์๋์ง ์ฌ๋ถ๋ ์ค์ ๋ก ๋ฌธ์ ๊ฐ ๋ฌด์์ธ์ง์ ๋ฌ๋ ค ์์ต๋๋ค.
@szotp
๊ทธ๋๋ Flutter ํ์ ์ด๋ ๋๊ตฌ๋ SwiftUI๋ฅผ ์์ธํ ์ดํด๋ณด์ง ์์๋ค๋ ์ธ์์ ๋ฐ๊ณ ์์ต๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ฐ๋ฆฌ์ ์ฐ๋ ค๊ฐ ์ดํดํ๊ธฐ ์ฌ์ธ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
์ ๋ ์ค์ํํธ UI๋ฅผ ๊ณต๋ถํ์ต๋๋ค. Flutter ์ฝ๋๋ณด๋ค Swift UI ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด ํ์คํ ๋ ์ฅํฉํ์ง๋ง ๊ฐ๋ ์ฑ ๋น์ฉ์ IMHO๊ฐ ๋งค์ฐ ๋์ต๋๋ค. "๋ง๋ฒ"(์๋น์ ์ฝ๋์์ ๋ช ํํ์ง ์์ ๋ฐฉ์์ผ๋ก ์๋ํ๋ ๋ ผ๋ฆฌ๋ผ๋ ์๋ฏธ์์)์ด ๋ง์ด ์์ต๋๋ค. ์ผ๋ถ ์ฌ๋๋ค์ด ์ ํธํ๋ ์คํ์ผ์ด๋ผ๊ณ ์ ์ ์ผ๋ก ๋ฏฟ์ ์ ์์ง๋ง Flutter์ ์ฅ์ ์ค ํ๋๋ ๋ง์ ์ด ๊ฑฐ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ด๋ ๋๋๋ก ๋ ๋ง์ ์ฝ๋๋ฅผ ์์ฑํ๋ค๋ ๊ฒ์ ์๋ฏธํ์ง๋ง, ๋ํ ํด๋น ์ฝ๋๋ฅผ ๋๋ฒ๊น ํ๋ ๊ฒ์ด _ํจ์ฌ_ ๋ ์ฝ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
๋ง์ ์คํ์ผ์ ํ๋ ์์ํฌ๋ฅผ ์ํ ์ฌ์ง๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. MVC ์คํ์ผ, React ์คํ์ผ, ๋งค์ฐ ๊ฐ๊ฒฐํ ๋ง์ , ๋ง์ ์ด ํ์ ์์ง๋ง ์ฅํฉํ... Flutter ์ํคํ ์ฒ์ ์ฅ์ ์ค ํ๋๋ ์ด์์ฑ ์ธก๋ฉด์ด ํ๋ ์์ํฌ ์์ฒด์ ์์ ํ ๋ถ๋ฆฌ๋์ด ์์ผ๋ฏ๋ก ๋ชจ๋ ๋๊ตฌ๋ฅผ ํ์ฉํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. -- ํฌ๋ก์ค ํ๋ซํผ ์ง์, ํซ ๋ฆฌ๋ก๋ ๋ฑ -- ์์ ํ ์๋ก์ด ํ๋ ์์ํฌ๋ฅผ ๋ง๋ญ๋๋ค. (์: flutter_sprites์ ๊ฐ์ ๋ค๋ฅธ Flutter ํ๋ ์์ํฌ๊ฐ ์ด๋ฏธ ์์ต๋๋ค.) ๋ง์ฐฌ๊ฐ์ง๋ก ํ๋ ์์ํฌ ์์ฒด๋ ๋ ์ด์ด ๋ฐฉ์์ผ๋ก ์ค๊ณ๋์ด ์์ด ์๋ฅผ ๋ค์ด ๋ชจ๋ RenderObject ๋ก์ง์ ์ฌ์ฌ์ฉํ ์ ์์ง๋ง ์์ ฏ ๋ ์ด์ด๋ฅผ ๋์ฒดํ ์ ์์ต๋๋ค. ์์ ฏ์ด ๋๋ฌด ๋ง์ต๋๋ค. ๋๊ตฐ๊ฐ ์ด๋ฅผ ๋์ฒดํ ๋์ฒด ํ๋ ์์ํฌ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ๋ฌผ๋ก ํจํค์ง ์์คํ ์ด ์์ผ๋ฏ๋ก ๊ธฐ์กด ํ๋ ์์ํฌ ์ฝ๋๋ฅผ ์์ง ์๊ณ ๊ธฐ๋ฅ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
์ฌํํผ, ์ฌ๊ธฐ์์ ๋ด ์์ฌ์ ์์ ์ ์ด๊ฒ์ด ์ ๋ถ ์๋๋ฉด ์ ๋ฌด๊ฐ ์๋๋ผ๋ ๊ฒ์ ๋๋ค. ์ฅ๊ธฐ์ ์ผ๋ก ์ฐ๋ฆฌ๊ฐ ๋น์ ์ ํ๋ณตํ๊ฒ ํ๋ ์๋ฃจ์ ์ ์ฑํํ์ง ์๋๋ผ๋, ๊ทธ๊ฒ์ด ๋น์ ์ด ์ข์ํ๋ ์ ํ์ ์ผ๋ถ๋ก๋ถํฐ ๊ณ์ ํํ์ ๋ฐ์ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํ์ง๋ ์์ต๋๋ค.
์ด ๋ฌธ์ ์ ๊ด์ฌ์ด ์๋ ์ฌ๋๋ค์ @TimWhiting ๊ณผ ๋ถ๊ฐ๋ฅํ ๋ ์ค๋๋ ์ ๋ชจ์ต์ ๋ณด์ฌ์ฃผ๋ ์ฑ์ ๋ง๋ค ๊ฒ์ ์ด๊ตฌํฉ๋๋ค(https://github.com/TimWhiting/local_widget_state_approaches). ์ด๊ฒ์ ์ฌ๊ธฐ์ ๋๊ธ์ ๋ฌ๊ณ ์๋ _๋ชจ๋ __ ์ฌ๋๋ค(Hooks๋ฅผ ์ข์ํ๋ ์ฌ๋๋ค๊ณผ Hooks๋ฅผ ์ข์ํ์ง ์๋ ์ฌ๋๋ค ํฌํจ)์ ์๊ตฌ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ์์ผ๋ก ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ ์์ ๋ง๋๋ ๋ฐ ์ง์ ์ ์ธ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
"_๋น๋๋ฅผ ํ๋ฉดํํ๊ณ ๋น๋๊ฐ ๊ตฌํ๋๋ ๋ฐฉ๋ฒ์ ์ ๊ฒฝ ์ฐ์ง ์๋ ๊ตฌ๋ฌธ ์คํ._"์ด ๊ฐ๋ฐ์๊ฐ ์ผ๊ธ ๊ธฐ๋ฅ์ผ๋ก ์ํ๋ ์ด์ ๋ฅผ ์ดํดํ๋ ๊ฒ์ ์ ๋ง ์ด๋ ต์ง ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๋์ฒด ์ ๊ทผ ๋ฐฉ์์ ๋ฌธ์ ๋ฅผ ๊ณ์ํด์ ์ค๋ช ํ์ต๋๋ค.
๊ฐ๋จํ ๋งํด์ ๋น๋๋ ์ฌ์ฌ์ฉ์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง๋ง ์ฝ๊ณ ์์ฑํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค. "๋ฌธ์ "๋ ๋จ์ํ ์ฐ๋ฆฌ๊ฐ ํจ์ฌ ๋ ์ฝ๊ธฐ ์ฌ์ด ๋น๋์ ์ ์ฌํ ๊ธฐ๋ฅ์ ์ํ๋ค๋ ๊ฒ์ ๋๋ค.
3๊ฐ์ ์ค์ฒฉ๋ ๋น๋๊ฐ ์ฝ๊ธฐ ์ด๋ ต๊ฑฐ๋ ์ผ๋ฐ์ ์ผ๋ก ๋น๋๊ฐ ์ค์ ๋ก ์ฝ๋ ์ฌ์ฌ์ฉ ๋ชฉ์ ์ ์ํํ์ง ์๋๋ค๋ ๋ฐ ๊ทผ๋ณธ์ ์ผ๋ก ๋์ํ์ง ์๋๋ค๋ฉด ์ฑ์ด ์ด๋ฅผ ๋ ๋ช ํํ๊ฒ ๋ณด์ฌ์ค ์ ์์ต๋๋ค. ์ฐ๋ฆฌ ์ค ๋ง์ ์ฌ๋๋ค์ด ์ค์ ๋ก ์ค์ฒฉ์ ์ค์ด๋ ๊ฒ์ ์ข์ํ๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด์ ์ฝ๋๋ฅผ ๋ณต์ ํ๋ ๊ฒ์ ์ข์ํ์ง ์๋๋ค๋ ์ฌ์ค์ ๋ฃ๋ ๊ฒ์ด ๋ ์ค์ํฉ๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ 2๊ฐ์ง ๋น์ด์์ ์ธ ์ต์ ์ฌ์ด์ ๊ฐํ ์์ต๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ๊ณ ๋ คํ๊ณ ๊ฐ๋ฅํ ์๋ฃจ์ ์ ์ค๋ช ํ๊ณ ์ฐ๋ฆฌ๊ฐ ํด๊ฒฐํ๋ ค๊ณ ํ๋ ๊ฒ์ ์ ํํ๊ฒ ๋์ถํ๋ ค๊ณ ๋ ธ๋ ฅํ๋ฉด์ ์ด๋ฒ ์ฃผ๋ง์ ๋ง ๊ทธ๋๋ก ๋ช ์๊ฐ์ ๋ณด๋์ต๋๋ค.
๋๋ ๊ทธ๊ฒ์ ๋ํด ๊ฐ์ฌํฉ๋๋ค
์ดํด์ ๋ถ์กฑ๊ณผ ๊ณ ๋ ค๋ฅผ ๊ฑฐ๋ถํ๋ ๋ฌธ์ ๋ฅผ ํผ๋ํ์ง ๋ง์ญ์์ค.
์ดํด๊ฐ ๋ถ์กฑํด๋ ๊ด์ฐฎ์ง๋ง ํ์ฌ ์ํฉ์ ํฌ๋ง์ด ์์ด ๋ณด์
๋๋ค.
์ฐ๋ฆฌ๋ ํ ๋ก ์ ๋งจ ์ฒ์์ ๋ง๋ค์ด์ง ์์ ์ ๋ํด ์ฌ์ ํ ํ ๋ก ํ๊ณ ์์ต๋๋ค.
๋ด ๊ด์ ์์, ๋๋ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ์ง๋ฌธ์ ๋ตํ๋ ์์ธํ ์ค๋ช ์ ์์ฑํ๋ ๋ฐ ๋ช ์๊ฐ์ ๋ณด๋ธ ๊ฒ์ฒ๋ผ ๋๊ปด์ง์ง๋ง ๋ด ์๊ฒฌ์ ๋ฌด์๋๊ณ ๊ฐ์ ์ง๋ฌธ์ด ๋ค์ ์ง๋ฌธ๋์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ํ์ฌ ๊ตฌ๋ฌธ์ ๊ฐ๋
์ฑ ๋ถ์กฑ์ด ๋
ผ์์ ์ค์ฌ์ ์์ต๋๋ค.
์ด๋ฅผ ๋ท๋ฐ์นจํ๊ธฐ ์ํด ๊ฐ๋
์ฑ ๋ฌธ์ ์ ๋ํด ๋ช ๊ฐ์ง ๋ถ์์ ํ์ต๋๋ค.
์ด๋ฌํ ๋ถ์์๋ ์๋นํ ์์ ๐๊ฐ ์๊ณ ๋ค๋ฅธ ์ฌ๋๋ค๋ ๋์ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
๊ทธ๋ฌ๋ ์ต๊ทผ ๋ต๋ณ์ ๋ฐ๋ฅด๋ฉด ๊ฐ๋ ์ฑ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. https://github.com/flutter/flutter/issues/51752#issuecomment -671009593
๋ํ ๋ค์์ ์ ์ํ์ต๋๋ค.
Widget build(context) {
var result = Text('result:');
var builder1 = (BuildContext context, AsyncSnapshot<int> snapshot) {
return Row(children: [result, Text(snapshot.data)]);
};
result = StreamBuilder(stream: _stream1, builder: builder1);
var builder2 = (BuildContext context, AsyncSnapshot<int> snapshot) {
return Column(children: [result, Text(snapshot.data)]);
};
result = StreamBuilder(stream: _stream2, builder: builder2);
}
์ฝ์ ์ ์๋ค๋ ๊ฒ์ ์๊ณ
์ด ๋ ๊ฐ์ง ์๊ฒฌ์์ ์ฐ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๋ก ์ ๋ด๋ฆด ์ ์์ต๋๋ค.
ํํฌ์ ์ ์ผํ ๋ชฉ์ ์ด ์ฌ์ฌ์ฉ ๊ฐ๋ฅ์ฑ์ด ์ต๊ณ ์กฐ์ ๋ฌํ์ง๋ง ๊ฐ๋
์ฑ/์ฐ๊ธฐ์ฑ์ด ์ข์ง ์์ ๋น๋์ ๊ตฌ๋ฌธ์ ๊ฐ์ ํ๋ ๊ฒ์์ ๊ณ ๋ คํ๋ฉด ๋ฃ๊ธฐ์ ๋๋ด์
๋๋ค.
์ฐ๋ฆฌ๊ฐ ๊ทธ๋ฌํ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ค์ ๋์ํ์ง ์๋๋ค๋ฉด ์ฐ๋ฆฌ๊ฐ ๋ฌด์์ ํ ์ ์์์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
@Hixie ๊ฐ์ฌํฉ๋๋ค. ์ด๊ฒ์ ๊ทํ์ ๊ด์ ์ ์ดํดํ๋ ๋ฐ ๋ง์ ๋์์ด ๋ฉ๋๋ค. ๋๋ ๊ทธ๋ค์ด ์ฝ๋ ๋ง์ ๋ก ๋๋ฌด ์ง๋์ณค์ ์ ์๋ค๋ ๋ฐ ๋์ํ์ง๋ง ์ ์ด๋ ๊ทธ๋ค์ด ์ณ์๋ ๊ฒ์ ๋ช ๊ฐ์ง ์๋ค๊ณ ํ์ ํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ ๋ Flutter์ ๊ณ์ธตํ๋ ์ํคํ ์ฒ๋ฅผ ๋งค์ฐ ์ข์ํฉ๋๋ค. ์์ ฏ์ ๊ณ์ ์ฌ์ฉํ๊ณ ์ถ์ต๋๋ค. ๋ฐ๋ผ์ ์๋ง๋ ๋๋ต์ Dart & Flutter์ ํ์ฅ์ฑ์ ๊ฐ์ ํ๋ ๊ฒ์ ๋๋ค. ์ ์๊ฒ ๋ค์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ฝ๋ ์์ฑ์ ๋ณด๋ค ์ํํ๊ฒ ํ์ธ์. Dart์์ SwiftUI ๋ง๋ฒ์ ๊ตฌํํ๋ ๊ฒ์ด ๊ฐ๋ฅํ ์๋ ์์ง๋ง ํ์ํ ์ผ๋ฐ์ ์ธ ์ค์ ์ ๋๋ฌด ํฌ๊ณ ๋๋ฌด ๋๋ฆฝ๋๋ค.
์ฝ๋ ์์ฑ์ ์ฌ์ฉํ๋ ๊ฒ์ด ํจํค์ง๋ฅผ ๊ฐ์ ธ์ค๊ณ ์ผ๋ถ ์ฃผ์์ ๋๋๋ฆฌ๋ ๊ฒ์ฒ๋ผ ๊ฐ๋จํ๋ค๋ฉด ๋ ผ์๋ ๋ฌธ์ ๊ฐ ์๋ ์ฌ๋๋ค์ ๊ทธ๋ ๊ฒ ํ๊ณ ๋ถํ์ ๋ฉ์ถ ๊ฒ์ ๋๋ค. ๋๋จธ์ง๋ ๊ณ์ํด์ ์ข์ ์ค๋๋ StatefulWidget์ ์ง์ ์ฌ์ฉํฉ๋๋ค.
ํธ์ง: flutter generate
๋ ์ข์ ๋ฐฉํฅ์ผ๋ก ๋์๊ฐ๋ ๋จ๊ณ๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ ๊ฑฐ๋ ๊ฒ์ ๋ถ๋๋ฌ์ด ์ผ์
๋๋ค.
๋ค์ Flutter ๊ฐ๋ฐ์ ์ค๋ฌธ์กฐ์ฌ์์ ์ด๊ฒ์ด ๋งค์ฐ ํฅ๋ฏธ๋ก์ด ์ง๋ฌธ์ด ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
์ข์ ์์์ด ๋ ๊ฒ์ ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ๋ค๋ฅธ ๋ถ๋ถ/์ง๋ฌธ์ผ๋ก ๋๋๊ณ ์ด๊ฒ์ด Flutter ๊ฐ๋ฐ์๊ฐ ํด๊ฒฐํ๊ณ ์ ํ๋ ์ค์ ๋ฌธ์ ์ธ์ง ํ์ธํ์ญ์์ค.
๋ช ํํด์ง๋ฉด ์ด ๋ํ๊ฐ ๋ ์ ์ฐฝํ๊ณ ํ๋ถํด์ง ๊ฒ์ ๋๋ค.
๋ด ๊ด์ ์์, ๋๋ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ์ง๋ฌธ์ ๋ตํ๋ ์์ธํ ์ค๋ช ์ ์์ฑํ๋ ๋ฐ ๋ช ์๊ฐ์ ๋ณด๋ธ ๊ฒ์ฒ๋ผ ๋๊ปด์ง์ง๋ง ๋ด ์๊ฒฌ์ ๋ฌด์๋๊ณ ๊ฐ์ ์ง๋ฌธ์ด ๋ค์ ์ง๋ฌธ๋์์ต๋๋ค.
๊ฐ์ ์ง๋ฌธ์ ํ๋ ๊ฒ์ ๋ต์ ์ดํดํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
์๋ฅผ ๋ค์ด ์ด์ ๋๊ธ(https://github.com/flutter/flutter/issues/51752#issuecomment-670959424)๋ก ๋์๊ฐ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ ผ์๋ ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
Widget build(context) { return ValueListenableBuilder<String>( valueListenable: someValueListenable, builder: (context, value, _) { return StreamBuilder<int>( stream: someStream, builder: (context, value2) { return TweenAnimationBuilder<double>( tween: Tween(...), builder: (context, value3) { return Text('$value $value2 $value3'); }, ); }, ); }, ); }
์ด ์ฝ๋๋ ์ฝ์ ์ ์์ต๋๋ค.
๋๋ ๊ทธ๊ฒ์ ๋ํด ์ฝ์ ์์๋ ๊ฒ์ ์ ๋ง๋ก ๋ณด์ง ๋ชปํฉ๋๋ค. ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ ํํ๊ฒ ์ค๋ช ํฉ๋๋ค. ๋ค ๊ฐ์ ์์ ฏ์ด ์์ต๋๋ค. ์ธ ๊ฐ์ ์์ ฏ์๋ ๋น๋ ๋ฉ์๋๊ฐ ์๊ณ , ํ๋๋ ๋ฌธ์์ด๋ง ์์ต๋๋ค. ์ ๋ ๊ฐ์ธ์ ์ผ๋ก ์ ํ์ ์๋ตํ์ง ์์ ๊ฒ์ ๋๋ค. ๋ณ์๊ฐ ๋ชจ๋ ๋ฌด์์ธ์ง ์ ์ ์๊ธฐ ๋๋ฌธ์ ์ฝ๊ธฐ๊ฐ ๋ ์ด๋ ค์ธ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง ํฐ ๋ฌธ์ ๋ ์๋๋๋ค.
์ฝ์ ์ ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
๋ถ๋ช ํ ๋ง์๋๋ฆฌ์๋ฉด, ๋น์ ์ ๊ทธ๊ฒ์ ์ฝ์ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋๋ ๋น์ ์ด ํ๋ ธ๋ค๊ณ ๋งํ๋ ค๋ ๊ฒ์ด ์๋๋๋ค. ์ ๊ทธ๋ฐ์ง ์ดํด๊ฐ ์๋ฉ๋๋ค.
๊ตฌ๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํ๋ ์ ํค์๋๋ฅผ ๋์ ํ์ฌ ๊ฐ๋ ์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค.
Widget build(context) { final value = keyword ValueListenableBuilder(valueListenable: someValueListenable); final value2 = keyword StreamBuilder(stream: someStream); final value3 = keyword TweenAnimationBuilder(tween: Tween(...)); return Text('$value $value2 $value3'); }
์ด ์ฝ๋๋ ํจ์ฌ ๋ ์ฝ๊ธฐ ์ฝ๊ณ ํํฌ์ ๊ด๋ จ์ด ์์ผ๋ฉฐ ์ ํ ์ฌํญ์ด ์์ต๋๋ค.
ํ์คํ ๋ ์ฅํฉํฉ๋๋ค. ์ ์ด๋ ๋์๊ฒ๋ ๋ ์ด์ ์ฝ์ ์ ์๋์ง ํ์คํ์ง ์์ต๋๋ค. ๋ ๋ง์ ๊ฐ๋ ์ด ์์ต๋๋ค(์ด์ ์์ ฏ๊ณผ ์ด "ํค์๋" ๊ธฐ๋ฅ์ด ๋ชจ๋ ์์ต๋๋ค). ๋ ๋ง์ ๊ฐ๋ ์ ๋ ๋ง์ ์ธ์ง ๋ถํ๋ฅผ ์๋ฏธํฉ๋๋ค. (๋ํ ์ด๋ฌํ ๊ฐ์ฒด๊ฐ ์ผ๋ง๋ ๋ ๋ฆฝ์ ์ธ์ง์ ๋ฐ๋ผ ์ ์ฌ์ ์ผ๋ก ๋ ํจ์จ์ ์ ๋๋ค. ์๋ฅผ ๋ค์ด ์ ๋๋ฉ์ด์ ์ด ํญ์ ์ฒญ์ทจ ๊ฐ๋ฅ ๋ฐ ์คํธ๋ฆผ ๊ฐ๋ณด๋ค ๋ ์์ฃผ ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ผ๋ก ํธ๋ฆฌ๊ฑฐ๋์ง ์๋๋ผ๋ ์ด์ ValueListenableBuilder ๋ฐ StreamBuilder๋ฅผ ๋ค์ ๋น๋ํฉ๋๋ค. ; ๋ํ ์ด๊ธฐํ ๋ ผ๋ฆฌ๋ ์ด์ ๋ชจ๋ ๋น๋๋ฅผ ์ ๋ ฅํ๊ณ ๊ฑด๋๋ฐ์ด์ผ ํฉ๋๋ค.)
๋น์ ์ ์ฅํฉํ ๊ฒ์ด ๋ฌธ์ ๊ฐ ์๋๋ผ๊ณ ๋งํ์ผ๋ฏ๋ก ๋ ๊ฐ๊ฒฐํ๋ค๊ณ ํด์ ๋ ์ฝ๊ธฐ ์ฌ์ด ๊ฒ์ ์๋๋๋ค. ์ ์๊ฐ์๋ (๋น์ ์ด ๋ฌธ์ ์ ๋ชฉ์ "๋๋ฌด ์ฅํฉํ๋ค"๋ฅผ ์ ๋ ฅํ๊ธฐ ๋๋ฌธ์ ์ ๋ ์ด๊ฒ์ ๋ํด ํผ๋์ค๋ฝ๊ธด ํ์ง๋ง ๋ฌธ์ ์ ์๋ ์ค๋ช ). ๋ค์ฌ์ฐ๊ธฐ๋ฅผ ๋ ํ๊ณ ์ถ๋ค๊ณ ๋ง์ํ์ จ์ง๋ง, ๋ค์ฌ์ฐ๊ธฐ ์์ด ๋น๋๋ฅผ ์ฌ์ฉํ๋ ๋ฒ์ ๋ ์ฝ์ ์ ์๋ค๊ณ ์ค๋ช ํ์ จ์ผ๋, ์๋ง๋ ์๋ณธ์ ๋ค์ฌ์ฐ๊ธฐ๊ฐ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ ๋๋ค.
๋น๋๊ฐ ์ฌ์ฌ์ฉ์ฑ์ ์ ์ ์ด๊ณ ๋์ฒด ๊ตฌ๋ฌธ์ ์ํ์ง๋ง ์ ์ํ ์ ์์ ๋น๋์ ๊ฐ์ง ์์ผ๋ฏ๋ก(์์ ฏ์ด๋ ์์๋ฅผ ์์ฑํ์ง ์์) ๋น๋ ์ธก๋ฉด์ด ํน๋ณํ ์ค์ํ์ง ์์ต๋๋ค. ๋ฅผ ์ฐพ๊ณ ์์ต๋๋ค.
๋ด๊ฐ ๋งํ ์ ์๋ ํ ํ๋ฅญํ๊ฒ ์๋ํ๋ (Hooks) ์๋ฃจ์ ์ด ์์ง๋ง ์ฌ๋๋ค์ด Hooks๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ ์์ํฌ์์ ๋ฌด์ธ๊ฐ๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ถ์ต๋๊น? ์ฌ๋๋ค์ด Hooks๋ฅผ ํจํค์ง๋ก ์ฌ์ฉํ ๋งํผ ์ถฉ๋ถํ ์ข์ํ์ง ์๋๋ค๋ฉด ํ๋ ์์ํฌ์๋ ์ข์ ์๋ฃจ์ ์ด ์๋ ์๋ ์์ต๋๋ค. Flutter ํ์ ๊ฐ์น ์๋ ๊ฒ์ ๋ง๋ญ๋๋ค.
๋ ์ฌ์ด ์ฝ๋ ์ฌ์ฌ์ฉ์ ๋ํ ์๊ตฌ๊ฐ ์๋ค๋ ๊ฒ์ ์ดํดํฉ๋๋ค. ๊ทธ๊ฒ ๋ฌด์จ ๋ป์ธ์ง ๋ชจ๋ฅด๊ฒ ์ด์.
๋ค์์ ์์ ๋ ๋ฒ์ ๊ณผ ๊ฐ๋ ์ฑ ๋ฉด์์ ์ด๋ป๊ฒ ๋น๊ต๋ฉ๋๊น?
Widget build(context) {
return
ValueListenableBuilder(valueListenable: someValueListenable, builder: (context, value, _) =>
StreamBuilder(stream: someStream, builder: (context, value2) =>
TweenAnimationBuilder(tween: Tween(...), builder: (context, value3) =>
Text('$value $value2 $value3'),
)));
}
@szotp ํ์ฌ codegen ์๋ฃจ์ ๊ณผ ๊ด๋ จํ์ฌ ๋๋ฌด ๋ง์ ๋ง์ฐฐ์ด ์๋ ๊ฒฝ์ฐ ์ฃผ์ ํ์ง ๋ง๊ณ ๋ฒ๊ทธ๋ฅผ
@jamesblasco ์ฌ๊ธฐ์ ์ฌ๋๋ค์ด ํด๊ฒฐํ๊ธฐ๋ฅผ ์ํ๋ ์ค์ ๋ฌธ์ ๊ฐ ์๋ค๋ ๋ฐ๋ ์์ฌ์ ์ฌ์ง๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ ์๊ฒ ์ง๋ฌธ์ ๋ฐ๋ก ๊ทธ ๋ฌธ์ ๊ฐ ๋ฌด์์ธ์ง ์ ๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ์๋ฃจ์ ์ ์ค๊ณํ ์ ์์ต๋๋ค.
ํํฌ ๊ฒฐํจ์ ๋ํ ์ฐ๋ ค๋ ์ฝ๋์ ํฌํจ๋๊ธฐ๋ฅผ ์ํ๋ ๊ฒ์ ๋ํ ์ฐ๋ ค์ ๋ตํ ์๋ ์์ง๋ง ์ง๊ธ์ ๊ทธ๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ์ง์คํด์ผ ํ๋ ๋ถ๋ถ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ๋จผ์ ๋ฌธ์ ๊ฐ ๋ฌด์์ธ์ง์ ๋์ํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์๋ค๋ฉด ๋ค๋ฅธ ์ฃผ์ ์ ๋ํด ์ด๋ป๊ฒ ๋์ํ ์ ์์์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๋๋ ๊ทธ๊ฒ์ ๋ํด ์ฝ์ ์์๋ ๊ฒ์ ์ ๋ง๋ก ๋ณด์ง ๋ชปํฉ๋๋ค. ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ ํํ๊ฒ ์ค๋ช ํฉ๋๋ค. ๋ค ๊ฐ์ ์์ ฏ์ด ์์ต๋๋ค. ์ธ ๊ฐ์ ์์ ฏ์๋ ๋น๋ ๋ฉ์๋๊ฐ ์๊ณ , ํ๋๋ ๋ฌธ์์ด๋ง ์์ต๋๋ค. ์ ๋ ๊ฐ์ธ์ ์ผ๋ก ์ ํ์ ์๋ตํ์ง ์์ ๊ฒ์ ๋๋ค. ๋ณ์๊ฐ ๋ชจ๋ ๋ฌด์์ธ์ง ์ ์ ์๊ธฐ ๋๋ฌธ์ ์ฝ๊ธฐ๊ฐ ๋ ์ด๋ ค์ธ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง ํฐ ๋ฌธ์ ๋ ์๋๋๋ค.
์ฌ๊ธฐ์ ๋ฌธ์ ์ ํฐ ๋ถ๋ถ์ ์ฝ๋ฉ ๋ฐฉ์์ด ๋๋ถ๋ถ์ ์ฌ๋๋ค์ด ์ฝ๋ฉํ๋ ๋ฐฉ์๊ณผ ํฌ๊ฒ ๋ค๋ฅด๋ค๋ ๊ฒ์ ๋๋ค.
์๋ฅผ ๋ค์ด Flutter์ ๊ทํ๊ฐ ์ ๊ณตํ ์ฑ ์์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ด ๋ ๊ฐ์ง ํฌ์ธํธ๋ง์ผ๋ก ์ปค๋ฎค๋ํฐ์ 1% ์ด์์ ๋ํํ๋ค๋ฉด ๋๋ ๊ฒ์ ๋๋ค.
๋ฐ๋ผ์ ๋น์ ์ด ์ฝ์ ์ ์๋ค๊ณ ํ๊ฐํ๋ ๊ฒ์ ๋๋ถ๋ถ์ ์ฌ๋๋ค์ด ์ฝ์ ์ ์๋ค๊ณ ์๊ฐํ๋ ๊ฒ๊ณผ๋ ๋งค์ฐ ๋ค๋ฅผ ์ ์์ต๋๋ค.
๋๋ ๊ทธ๊ฒ์ ๋ํด ์ฝ์ ์์๋ ๊ฒ์ ์ ๋ง๋ก ๋ณด์ง ๋ชปํฉ๋๋ค. ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ ํํ๊ฒ ์ค๋ช ํฉ๋๋ค. ๋ค ๊ฐ์ ์์ ฏ์ด ์์ต๋๋ค. ์ธ ๊ฐ์ ์์ ฏ์๋ ๋น๋ ๋ฉ์๋๊ฐ ์๊ณ , ํ๋๋ ๋ฌธ์์ด๋ง ์์ต๋๋ค. ์ ๋ ๊ฐ์ธ์ ์ผ๋ก ์ ํ์ ์๋ตํ์ง ์์ ๊ฒ์ ๋๋ค. ๋ณ์๊ฐ ๋ชจ๋ ๋ฌด์์ธ์ง ์ ์ ์๊ธฐ ๋๋ฌธ์ ์ฝ๊ธฐ๊ฐ ๋ ์ด๋ ค์ธ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง ํฐ ๋ฌธ์ ๋ ์๋๋๋ค.
์ฝ์ ์ ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
๋ด ์ถ์ฒ์ ํน์ ํญ๋ชฉ์ ๊ฒ์ํ ๋ ๋์ด ๋ณด๊ณ ์๋ ์์น์ ๊ฑฐ๊ธฐ์ ๋๋ฌํ๋ ๋ฐ ์ผ๋ง๋ ๋ง์ ๋จ๊ณ๊ฐ ํ์ํ์ง ๋ถ์ํ๋ ๊ฒ์ ๋๋ค.
์คํ์ ํด๋ณด์:
๋ ๊ฐ์ ์์ ฏ ํธ๋ฆฌ๋ฅผ ์ ๊ณตํ๊ฒ ์ต๋๋ค. ํ๋๋ ์ ํ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๊ณ ๋ค๋ฅธ ํ๋๋ ์ค์ฒฉ ๊ตฌ๋ฌธ์ ์ฌ์ฉํฉ๋๋ค.
๋ํ ํด๋น ์ค ๋ํซ์์ ์ฐพ์์ผ ํ ํน์ ์ฌํญ์ ์๋ ค ๋๋ฆฌ๊ฒ ์ต๋๋ค.
์ ํ ๊ตฌ๋ฌธ ๋๋ ์ค์ฒฉ ๊ตฌ๋ฌธ ์ฌ์ฉ์ ๋ํ ๋ต์ ์ฐพ๋ ๊ฒ์ด ๋ ์ฝ์ต๋๊น?
์ง๋ฌธ:
bar
๋ณ์๋ ๋๊ฐ ์์ฑํฉ๋๊น?๋น๋ ์ฌ์ฉ:
์์ ฏ ๋น๋(์ปจํ ์คํธ) { ValueListenableBuilder ๋ฐํ( valueListenable: someValueListenable, ๋น๋: (context, foo, _) { ์คํธ๋ฆผ ๋น๋๋ฅผ ๋ฐํ ( ์คํธ๋ฆผ: someStream, ๋น๋: (์ปจํ ์คํธ, baz) { TweenAnimationBuilder ๋ฐํ ( ํธ์: ํธ์(...), ๋น๋: (์ปจํ ์คํธ, ๋ฐ) { ๋ฐํ Container(); }, ); }, ); }, ); }
์ ํ ๊ตฌ๋ฌธ ์ฌ์ฉ:
์์ ฏ ๋น๋(์ปจํ
์คํธ) {
์ต์ข
foo = ํค์๋ ValueListenableBuilder(valueListenable: someValueListenable);
์ต์ข
๋ง๋ = ํค์๋ StreamBuilder(์คํธ๋ฆผ: someStream);
์ต์ข
baz = ํค์๋ TweenAnimationBuilder(tween: Tween(...));
๋ฐํ ์ด๋ฏธ์ง();
}
์ ๊ฒฝ์ฐ์๋ ๋ต์ ์ฐพ๊ธฐ ์ํด ์ค์ฒฉ๋ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ ๊ฒ์ด ์ด๋ ต์ต๋๋ค.
๋ฐ๋ฉด์ ์ ํ ํธ๋ฆฌ๋ก ๋ต์ ์ฐพ๋ ๊ฒ์ ์ฆ๊ฐ์ ์
๋๋ค.
๋ค์ฌ์ฐ๊ธฐ๋ฅผ ๋ ํ๊ณ ์ถ๋ค๊ณ ๋ง์ํ์ จ์ง๋ง, ๋ค์ฌ์ฐ๊ธฐ ์์ด ๋น๋๋ฅผ ์ฌ์ฉํ๋ ๋ฒ์ ๋ ์ฝ์ ์ ์๋ค๊ณ ์ค๋ช ํ์ จ์ผ๋, ์๋ง ์๋ณธ์ ๋ค์ฌ์ฐ๊ธฐ๊ฐ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ ๋๋ค.
StreamBuilder๊ฐ ์ฌ๋ฌ ๋ณ์๋ก ๋ถํ ๋ ๊ฒ์ด ์ฌ๊ฐํ ์ ์์ด์์ต๋๊น?
๋ด๊ฐ ์ดํดํ ๋ฐ์ ๋ฐ๋ฅด๋ฉด ์ด๊ฒ์ ๋
ผ์์ ๋ฒ์ด๋ ค๋ ๋น๊ผฌ๋ ์ ์์ด์๋ค. ์๋์๋์? ์ด ํจํด์ด ํฐ ์์ ฏ์์๋ ๋ ์ฝ๊ธฐ ์ฌ์ด ์ฝ๋๋ก ์ด์ด์ง ๊ฒ์ด๋ผ๊ณ ์ ๋ง๋ก ์๊ฐํ์ญ๋๊น?
์์ ๊ฐ ์๋ํ์ง ์๋๋ค๋ ์ฌ์ค์ ๋ฌด์ํ๊ณ ์ ์ฝ์ ์ ์๋์ง ์ค๋ช ํ๊ธฐ ์ํด ์์ ๋ฅผ ๋ถํดํ๋ ๋ฐ ์ ๊ฒฝ์ฐ์ง ์์ต๋๋ค. ๊ทธ๊ฒ ๊ฐ์น๊ฐ ์์๊น์?
```๋คํธ
์์ ฏ ๋น๋(์ปจํ ์คํธ) {
๋ฐํ
ValueListenableBuilder(valueListenable: someValueListenable, builder: (context, value, _) =>
StreamBuilder(์คํธ๋ฆผ: someStream, ๋น๋: (context, value2) =>
TweenAnimationBuilder(tween: Tween(...), builder: (context, value3) =>
ํ ์คํธ('$๊ฐ $๊ฐ2 $๊ฐ3'),
)));
}
๊ทธ๊ฒ ๋ ์ข์ ๋ณด์ธ๋ค.
๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ์ฌ๋๋ค์ด dartfmt๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค๊ณ ๊ฐ์ ํฉ๋๋ค
dartfmt๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
Widget build(context) {
return ValueListenableBuilder(
valueListenable: someValueListenable,
builder: (context, value, _) => StreamBuilder(
stream: someStream,
builder: (context, value2) => TweenAnimationBuilder(
tween: Tween(),
builder: (context, value3) => Text('$value $value2 $value3'),
)));
}
์๋ ์ฝ๋์ ๊ฑฐ์ ๋ค๋ฅด์ง ์์ต๋๋ค.
๋น๋๊ฐ ์ฌ์ฌ์ฉ์ฑ์ ์ ์ ์ด๊ณ ๋์ฒด ๊ตฌ๋ฌธ์ ์ํ์ง๋ง ์ ์ํ ์ ์์ ๋น๋์ ๊ฐ์ง ์์ผ๋ฏ๋ก(์์ ฏ์ด๋ ์์๋ฅผ ์์ฑํ์ง ์์) ๋น๋ ์ธก๋ฉด์ด ํน๋ณํ ์ค์ํ์ง ์์ต๋๋ค. ๋ฅผ ์ฐพ๊ณ ์์ต๋๋ค.
๊ตฌํ ์ธ๋ถ ์ฌํญ์
๋๋ค.
์์๊ฐ ์๋์ง ์๋์ง์ ๋ํ ํน๋ณํ ์ด์ ๋ ์์ต๋๋ค.
์ฌ์ค, LayoutBuilder
๋ฐ ์ ์ฌ์ ์ผ๋ก GestureDetector
ํฌํจํ ์ ์๋๋ก ์์๋ฅผ ๊ฐ๋ ๊ฒ์ด ํฅ๋ฏธ๋ก์ธ ์ ์์ต๋๋ค.
์ฐ์ ์์๊ฐ ๋ฎ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ React ์ปค๋ฎค๋ํฐ์์ ๋ค์ํ ํํฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์์ ๋ค์์ ๋ณด์์ต๋๋ค.
(๋ํ ์ด๋ฌํ ๊ฐ์ฒด๊ฐ ์ผ๋ง๋ ๋ ๋ฆฝ์ ์ธ์ง์ ๋ฐ๋ผ ์ ์ฌ์ ์ผ๋ก ๋ ํจ์จ์ ์ ๋๋ค. ์๋ฅผ ๋ค์ด ์ ๋๋ฉ์ด์ ์ด ํญ์ ์ฒญ์ทจ ๊ฐ๋ฅ ๋ฐ ์คํธ๋ฆผ ๊ฐ๋ณด๋ค ๋ ์์ฃผ ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ผ๋ก ํธ๋ฆฌ๊ฑฐ๋์ง ์๋๋ผ๋ ์ด์ ValueListenableBuilder ๋ฐ StreamBuilder๋ฅผ ๋ค์ ๋น๋ํฉ๋๋ค. ; ๋ํ ์ด๊ธฐํ ๋ ผ๋ฆฌ๋ ์ด์ ๋ชจ๋ ๋น๋๋ฅผ ์ ๋ ฅํ๊ณ ๊ฑด๋๋ฐ์ด์ผ ํฉ๋๋ค.)
๊ทธ๊ฒ์ ์๋ฃจ์ ์ด ์ด๋ป๊ฒ ํด๊ฒฐ๋๋์ง์ ๋ฌ๋ ค ์์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ธ์ด ์์ ์ ์ํด ๊ฐ๋ค๋ฉด ์ด ๋ฌธ์ ๋ ์ ํ ๋ฌธ์ ๊ฐ ๋์ง ์์ ๊ฒ์ ๋๋ค.
์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ๋ง๋ค ์ ์์ต๋๋ค:
Widget build(context) {
final value = keyword ValueListenableBuilder(valueListenable: someValueListenable);
final value2 = keyword StreamBuilder(stream: someStream);
final value3 = keyword TweenAnimationBuilder(tween: Tween(...));
return Text('$value $value2 $value3');
}
"์ปดํ์ผ":
Widget build(context) {
return ValueListenableBuilder<String>(
valueListenable: someValueListenable,
builder: (context, value, _) {
return StreamBuilder<int>(
stream: someStream,
builder: (context, value2) {
return TweenAnimationBuilder<double>(
tween: Tween(...),
builder: (context, value3) {
return Text('$value $value2 $value3');
},
);
},
);
},
);
}
ํํฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ flutter_hooks์๋ HookBuilder
์์ ฏ์ด ์ ๊ณต๋๋ฏ๋ก ํ์ํ ๋ ์ฌ์ ํ ๋ถํ ํ ์ ์์ต๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก, ํนํ ์ฌ๊ธฐ์์ ๋ง๋ ์์์ ์ค์ ๋ก ๋ฌธ์ ์ธ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ ค๋ฉด ์ ์ ํ ๋ฒค์น๋งํฌ๊ฐ ํ์ํฉ๋๋ค.
ํํฌ๋ฅผ ์ฌ์ฉํ์ฌ ํ๋์ ์์๋ง ๋ค์ ๋น๋ํฉ๋๋ค.
๋น๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ๊ตฌ์ถ์ด ์ฌ๋ฌ ์์๋ก ๋ถํ ๋ฉ๋๋ค. ๊ทธ๊ฒ์ ์๋๋ผ๋ ์ฝ๊ฐ์ ์ค๋ฒ ํค๋๋ฅผ ์ถ๊ฐํฉ๋๋ค.
๋ชจ๋ ํํฌ๋ฅผ ์ฌํ๊ฐํ๋ ๊ฒ์ด ๋ ๋น ๋ฅผ ์๋ ์์ต๋๋ค. ์ด๊ฒ์ด React ํ์ด hook์ ๋์์ธํ ๋ ์๊ฐํด ๋ธ ๊ฒฐ๋ก ์ธ ๊ฒ ๊ฐ์ต๋๋ค.
๊ทธ๋ฌ๋ ์ด๊ฒ์ Flutter์๋ ์ ์ฉ๋์ง ์์ ์ ์์ต๋๋ค.
์ฝ์ ์ ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
์ค์ฒฉ์ผ๋ก ์ธํด ์ค์ฒฉ์ ์ฌ์ฉํ๋ฉด ๋น ๋ฅด๊ฒ ์ค์บํ๊ณ ๋ฌด์ํ ์ ์๋ ๋ถ๋ถ๊ณผ ์งํ ์ค์ธ ์์ ์ ์ดํดํ๋ ๋ฐ ํ์์ ์ธ ๋ถ๋ถ์ ํ์ ํ๊ธฐ๊ฐ ๋ ์ด๋ ค์์ง๋๋ค. ์ฝ๋๋ ๋ณธ์ง์ ์ผ๋ก "์์ฐจ์ "์ด์ง๋ง ์ค์ฒฉ์ ์ด๋ฅผ ์จ๊น๋๋ค. ๋ํ ์ค์ฒฉ์ ์์ ์ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค. ๋ ํญ๋ชฉ์ ์ฌ์ ๋ ฌํ๊ฑฐ๋ ๋ ํญ๋ชฉ ์ฌ์ด์ ์ ํญ๋ชฉ์ ์ฝ์ ํ๊ณ ์ถ๋ค๊ณ ์์ํด๋ณด์ธ์. ์์ฐจ ์ฝ๋์์๋ ์ฌ์ํ์ง๋ง ์ค์ฒฉ ์์ ์ด ํ์ํ ๋๋ ์ด๋ ต์ต๋๋ค.
์ด๊ฒ์ async/await ์คํ๊ณผ ์์ Future API๋ก ์์ ํ๋ ๊ฒ๊ณผ ๋งค์ฐ ์ ์ฌํ๋ฉฐ, ์๋์ ์๋ dame ์ฐ์ ๊ธฐ๋ฐ ๊ฐ๋ (๊ทธ๋ฆฌ๊ณ ์ฐฌ์ฑ ๋ฐ ๋ฐ๋ ์ธ์๋ ๋งค์ฐ ์ ์ฌํจ) - ์ Future API๋ ์ง์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ์๋ฌด ๊ฒ๋ ์จ๊ธฐ์ง ์์ง๋ง ๊ฐ๋ ์ฑ ๋ฐ ์ ์ง ๊ด๋ฆฌ ์ฉ์ด์ฑ ํ์คํ ์ข์ง ์์ต๋๋ค. async/wait๊ฐ ์น์์ ๋๋ค.
๋ด ์ถ์ฒ์ ํน์ ํญ๋ชฉ์ ๊ฒ์ํ ๋ ๋์ด ๋ณด๊ณ ์๋ ์์น์ ๊ฑฐ๊ธฐ์ ๋๋ฌํ๋ ๋ฐ ์ผ๋ง๋ ๋ง์ ๋จ๊ณ๊ฐ ํ์ํ์ง ๋ถ์ํ๋ ๊ฒ์ ๋๋ค.
์ ๋ 25๋ ๋์ 10๊ฐ ์ด์์ ๋ค๋ฅธ ์ธ์ด๋ก ํ๋ก๊ทธ๋๋ฐ์ ํด์์ผ๋ฉฐ, ์ด๋ ์ฝ๋๋ฅผ ๊ฐ๋ ์ฑ ์๊ฒ ๋ง๋๋ ์์๋ฅผ ํ๊ฐํ๋ ๊ฐ์ฅ ๋์ ๋ฐฉ๋ฒ์ ๋๋ค. ์์ค ์ฝ๋์ ๊ฐ๋ ์ฑ์ ๊น๋ค๋กญ์ง๋ง "๋ด ๋์ด ๋ณด๋ ๊ณณ"์ด๋ ์ฌ์ฉํ๋ ์ฝ๋ ์ค ์๋ณด๋ค ํ๋ก๊ทธ๋๋ฐ ๊ฐ๋ ๊ณผ ๋ ผ๋ฆฌ๋ฅผ ์ผ๋ง๋ ์ ํํํ๋๋๊ฐ ๋ ์ค์ํฉ๋๋ค.
๋๋ ์คํ๋ ค ๊ฐ๋ ์ฑ์ ๋๋ฌด ์ง์คํ๊ณ ์ ์ง ๊ด๋ฆฌ์ ๋ ์ง์คํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ฝ๋์ __intent__๊ฐ ๋ ๋ช ํํ๊ณ ๋์ผํ ์์น์ ์จ๊ฒจ์ง ๋ค๋ฅธ ๊ด์ฌ์ฌ๋ก ์ธํด ์ ์ง ๊ด๋ฆฌ๊ฐ ๋ ์ด๋ ค์์ง๊ธฐ ๋๋ฌธ์ ์์ ๋ ๋ ์ฝ๊ธฐ ์ฝ์ต๋๋ค.
final value = keyword ValueListenableBuilder(valueListenable: someValueListenable);
๊ทธ ๊ฐ์น๋ ์ผ๋ง๋ ๋ ๊น์? ์์ ฏ? ๋ฌธ์์ด ๋ณ์? ๋ด๋ถ์์ ์ฌ์ฉํ๋ค๊ณ ํฉ๋๋ค
return Text('$value $value2 $value3');
๊ธฐ๋ณธ์ ์ผ๋ก ์ํ๋ ๊ฒ์ ์์ ฏ B์ ๋น๋ ๋ฉ์๋์์ ๋ณ์ A๋ฅผ ์ฐธ์กฐํ์ฌ A ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค B๊ฐ ๋ค์ ๋น๋๋๋๋ก ํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๊ฒ์ด ๋ง ๊ทธ๋๋ก mobx๊ฐ ํ๋ ์ผ์ด๋ฉฐ, ์ ์ ํ ์์ ๋ง๋ฒ/๋ณด์ผ๋ฌ ํ๋ ์ดํธ๋ก ์ ํํ๊ฒ ์ํํฉ๋๋ค.
final value2 = keyword StreamBuilder(stream: someStream);
์ด๊ฒ์ ๋ฌด์์ ๋ฐํํด์ผํฉ๋๊น? ์์ ฏ? ์คํธ๋ฆผ? ๋ฌธ์์ด ๊ฐ?
๋ค์ ๋งํ์ง๋ง, ๊ทธ๊ฒ์ ๋ฌธ์์ด ๊ฐ์ฒ๋ผ ๋ณด์ ๋๋ค. ๋น์ ์ ๋จ์ํ ์์ ฏ ์คํธ๋ฆผ์ด ๊ฐ์ ๋ฐฉ์ถ ํ ๋๋ง๋ค ๋ค์ ๊ฒ์, ๋น๋ ๋ฐฉ๋ฒ์ ์์ธ์ ์คํธ๋ฆผ์ ์ฐธ์กฐํ๊ณ ๋ฐฉ์ถ ๊ฐ์ ์ก์ธ์ค ํ ์ ์์ผ๋ฉฐ ์์ ฏ์ด ์์ฑ ๋ ๋๋ง๋ค ์คํธ๋ฆผ์ / ๊ฐฑ์ / ํ๊ธฐ๋ฅผ ๋ง๋ค ์ ์๊ธฐ๋ฅผ ์ํ๋ ๊ทธ๋์ / ์ ๋ฐ์ดํธ /ํ๊ดด๋จ? ํ ์ค์ ์ฝ๋๋ก? ๋น๋ ๋ฉ์๋ ๋ด๋ถ?
์, mobx๋ฅผ ์ฌ์ฉํ๋ฉด ๋น๋ ๋ฐฉ๋ฒ์ด "๊ฐ๋ ์ฑ์ด ๋ ๋์" ์์ ์ ๋๊ฐ์ด ๋ณด์ด๋๋ก ํ ์ ์์ต๋๋ค(๊ด์ธก ๊ฐ๋ฅ ํญ๋ชฉ ์ฐธ์กฐ ์ ์ธ). ํํฌ์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ชจ๋ ์์ ์ ์ํํ๋ ์ค์ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค. ์ค์ ์ฝ๋๋ ์ฝ 10์ค์ด๋ฉฐ ๋ชจ๋ ์์ ฏ์์ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
final value3 = keyword TweenAnimationBuilder(tween: Tween(...));
๋ฌธ์์ด์ ๋ฐํํ๋ "TweenAnimationBuilder"๋ผ๋ ํด๋์ค?! ๋๋ ์ด๊ฒ์ด ์ ๋์ฐํ ์๊ฐ์ธ์ง ๊ฐ๊น์ด ๊ฐ์ง๋ ์์ต๋๋ค.
๋ค์ฌ์ฐ๊ธฐ/๊ฐ๋ ์ฑ์๋ ์ฐจ์ด๊ฐ ์์ต๋๋ค.
Future<double> future;
AsyncSnapshot<double> value = keyword FutureBuilder<double>(future: future);
๊ทธ๋ฆฌ๊ณ :
Future<double> future;
double value = await future;
๋ ๋ค ๋๊ฐ์ ์ผ์ ํฉ๋๋ค. ์ฆ, ๊ฐ์ฒด๋ฅผ ๋ฃ๊ณ ๊ฐ์ ์ธ๋ํํฉ๋๋ค.
๋๋ ๊ทธ๊ฒ์ ๋ํด ์ฝ์ ์์๋ ๊ฒ์ ์ ๋ง๋ก ๋ณด์ง ๋ชปํฉ๋๋ค. ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ ํํ๊ฒ ์ค๋ช ํฉ๋๋ค. ๋ค ๊ฐ์ ์์ ฏ์ด ์์ต๋๋ค. ์ธ ๊ฐ์ ์์ ฏ์๋ ๋น๋ ๋ฉ์๋๊ฐ ์๊ณ , ํ๋๋ ๋ฌธ์์ด๋ง ์์ต๋๋ค. ์ ๋ ๊ฐ์ธ์ ์ผ๋ก ์ ํ์ ์๋ตํ์ง ์์ ๊ฒ์ ๋๋ค. ๋ณ์๊ฐ ๋ชจ๋ ๋ฌด์์ธ์ง ์ ์ ์๊ธฐ ๋๋ฌธ์ ์ฝ๊ธฐ๊ฐ ๋ ์ด๋ ค์ธ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง ํฐ ๋ฌธ์ ๋ ์๋๋๋ค.
๋์ผํ ์ฃผ์ฅ์ด Promise/Future ์ฒด์ธ์ ์ ์ฉ๋ ์ ์์ต๋๋ค.
foo().then(x =>
bar(x).then(y =>
baz(y).then(z =>
qux(z)
)
)
)
๋
let x = await foo();
let y = await bar(x);
let z = await baz(y);
await qux(z);
์ฒซ ๋ฒ์งธ ์์ฑ ๋ฐฉ๋ฒ์ Promise๊ฐ ํ๋ ์๋์์ ์์ฑ๋๊ณ ์์ผ๋ฉฐ ์ฒด์ธ์ด ์ ํํ ์ด๋ป๊ฒ ํ์ฑ๋๋์ง๋ฅผ ๋ช ํํ ํด์ค๋ค๊ณ ๋งํ ์ ์์ต๋๋ค. ๋๋ ๋น์ ์ด ๊ทธ๊ฒ์ ๊ตฌ๋ ํ๋์ง, ๋๋ ๋น์ ์ด ๊ตฌ๋ฌธ์๋ฐ์ ์๊ฒฉ์ด ์๋ค๋ ์ ์์ ์ฝ์์ด ๋น๋์ ๊ทผ๋ณธ์ ์ผ๋ก ๋ค๋ฅด๋ค๊ณ ์๊ฐํ๋์ง ๊ถ๊ธํฉ๋๋ค.
๋ฌธ์์ด์ ๋ฐํํ๋ "TweenAnimationBuilder"๋ผ๋ ํด๋์ค?! ๋๋ ์ด๊ฒ์ด ์ ๋์ฐํ ์๊ฐ์ธ์ง ๊ฐ๊น์ด ๊ฐ์ง๋ ์์ต๋๋ค.
Promises/Futures์ ๋ํด ๋์ผํ ์ฃผ์ฅ์ ํ๊ณ await
๊ฐ Promise๋ฅผ ๋ฐํํ๋ค๋ ์ฌ์ค์ ๋ชจํธํ๊ฒ ํ๋ค๊ณ ๋งํ ์ ์์ต๋๋ค.
๊ตฌ๋ฌธ์ ํตํด ์ฌ๋ฌผ์ "ํ๊ธฐ"ํ๋ค๋ ์์ด๋์ด๋ ๊ฑฐ์ ์๋ก์ด ๊ฒ์ด ์๋๋๋ค. ์, ์ฃผ๋ฅ ์ธ์ด์์๋ async/await๋ฅผ ํตํด ์ ๊ณต๋์์ง๋ง, ์๋ฅผ ๋ค์ด F#์๋ ์ผ๋ถ ํ๋์ฝ์ด FP ์ธ์ด์ do
ํ๊ธฐ๋ฒ๊ณผ ์ ์ฌํ ๊ณ์ฐ ํํ์์ด ์์ต๋๋ค. ๊ฑฐ๊ธฐ์์ ํจ์ฌ ๋ ๋ง์ ๊ถํ์ ๊ฐ์ง๋ฉฐ ํน์ ๋ฒ๋ฅ ์ ์ถฉ์กฑํ๋ ๋ชจ๋ ๋ํผ์ ํจ๊ป ์๋ํ๋๋ก ์ผ๋ฐํ๋ฉ๋๋ค. Dart์ Monad๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ์ ์ํ๋ ๊ฒ์ ์๋์ง๋ง ๋น๋๊ธฐ ํธ์ถ์ ๋ฐ๋์ ํด๋นํ์ง ์๋ "๋ํ ํด์ "์ ๋ํ ์ ํ ์์ ๊ตฌ๋ฌธ์ ๋ํ ์ ๋ก๊ฐ ์๋ค๋ ์ ์ ์ธ๊ธํ ๊ฐ์น๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํ ๊ฑธ์ ๋ฌผ๋ฌ์์, ์ฌ๊ธฐ ๋ง์ ์ฌ๋๋ค์ด (์ ๋ฅผ ํฌํจํ์ฌ) ์ด๋ ค์์ ๊ฒช๊ณ ์๋ ํ ๊ฐ์ง๋ ๊ฐ๋
์ฑ์ ๋ํ ์ด ์ง๋ฌธ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. @rrousselGit ์ด ์ธ๊ธํ๋ฏ์ด ํ์ฌ Builder
๊ธฐ๋ฐ ์ ๊ทผ ๋ฐฉ์์ ๋ํ ๊ฐ๋
์ฑ ๋ฌธ์ ์ ์ด ์ค๋ ๋ ์ ๋ฐ์ ๊ฑธ์ณ ๋ง์ ์๊ฐ ์์ต๋๋ค. ์ฐ๋ฆฌ ์ค ๋ง์ ์ฌ๋๋ค์๊ฒ ๋ค์๊ณผ ๊ฐ์ ์ฌ์ค์ด ์๋ช
ํด ๋ณด์
๋๋ค.
Widget build(context) {
return ValueListenableBuilder<String>(
valueListenable: someValueListenable,
builder: (context, value, _) {
return StreamBuilder<int>(
stream: someStream,
builder: (context, value2) {
return TweenAnimationBuilder<double>(
tween: Tween(...),
builder: (context, value3) {
return Text('$value $value2 $value3');
},
);
},
);
},
);
}
๋ค์๋ณด๋ค ๊ฐ๋ ์ฑ์ด ํ์ ํ ๋จ์ด์ง๋๋ค.
Widget build(context) {
final value = keyword ValueListenableBuilder(valueListenable: someValueListenable);
final value2 = keyword StreamBuilder(stream: someStream);
final value3 = keyword TweenAnimationBuilder(tween: Tween(...));
return Text('$value $value2 $value3');
}
๊ทธ๋ฌ๋ @Hixie ์ @Rudiksz ๋ ๋ ๋ฒ์งธ๊ฐ ์ฒซ ๋ฒ์งธ ๊ฒ๋ณด๋ค ๋ ์ฝ๊ธฐ ์ฝ๋ค๋ ์์ด๋์ด์ ํ์ ์
๊ทธ๋์ ์ฌ๊ธฐ์ ๋ ๋ฒ์งธ ์ฝ๋ ๋ธ๋ก์ด ์ฒซ ๋ฒ์งธ ์ฝ๋ ๋ธ๋ก๋ณด๋ค ๋ ์ฝ๊ธฐ ์ฌ์ด ์ด์ ์ ๋ํ ๋ด ๋ถ์(๊ฐ์น๊ฐ ์๋ ์์ ๊ธ์ก์ ๋ํด)์ด ์์ต๋๋ค.
๋ด ๊ฒฝํ์ ๋ฐ๋ฅด๋ฉด ๋ค์ฌ์ฐ๊ธฐ๋ ์ผ๋ฐ์ ์ผ๋ก ๋น๋๊ธฐ์, ๋ถ๊ธฐ ๋๋ ์ฝ๋ฐฑ๊ณผ ๋์ผํ๋ฉฐ, ๋ชจ๋ ๋ค์ฌ์ฐ๊ธฐ๋์ง ์์ ์ ํ ์ฝ๋๋ณด๋ค ๋ ๋ง์ ์ธ์ง ๋ถํ๊ฐ โโํ์ํฉ๋๋ค. ์ฒซ ๋ฒ์งธ ์ฝ๋ ๋ธ๋ก์๋ ์ฌ๋ฌ ๊ฒน์ ๋ค์ฌ์ฐ๊ธฐ๊ฐ ์์ผ๋ฏ๋ก ์ฌ๊ธฐ์์ ์ผ์ด๋๋ ์ผ๊ณผ ๊ถ๊ทน์ ์ผ๋ก ๋ ๋๋ง๋๋ ๋ด์ฉ(๋จ์ผ Text
)์ ์ดํด๋ณด๋ ๋ฐ ์ ์ง ์์ ์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค. ์๋ง๋ ๋ค๋ฅธ ์ฌ๋๋ค์ ๋ง์์์ผ๋ก ๋ค์ฌ์ฐ๊ธฐ๋ฅผ ํตํด ์์
ํ๋ ๊ฒ์ด ๋ ๋์ ๊ฒ์
๋๋ค.
๋ ๋ฒ์งธ ์ฝ๋ ๋ธ๋ก์๋ ๋ฌธ์ ๋ฅผ ์ํํ๋ ๋ค์ฌ์ฐ๊ธฐ๊ฐ ์์ต๋๋ค.
์ฒซ ๋ฒ์งธ ์ฝ๋ ๋ธ๋ก์๋ return
๋ฌธ 3๊ฐ, ๋น๋ ๋ฌธ 3๊ฐ, ๋๋ค ํค๋ 3๊ฐ, ์ปจํ
์คํธ 3๊ฐ, ๋ง์ง๋ง์ผ๋ก ๊ฐ 3๊ฐ๊ฐ ์์ต๋๋ค. ๊ถ๊ทน์ ์ผ๋ก ์ฐ๋ฆฌ๊ฐ ๊ด์ฌ์ ๊ฐ๋ ๊ฒ์ ์ด ์ธ ๊ฐ์ง ๊ฐ์น์
๋๋ค. ๋๋จธ์ง๋ ์ฐ๋ฆฌ๋ฅผ ๊ฑฐ๊ธฐ์ ์ด๋ฅด๊ฒ ํ๋ ์์ฉ๊ตฌ์
๋๋ค. ์ ๋ ์ค์ ๋ก ์ด๊ฒ์ด ์ด ์ฝ๋ ๋ธ๋ก์์ ๊ฐ์ฅ ์ด๋ ค์ด ๋ถ๋ถ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋๋ฌด ๋ง์ ์ผ์ด ์งํ๋๊ณ ์๊ณ ๋ด๊ฐ ์ค์ ๋ก ๊ด์ฌ์ ๊ฐ๊ณ ์๋ ๋ถ๋ถ(๋น๋๊ฐ ๋ฐํํ๋ ๊ฐ)์ ๋๋ฌด ์์ ๋ถ๋ถ์ด๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ํ์ํ ๋ถ๋ถ์ ์ง์คํ๋ ๋์ ์์ฉ๊ตฌ๋ฅผ ๋ง๋๋ ๋ฐ ์ ์ ์๋์ง์ ๋๋ถ๋ถ์ ์๋นํฉ๋๋ค( ๋ค์, ๊ฐ).
๋ ๋ฒ์งธ ์ฝ๋ ๋ธ๋ก์๋ ์์ฉ๊ตฌ๊ฐ ํฌ๊ฒ ์ค์ด๋ค์ด ๋ด๊ฐ ๊ด์ฌ ์๋ ๋ถ๋ถ, ์ฆ ๊ฐ์ ์ง์คํ ์ ์์ต๋๋ค.
build
๋ฉ์๋์ ๊ฐ์ฅ ์ค์ํ ๋ถ๋ถ์ ์จ๊น๋๋ค.์ด build
๋ฉ์๋์ ๋ชจ๋ ๋ถ๋ถ์ด ์ค์ํ๋ค๋ ๊ฒ์ ์๊ณ ์์ง๋ง ์ด ์คํ์ผ์ ์ ์ธ์ UI ์ฝ๋๋ฅผ ์ฝ์ ๋ ์ผ๋ฐ์ ์ผ๋ก ์ฐพ๊ณ ์๋ ๊ฒ์ ์ด ๊ฒฝ์ฐ ๊ฐ์ฅ ๊น์ ์ค์ฒฉ ๋น๋์ ํฌํจ๋ Text
์์ ฏ์
๋๋ค. ๊ทธ Text
์์ ฏ์ ์ ๋ฉด ์ค์์ ์์นํ์ง ์๊ณ ๋ค์ฌ์ฐ๊ธฐ, ๊ตฌ๋ฌธ ๋ฐ ์๋์ ์ฌ๋ฌ ๋ ์ด์ด์ ๋ฌปํ ์์ต๋๋ค. ์ด ๋ ์ด์ด ์ค ํ๋์ Column
๋๋ Row
๋ฅผ ๋์ง๋ฉด ํจ์ฌ ๋ ๊น์ด ์ค์ฒฉ๋๊ณ ๊ทธ ์์ ์์ ๊ฐ์ฅ ๋ค์ฌ์ฐ๊ธฐ๋ ์น์
์ผ๋ก ์ถ์ ํ๋ ์ด์ ์กฐ์ฐจ ์์ต๋๋ค. .
๋ ๋ฒ์งธ ์ฝ๋ ๋ธ๋ก์์ ๋ฐํ๋๋ ์ค์ ๋ ๋๋ง ๊ฐ๋ฅ Widget
์ ํจ์์ ๋งจ ์๋์ ์์ผ๋ฉฐ ์ฆ์ ๋ช
๋ฐฑํฉ๋๋ค. ๋ํ ์ ์๋ ๊ตฌ๋ฌธ OP์ ๊ฐ์ ๊ฒ์ด ์์ ๋ ์๊ฐ์ ์ธ Widget
ํญ์ ํจ์์ ๋งจ ์๋์ ์๋ค๋ ๊ฒ์ ์ ์ ์์ผ๋ฏ๋ก ์ฝ๋๋ฅผ ํจ์ฌ ๋ ์์ธก ๊ฐ๋ฅํ๊ณ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
์ค์ฒฉ๊ณผ ๊ด๋ จ ํ์ฌ _tree_ ๋ฅผ ํํํ๋ ์ค์ฒฉ๊ณผ _sequence_ ๋ฅผ ํํํ๋ ์ค์ฒฉ ์๋ ์ฐจ์ด๊ฐ ์์ต๋๋ค.
์ผ๋ฐ์ ์ธ View -> Text
์ค์ฒฉ ๋ฑ์ ๊ฒฝ์ฐ ์ค์ฒฉ์ ํ๋ฉด์ ๋ถ๋ชจ-์์ ๊ด๊ณ ๋ฅผ ๋ํ๋ด๊ธฐ ๋๋ฌธ์ ์ค์ํฉ๋๋ค. Context์ ๊ฐ์ ๊ธฐ๋ฅ์ ๊ฒฝ์ฐ(Flutter์ ์๋์ง ํ์คํ์ง ์์) ์ปจํ
์คํธ์ ๋ฒ์๋ฅผ ๋ํ๋
๋๋ค. ๋ฐ๋ผ์ ์ค์ฒฉ ์์ฒด๋ ์ด๋ฌํ ๊ฒฝ์ฐ์ ์ค์ํ ์๋ฏธ๋ก ์ ์๋ฏธ๋ฅผ ๊ฐ์ง๋ฉฐ ๋ฌด์ํ ์ ์์ต๋๋ค. ๋ถ๋ชจ์ ์์์ ์๋ฆฌ๋ง ๋ฐ๊ฟ์ ๊ฒฐ๊ณผ๊ฐ ๊ฐ์ ๊ฒ์ด๋ผ๊ณ ๊ธฐ๋ํ ์๋ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๋น๋์ ์ค์ฒฉ(React์ "Render Props"๋ผ๊ณ ๋ ํจ) ๋๋ Promises์ ์ค์ฒฉ์ ์ฌ์ฉํ๋ฉด ์ค์ฒฉ์ด ์ผ๋ จ์ ๋ณํ/์ฆ๊ฐ ๋ฅผ ์ ๋ฌํด์ผ ํฉ๋๋ค. ํธ๋ฆฌ ์์ฒด๋ ๊ทธ๋ค์ง ์ค์ํ์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋
๋ฆฝ์ ์ธ ABuilder -> BBuilder -> CBuilder
์ค์ฒฉํ ๋ ๋ถ๋ชจ-์์ ๊ด๊ณ๋ ์ถ๊ฐ ์๋ฏธ๋ฅผ ์ ๋ฌํ์ง ์์ต๋๋ค.
์๋ ๋ฒ์์์ ์ธ ๊ฐ์ง ๊ฐ์ ๋ชจ๋ ์ฌ์ฉํ ์ ์๋ ํ ํด๋น ํธ๋ฆฌ ๊ตฌ์กฐ๋ ์ค์ ๋ก ๊ด๋ จ์ด ์์ต๋๋ค. ๊ฐ๋ ์ ์ผ๋ก๋ "ํํ"ํ๊ณ ์ค์ฒฉ์ ๊ตฌ๋ฌธ์ ์ํฐํฉํธ์ผ ๋ฟ์ ๋๋ค. ๋ฌผ๋ก ์๋ก์ ๊ฐ์ ์ฌ์ฉํ ์๋ ์์ง๋ง(์ด ๊ฒฝ์ฐ ์์๊ฐ ์ค์ํจ) ์ด๊ฒ์ ์์ฐจ ํจ์ ํธ์ถ์์๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ฉฐ ์ค์ฒฉ ์์ด ์ํํ ์ ์์ต๋๋ค.
์ด๊ฒ์ด async/await
๊ฐ ๋งค๋ ฅ์ ์ธ ์ด์ ์
๋๋ค. ๋ฎ์ ์์ค์ ๋ฉ์ปค๋์ฆ์ ์ค๋ช
ํ๋ ์ถ๊ฐ ์ ๋ณด(Promise์ ๋ถ๋ชจ-์์ ๊ด๊ณ)๋ฅผ ์ ๊ฑฐํ๊ณ ๋์ ๋์ ์์ค์ ์๋(์ํ์ค ์ค๋ช
)์ ์ง์คํ ์ ์์ต๋๋ค.
ํธ๋ฆฌ๋ ๋ชฉ๋ก๋ณด๋ค ์ ์ฐํ ๊ตฌ์กฐ์ ๋๋ค. ๊ทธ๋ฌ๋ ๊ฐ ๋ถ๋ชจ์๊ฒ ์์์ด ํ๋๋ง ์์ผ๋ฉด ๋ณ์ ๋๋ฌด ๊ฐ ๋ฉ๋๋ค. ๋ณธ์ง์ ์ผ๋ก ๋ชฉ๋ก์ ๋๋ค. Async/Await ๋ฐ Hooks๋ ์ ๋ณด๋ฅผ ์ ๋ฌํ์ง ์๋ ๊ฒ์ ๊ตฌ๋ฌธ์ ๋ญ๋นํ๊ณ ์์์ ์ธ์ํ๊ณ ์ ๊ฑฐํฉ๋๋ค.
์ด๊ฒ์ ๋ด๊ฐ ์ด์ ์ "์ด๊ฒ์ ์์ฉ๊ตฌ์ ๊ดํ ๊ฒ์ด ์๋๋ค"๋ผ๊ณ ๋งํ๊ณ ์ด์ ๋ ๋ด ์์ ๊ณผ ๋ชจ์๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ์ค์ ๋ก ํฅ๋ฏธ๋กญ์ต๋๋ค. ์ฌ๊ธฐ ๋ ๊ฐ์ง๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ทธ ์์ฒด๋ก ๋น๋(๋๋ ์ต์ํ React์ Render Props) ๋ "์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ ผ๋ฆฌ" ๋ฌธ์ ์ ๋ํ ์๋ฃจ์ (AFAIK)์ ๋๋ค. ๋ง์ด ์ฌ์ฉํ๋ฉด ์ธ์ฒด ๊ณตํ์ ์ด์ง ์๋ค๋ ๊ฒ์ ๋๋ค. ๋์ผํ ๊ตฌ์ฑ ์์์์ 4๊ฐ ๋๋ 5๊ฐ ์ด์์ ์ฌ์ฉํ๋ ๋ค์ฌ์ฐ๊ธฐ์ ์ํด ์์ฐ์ค๋ฝ๊ฒ ๋๋ดํ๊ฒ ๋ฉ๋๋ค. ๊ฐ ๋ค์ ๋ ๋ฒจ์ ๊ฐ๋ ์ฑ ํํธ์ ๋๋ค.
๊ทธ๋์ ๋์๊ฒ ํด๊ฒฐ๋์ง ์์ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ ๋ถ๋ถ์ ๋
์์ ์ค์ฒฉ ๋น์ฉ์ ์ค์ด๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ์ธ์๋ async / await
์ ์ ํํ ๊ฐ์ ์ธ์์
๋๋ค.
๋ค์๊ณผ ๊ฐ์ ์ด์ ๋ก ์ฝ์ ์ ์์ต๋๋ค.
์ด๊ฒ์ ๋ณด๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๋น ์์ฉ๊ตฌ ์ฝ๋๋ฅผ ๊ฐ์กฐ ํ์ํ๊ณ ๋์ด ์ฝ๊ฒ ์ฆ๊ธธ ์ ์๋๋ก ํจ๊ป ๊ทธ๋ฃนํ๋์ด ์๋์ง ๋๋ ๋์ด ์ฃผ์๋ฅผ ์ค์บํด์ผ ํ๋ ๋ชจ๋ ๊ณณ์ ํฉ์ด์ ธ ์๋์ง ์ฌ๋ถ๋ฅผ ๊ฐ์กฐ ํ์ํ๋ ๊ฒ์ ๋๋ค.
๊ฐ์กฐ ํ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋งค์ฐ ์ฝ๊ฒ ์ถ๋ก ํ ์ ์์ต๋๋ค. ๊ทธ๊ฒ ์์ด๋ ๋๊ฐ ๋ฌด์์ ์ด๋์์ ์ฌ์ฉํ๊ณ ์๋์ง ํ์
ํ๊ธฐ ์ ์ ์ ์ฒด ์์ธ ์ ๋ณด๋ฅผ ์ฝ์ด์ผ ํฉ๋๋ค.
์ด์ ์ด๊ฒ๊ณผ ๋น๊ตํ๋ฉด ๊ฐ์กฐ ํ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ค๋ณต๋ฉ๋๋ค. ๋ด ๋์ด ๊ฐ ๊ณณ์ด ์๊ธฐ ๋๋ฌธ์
๋๋ค.
๊ฐ๋ ์ฑ ๋ grokability์์ ์๋ง๋ ๋ถ์ผ์น๊ฐ ์๋ค๋ ์ ์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์์ต๋๋ค. @Hixie ๋ ๋๊ท๋ชจ ํธ๋ฆฌ๋ฅผ ์ง์์ ์ผ๋ก ์ฝ๊ณ ์ดํดํด์ผ ํ๋ ๋ชจ๋๋ฆฌ์ ํด๋์ค ํ์ผ์์ ์๊ฐ์
์ฐธ๊ณ ๋ก React์ Context๋ InheritedWidgets/Provider์ ๋๋ค.
๊ทธ๋ค ์ฌ์ด์ ์ ์ผํ ์ฐจ์ด์ ์ ํํฌ ์ ์ React์์ Builder ํจํด์ ์ฌ์ฉํ์ฌ Context/Inheritedwidget์ ์๋นํ๋ค๋ ๊ฒ์ ๋๋ค.
Flutter์๋ ๊ฐ๋จํ ํจ์ ํธ์ถ๋ก ๋ค์ ๋น๋๋ฅผ ๋ฐ์ธ๋ฉํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
๋ฐ๋ผ์ InheritedWidgets๋ฅผ ์ฌ์ฉํ์ฌ ํธ๋ฆฌ๋ฅผ ํ๋ฉดํํ๊ธฐ ์ํด ํํฌ๊ฐ ํ์ํ์ง ์์ต๋๋ค. ์ด๋ ๋น๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์
๋๋ค.
Builder๊ฐ ๋ ์์ฃผ ํ์ํ๊ธฐ ๋๋ฌธ์ ๋ ผ์๊ฐ ๋ ์ด๋ ค์ด ์ด์ ์ค ํ๋์ผ ๊ฒ์ ๋๋ค.
๊ทธ๋ฌ๋ ํํฌ์ ๊ฐ์ ์๋ฃจ์
์ ๋์
ํ๋ฉด https://github.com/flutter/flutter/issues/30062๋ฅผ ๋ชจ๋ ํด๊ฒฐํ ์ ์๋ค๋ ์ ์ ์ธ๊ธํ ๊ฐ์น๊ฐ
๋ฐ https://github.com/flutter/flutter/issues/12992
๋ํ @Hixie ๋ ๋ด ์๊ฒฌ์ผ๋ก๋ ๋ค๋ฅธ ์ธ์ด๋ณด๋ค Flutter๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ํธ๋ฆฌ์ด๊ธฐ ๋๋ฌธ์ ๊น์ ์ค์ฒฉ ํธ๋ฆฌ๋ฅผ ์ฝ๋ ๋ฐ ๋ ์ต์ํฉ๋๋ค. ๋ฌผ๋ก Flutter ์์ฒด์ ์ฃผ์ ๊ฐ๋ฐ์ ์ค ํ ๋ช ์ผ๋ก์ ๊ทธ๋ ํจ์ฌ ๋ ๋ง์ ๊ฒฝํ์ ํ์ ๊ฒ์ ๋๋ค. Flutter๋ ๋ณธ์ง์ ์ผ๋ก @Hixie ๊ฐ HTML5 ์ฌ์์ ๋ง๋ ๊ฒฝํ์ด ์๋ HTML๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๊น์ ์ค์ฒฉ์ด ์๋ ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ ํ๋ ์์ํฌ๋ก ์๊ฐํ ์ ์์ต๋๋ค. ์ฆ, ์ฝ๋ ๋ธ๋ก์ ๊ฐ์ฅ ์ค๋ฅธ์ชฝ ์ง์ ์ ์ฃผ์ ๋ ผ๋ฆฌ์ ๋ฐํ ๊ฐ์ด ์๋ ๊ณณ์ ๋๋ค.
๊ทธ๋ฌ๋, ๋๋ถ๋ถ์ ๊ฐ๋ฐ์๋ ๊ทธ๋ ์ง ์๋ค, ๋๋ ํ๋จ ์ธ์ด์ ๋
๊ทธ๊ฒ์ ๋ณด๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๋ด ๋๋๊ฐ ์๊ฐ์ ์ผ๋ก ์์ ํด์ผ ํ๋ ์ฝ๋์ ์์
๋๋ค. ๋์๊ฒ ์ด๊ฒ์ ํธ๋ฆฌ์์ ๋ฐํ๋๋ ๋ด์ฉ์ ๊ตฌ๋ฌธ ๋ถ์ํ๊ธฐ ์ ์ ๋ด ๋๋๊ฐ ์ํํด์ผ ํ๋ "๊ฐ๋จํ ์์
"์ ์ ํํ๊ฒ ๋ํ๋
๋๋ค.
๊ฐ๋จํ ๋งํด์ ๋น๋ ๋ฒ์ ์ ๋ง ๊ทธ๋๋ก ์ถ๊ฐ ์ ๋ณด๋ ์ปจํ ์คํธ๋ฅผ ์ถ๊ฐํ์ง ์์ผ๋ฉด์ 4๋ฐฐ ๋ ํฐ ์์ง ๊ณต๊ฐ์ ๊ฐ์ง๋ฉฐ ํจ์ฌ ๋ ํฌ์/์ฐ๋ํ ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ์์ถํฉ๋๋ค. ๋ด ์๊ฐ์ ๊ทธ๊ฒ์ ์ด๋ ค ์๊ณ ๋ซํ ๊ฒฝ์ฐ์ด๋ฉฐ, ๊ทธ ์ด์ ๋ง์ผ๋ก ๊ฐ๊ด์ ์ผ๋ก ์ฝ๊ธฐ๊ฐ ์ฝ์ง ์์ผ๋ฉฐ, ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ํ๋ฌํฐ๋ก ์ฒ๋ฆฌํ ๋ค์ฌ์ฐ๊ธฐ ๋ฐ ์ค๊ดํธ ์ ๋ ฌ์ ๋ํ ์ถ๊ฐ์ธ์ง ๋ถํ๋ฅผ ๊ณ ๋ คํ์ง๋ ์์ต๋๋ค.
๋ด ๋์ ์ฒ๋ฆฌ์ ๋ ์ต์ ํ๋ ๋ฐฐ๊ณ ํ CPU๋ผ๊ณ ์๊ฐํ์ญ๋๊น? :)
์ผ๋ฐ์ ์ธ
View -> Text
์ค์ฒฉ ๋ฑ์ ๊ฒฝ์ฐ ์ค์ฒฉ์ ํ๋ฉด์ _๋ถ๋ชจ-์์ ๊ด๊ณ_๋ฅผ ๋ํ๋ด๊ธฐ ๋๋ฌธ์ ์ค์ํฉ๋๋ค. Context์ ๊ฐ์ ๊ธฐ๋ฅ์ ๊ฒฝ์ฐ(Flutter์ ์๋์ง ํ์คํ์ง ์์) ์ปจํ ์คํธ์ ๋ฒ์๋ฅผ ๋ํ๋ ๋๋ค. ๋ฐ๋ผ์ ์ค์ฒฉ ์์ฒด๋ ์ด๋ฌํ ๊ฒฝ์ฐ์ ์ค์ํ ์๋ฏธ๋ก ์ ์๋ฏธ๋ฅผ ๊ฐ์ง๋ฉฐ ๋ฌด์ํ ์ ์์ต๋๋ค. ๋ถ๋ชจ์ ์์์ ์๋ฆฌ๋ง ๋ฐ๊ฟ์ ๊ฒฐ๊ณผ๊ฐ ๊ฐ์ ๊ฒ์ด๋ผ๊ณ ๊ธฐ๋ํ ์๋ ์์ต๋๋ค.
์ ์ ์ผ๋ก ๋์ํ๋ฉฐ ์์ ์ธ๊ธํ์ต๋๋ค. ์ํ๊ฐ ์๋ ์ถ๊ฐ ๋น์๊ฐ์ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์๊ฐ์ ๋์คํ๋ ์ด ํธ๋ฆฌ์ ์ถ๊ฐ ์ปจํ ์คํธ ๋ ์ด์ด๋ฅผ ์์ฑํ๋ ๊ฒ์ ์๋ฏธ์ ์๋ฏธ๊ฐ ์์ต๋๋ค. 5๊ฐ์ ์ ๋๋ฉ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ์ด์ ์์ ฏ์ ๊น์ด๊ฐ 5๊ฐ์ ๋๊น? ๊ทธ ๋์ ์์ค์์๋ง ํ์ฌ ์ ๊ทผ ๋ฐฉ์์ ๋์๊ฐ๋ฉ๋๋ค.
์ฌ๊ธฐ์ ๋ ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
๊ฐ๋น์ผ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ ๋ ์ผ๋ง๋ ์ด๋ ต๊ณ ๋ช ์์ ์ด์ด์ผ ํ๋์ง์ ๋ํด ์๊ฒฌ์ด ๋ถ๋ถํ๋ค๊ณ ์๊ฐํฉ๋๋ค. Flutter์ ์ฒ ํ์ ๊ฐ๋ฐ์๊ฐ ์ธ์ ์ด๋ป๊ฒ ์ฌ์ฉํ ์ง์ ๋ํด ์ง์งํ๊ฒ ์๊ฐํ ์ ์๋๋ก ๋ ์ด๋ ต๊ณ ๋ช ์์ ์ด์ด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค. ์คํธ๋ฆผ, ์ ๋๋ฉ์ด์ , ๋ ์ด์์ ๋น๋ ๋ฑ์ ๋๋ฌด ์ฌ์ธ ๊ฒฝ์ฐ ๋นํจ์จ์ ์ผ๋ก ์ฌ์ฉ๋ ์ ์๋ ์ฌ์ํ์ง ์์ ๋น์ฉ์ ๋ํ๋ ๋๋ค.
๋น๋๋ ๋๊ธฐํ์ด์ง๋ง ์ฑ ๊ฐ๋ฐ์๋ก์ ๋ค๋ฃจ๋ ๊ฐ์ฅ ํฅ๋ฏธ๋ก์ด ๊ฒ์ ๋น๋๊ธฐ์ ๋๋ค. ๋ฌผ๋ก ๋น๋๋ฅผ ๋น๋๊ธฐ์์ผ๋ก ๋ง๋ค ์๋ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ Stream/Animation/FutureBuilder์ ๊ฐ์ ์ด๋ฌํ ํธ์๋ฅผ ๋ง๋ค์์ง๋ง ๊ฐ๋ฐ์๊ฐ ํ์๋ก ํ๋ ๊ฒ์ ํญ์ ์ถฉ๋ถํ ์ ์๋ํ์ง๋ ์์ต๋๋ค. ํ๋ ์์ํฌ์์ Stream์ด๋ FutureBuilder๋ฅผ ๋ง์ด ์ฌ์ฉํ์ง ์๋๋ค๋ ๋ป์ผ ๊ฒ์ ๋๋ค.
๋ฌผ๋ก ๊ฐ๋ฐ์์๊ฒ ๋น๋๊ธฐ ์์ ์ผ๋ก ์์ ํ ๋ ํญ์ ์ฌ์ฉ์ ์ง์ ๋ ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋๋ก ์ง์ํ๋ ๊ฒ์ด ์๋ฃจ์ ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด ๋ฒ๊ทธ์์ ๋ด๊ฐ ๋ณด๊ณ ์๋ ์์๋ ์ฐ๋ฆฌ๊ฐ ๊ทธ๋ฅ ๊ธฐ๋ค๋ฆด ์ ์๋ ๋น๋๊ธฐ ๋ฐ ๋๊ธฐํ ์์ ์ด ํผํฉ๋์ด ์์ต๋๋ค. ๋น๋๋ ๋ชจ๋ ํธ์ถ์์ ๋ฌด์ธ๊ฐ๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค.
fwiw์์ React ํ์ 1 ๋๊ธฐ๋ก ๊ฐ๋
์ฑ ๋ฌธ์ ์ฌ์ฌ์ฉ์ ํด๊ฒฐํ์ต๋๋ค.
Hooks Motivation: ์ปดํฌ๋ํธ ๊ฐ์ Stateful ๋ก์ง์ ์ฌ์ฌ์ฉํ๊ธฐ ์ด๋ ต์ต๋๋ค.
React ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋์์ ๊ตฌ์ฑ ์์์ "์ฒจ๋ถ"ํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ง ์์ต๋๋ค . ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ์๋ํ๋ ํจํด์ ์ต์ํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ํจํด์ ์ฌ์ฉํ๋ ค๋ฉด ๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฉํ ๋ ๊ตฌ์ฑ ์์๋ฅผ ์ฌ๊ตฌ์ฑํด์ผ ํ๋ฏ๋ก ๋ฒ๊ฑฐ๋กญ๊ณ ์ฝ๋๋ฅผ ๋ฐ๋ฅด๊ธฐ๊ฐ ๋ ์ด๋ ค์์ง ์ ์์ต๋๋ค .
์ด๊ฒ์ Flutter๊ฐ ํ์ฌ ๊ธฐ๋ณธ์ ์ผ๋ก '์ํ๋ฅผ ๊ตฌ์ฑ'ํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ง ์๋ ๊ฒ๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ๋ํ ๋ ์ด์์ ํธ๋ฆฌ๋ฅผ ์์ ํ์ฌ ์์ ํ๊ธฐ๊ฐ ๋ ๋ณต์กํ๊ณ "๋ฐ๋ผํ๊ธฐ๊ฐ ๋ ์ด๋ ค์์ง๋" ๋น๋๋ฅผ ๋ง๋ค ๋ ๋ฐ์ํ๋ ์ผ์ ๋ฐ์ํฉ๋๋ค.
build
๊ฐ ๋งค๋ฒ ํธ์ถ๋์ด์ผ ํ๋ ๊ฒฝ์ฐ @dnfield ์๋ง๋ ๋น๋๊ฐ ํญ์ ๋๊ธฐํ๋๋๋ก build
๋ฉ์๋์ ์๋ ํํฌ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค initState
๋ฐ dispose
์
๋๋ค. ํํฌ๋ฅผ ์์ฑํ๋ ์ฌ๋๋ค๋ก๋ถํฐ ๊ทธ๋ ๊ฒ ํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์์ต๋๊น?
Promises/Futures์ ๋ํด ๋์ผํ ์ฃผ์ฅ์ ํ๊ณ
await
๊ฐ Promise๋ฅผ ๋ฐํํ๋ค๋ ์ฌ์ค์ ๋ชจํธํ๊ฒ ํ๋ค๊ณ ๋งํ ์ ์์ต๋๋ค.
์๋์. Await๋ ๋ง ๊ทธ๋๋ก ํ๋์ ๋จ์ผ ๊ธฐ๋ฅ์ ๋ํ ๊ตฌ๋ฌธ ์คํ์ ๋๋ค. ์ฅํฉํ Futures ๋๋ ์ ์ธ์ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋ ๋ ์จ์ ์ฝ๋์ __intent__๋ ๋์ผํฉ๋๋ค.
์ฌ๊ธฐ์์ ์๊ตฌํ๋ ๊ฒ์ ์์ ํ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ์ฒ๋ฆฌํ๋ ์์ค ์ฝ๋๋ฅผ ๋์ผํ ์ฐ์ฐ ์๋๋ก ์ฎ๊ธฐ๊ณ , ๋จ์ผ ํค์๋ ๋ค์ ๋ชจ๋ ์ข ๋ฅ์ ๋ค๋ฅธ ๋์์ ์จ๊ธฐ๊ณ , ์ด๋ป๊ฒ๋ ์ธ์ง ๋ถํ๋ฅผ ์ค์ธ๋ค๊ณ ์ฃผ์ฅํ๋ ๊ฒ์ ๋๋ค.
๊ทธ๊ฒ์ ์์ ํ ์๋ชป๋ ๊ฒ์ ๋๋ค. ์ด์ ๊ทธ ํค์๋๋ฅผ ์ฌ์ฉํ ๋๋ง๋ค ๊ฒฐ๊ณผ๊ฐ ๋น๋๊ธฐ ์์ ์ ์ํํ๊ณ , ๋ถํ์ํ ์ฌ๊ตฌ์ถ์ ํธ๋ฆฌ๊ฑฐํ๊ณ , ์๋ช ์ด ๊ธด ๊ฐ์ฒด๋ฅผ ์ด๊ธฐํํ๊ณ , ๋คํธ์ํฌ ํธ์ถ์ ์ํํ๊ณ , ๋์คํฌ์์ ํ์ผ์ ์ฝ๊ฑฐ๋, ๋จ์ํ ์ ์ ๊ฐ์ ๋ฐํํ๋์ง์ ๋ํด ๊ถ๊ธํดํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. . ์ด ๋ชจ๋ ์ํฉ์ ๋งค์ฐ ๋ค๋ฅด๋ฉฐ ๋ด๊ฐ ์ฌ์ฉํ๋ ํํฌ์ ๋ง์ ์ต์ํด์ ธ์ผ ํฉ๋๋ค.
์ฌ๊ธฐ ์๋ ๋๋ถ๋ถ์ ๊ฐ๋ฐ์๋ ๊ตฌํ ์ธ๋ถ ์ฌํญ์ ๋ํด ๊ฑฑ์ ํ ํ์ ์์ด ์ด๋ฌํ "ํํฌ"๋ฅผ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ์ข
๋ฅ์ ์ธ๋ถ ์ฌํญ์ ์ ๊ฒฝ์ฐ๋ ๊ฒ์ ์ข์ํ์ง ์๊ณ ์์ฌ์ด ๊ฐ๋ฐ์ ์ํ๋ค๋ ๊ฒ์ ํ ๋ก ์์ ์ดํดํฉ๋๋ค.
์์ ํ ์๋ฏธ๋ฅผ ์ดํดํ์ง ๋ชปํ ์ฑ ์์ "ํํฌ"๋ฅผ ์ฌ์ฉํ๋ฉด ๋นํจ์จ์ ์ด๊ณ ์๋ชป๋ ์ฝ๋๊ฐ ์์ฑ๋๊ณ ์ฌ๋๋ค์ด ๋ฐ์ ์ด์ ์๊ฒ ๋ฉ๋๋ค. ๋ฐ๋ผ์ "์ด๋ณด์ ๊ฐ๋ฐ์ ๋ณดํธ" ๋ฌธ์ ๋ ํด๊ฒฐ๋์ง ์์ต๋๋ค.
์ฌ์ฉ ์ฌ๋ก๊ฐ ๊ฐ๋จํ๋ค๋ฉด ํํฌ๋ฅผ ๊ธฐ๊บผ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋น๋๋ฅผ ์ํ๋ ๋๋ก ์ฌ์ฉํ๊ณ ์ค์ฒฉํ ์ ์์ง๋ง ์ฑ์ด ๋ณต์กํด์ ธ์ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ ๋ฐ ์ด๋ ค์์ ๊ฒช์์๋ก ์์ ์ ์ฝ๋์ ์ํคํ ์ฒ์ ๋ ๋ง์ ๊ด์ฌ์ ๊ธฐ์ธ์ฌ์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ ์ฌ์ ์ผ๋ก ์๋ฐฑ๋ง ๋ช ์ ์ฌ์ฉ์๋ฅผ ์ํ ์ฑ์ ๊ตฌ์ถํ๊ณ ์๋ค๋ฉด ์ค์ํ ์ธ๋ถ ์ฌํญ์ ์ถ์ํํ๋ "๋ง๋ฒ"์ ์ฌ์ฉํ๋ ๊ฒ์ ๋งค์ฐ ์ฃผ์ ํ ๊ฒ์ ๋๋ค. ์ง๊ธ ์ ๋ Flutter์ API๊ฐ ๋งค์ฐ ๊ฐ๋จํ ์ฌ์ฉ ์ฌ๋ก์ ๋ํด ๋จ์ํ๊ณ , ๋๊ตฌ๋ ๋งค์ฐ ํจ์จ์ ์ธ ๋ฐฉ์์ผ๋ก ๋ชจ๋ ์ข ๋ฅ์ ๋ณต์กํ ๋ก์ง์ ๊ตฌํํ ์ ์๋๋ก ์ฌ์ ํ ์ ์ฐํ๋ค๋ ๊ฒ์ ์์์ต๋๋ค.
@Rudiksz ๋ค์ ๋งํ์ง๋ง ์๋ฌด๋ ํํฌ๋ก ์ด๋ํ๋๋ก ๊ฐ์ํ์ง ์์ต๋๋ค. ํ์ฌ ์คํ์ผ์ ๊ทธ๋๋ก ์ ์ง๋ฉ๋๋ค. ์ด ์ง์์ ์ง๋ฉดํ์ฌ ๋น์ ์ ์ฃผ์ฅ์ ๋ฌด์์ ๋๊น?
์ด์จ๋ ์ฌ๋๋ค์ ์ฌ๋ฌ ํํฌ๊ฐ ์ด๋ป๊ฒ๋ ์ฑ์ ์ฐจ๋จํ๊ณ ์๋ค๋ ๊ฒ์ ์๊ฒ ๋๋ฉด ์ฌ์ ํ ํจ์จ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ํ์ฌ ์คํ์ผ์์์ ๋ง์ฐฌ๊ฐ์ง๋ก ํ๋กํ์ ์์ฑํ๊ฑฐ๋ ์ฑ์ ์คํํ ๋๋ ๋ณผ ์ ์์ต๋๋ค.
@Rudiksz ๋ค์ ๋งํ์ง๋ง ์๋ฌด๋ ํํฌ๋ก ์ด๋ํ๋๋ก ๊ฐ์ํ์ง ์์ต๋๋ค. ํ์ฌ ์คํ์ผ์ ๊ทธ๋๋ก ์ ์ง๋ฉ๋๋ค. ์ด ์ง์์ ์ง๋ฉดํ์ฌ ๋น์ ์ ์ฃผ์ฅ์ ๋ฌด์์ ๋๊น?
์ด๋ฐ, ์ด ๊ฐ์ ์ฃผ์ฅ์ ํ๋ ์์ํฌ์ ๋ฌธ์ ์ ๋ํด ๋ถํํ๋ ์ฌ๋๋ค์๊ฒ๋ ์ ์ฉ๋ฉ๋๋ค. ์๋ฌด๋ ํํฌ ํจํค์ง๋ฅผ ์ฌ์ฉํ์ง ์๋๋ก ๊ฐ์ํ์ง ์์ต๋๋ค.
๋๋ ์ฌ๊ธฐ์ ๋งค์ฐ ๋ฌด๋๋ํ ๊ฒ์ด๋ค.
์ด ๋ฌธ์ ๋ ์ค์ ๋ก ํํฌ, statefulwidget ๋ฐ ๋๊ฐ ๋ฌด์์ ์ฌ์ฉํ๋์ง์ ๊ดํ ๊ฒ์ด ์๋๋ผ ์ผ๋ถ ์ฌ๋๋ค์ด 5์ค์ ์ฝ๋๋ฅผ ๋ ์์ฑํ ์ ์๋๋ก ์์ญ ๋
์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋๋๋ฆฌ๋ ๊ฒ์ ๊ดํ ๊ฒ์
๋๋ค.
๋น์ ์ ์ฃผ์ฅ์ ์ ๋ง ํตํ์ง ์์ต๋๋ค. ์ด ๋ฌธ์ ๊ฐ ์์ฑ๋ ์ด์ ๋ flutter_hooks ํจํค์ง๊ฐ ํ๋ ์์ํฌ์ ์๋ ๊ฒ์ผ๋ก ๊ฐ๋ฅํ ๋ชจ๋ ์์ ์ ์ํํ์ง ์๋ ๋ฐ๋ฉด ํ์ฌ ๋ชจ๋ธ์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ ์์ํฌ์ ์ด๋ฏธ ์๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ธ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก flutter_hooks์ ๊ธฐ๋ฅ์ ํ๋ ์์ํฌ๋ก ์ด๋ํ๋ ๊ฒ์ ๋๋ค. ๋น์ ์ ์ฃผ์ฅ์ ๋ด๊ฐ ํ์ฌ ๋ชจ๋ธ๋ก ํ ์ ์๋ ๊ฒ์ ๋ฌด์์ด๋ ์ง ํํฌ ํจํค์ง๋ก๋ ํ ์ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค. ์ด๋ ์ฌ์ค์ด ์๋๋๋ค. ์ด ํ ๋ก ์ ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ๊ฐ์ต๋๋ค. ๊ทธ๊ฒ์ด ์ฌ์ค์ด๋ผ๋ฉด ์๋ํ ๊ฒ์ด๊ณ , ์ด๋ ๋ํ ํํฌ๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ ์์ํฌ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํ๋ฉฐ, ๋ฐ๋ผ์ ๋ค์ ํํฌ์ ๋นํํฌ๊ฐ ๋์ผํ๋ฏ๋ก ํ์ฌ ๋ชจ๋ธ๊ณผ ํํฌ ๊ธฐ๋ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ ๊ฐ ์ฃผ์ฅํ๋ ๋ชจ๋ธ์ ๋๋ค.
์ฝ๋๋ฅผ ์ฝ๊ฒ ์ฝ์ ์ ์๋๋ก ์ ์งํ๋ ๊ฒ์ด ๋ชจ๋ฒ ์ฌ๋ก์ด๊ณ ๊ณผ๋ํ ์ค์ฒฉ์ด ์ํฐ ํจํด์ด๋ผ๋ ๊ฒ์ ์๊ณ ์์ผ๋ฏ๋ก ๋ชจ๋ฒ ์ฌ๋ก๊ฐ ์ด๋์์ ์๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ ํํ ์ด๋ค ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ธ๊ธํ๊ณ ์์ต๋๊น?
fwiw์์ React ํ์ 1 ๋๊ธฐ๋ก ๊ฐ๋ ์ฑ ๋ฌธ์ ์ฌ์ฌ์ฉ์ ํด๊ฒฐํ์ต๋๋ค.
Hooks Motivation: ์ปดํฌ๋ํธ ๊ฐ์ Stateful ๋ก์ง์ ์ฌ์ฌ์ฉํ๊ธฐ ์ด๋ ต์ต๋๋ค.
React ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋์์ ๊ตฌ์ฑ ์์์ "์ฒจ๋ถ"ํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ง ์์ต๋๋ค . ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ์๋ํ๋ ํจํด์ ์ต์ํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ํจํด์ ์ฌ์ฉํ๋ ค๋ฉด ๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฉํ ๋ ๊ตฌ์ฑ ์์๋ฅผ ์ฌ๊ตฌ์ฑํด์ผ ํ๋ฏ๋ก ๋ฒ๊ฑฐ๋กญ๊ณ ์ฝ๋๋ฅผ ๋ฐ๋ฅด๊ธฐ๊ฐ ๋ ์ด๋ ค์์ง ์ ์์ต๋๋ค .
Flutter๊ฐ React๋ณด๋ค ํจ์ฌ ๋ ํ๋ฅญํ๋ค๊ณ ๋ชจ๋ ์ฌ๋๋ค์ด ์ด๊ดํ๋ ๊ฒ์ ๋ค์์ต๋๋ค. React๊ฐ ํ๋ ๋ชจ๋ ์ผ์ ํ์ง ์๊ธฐ ๋๋ฌธ์ผ๊น์? Flutter๊ฐ React๋ณด๋ค ๋ช ๋ง์ผ ์์ ์๋ค๊ณ ๋งํ ์๋ ์๊ณ ๋ชจ๋ ์์ ์ React์ ๋๊ฐ์ด ์ํํ๋๋ก ์์ฒญํ ์๋ ์์ต๋๋ค.
Flutter๊ฐ ์ฃผ์ด์ง ๋ฌธ์ ์ ๋ํด ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ ์๋ฃจ์ ์ ๋ฌด์์ด๋ ์์ฒด ์ฅ์ ์ด ์์ด์ผ ํฉ๋๋ค. ๋๋ React์ ์ต์ํ์ง ์์ง๋ง ๋ถ๋ช ํ ๋๋ โโ์ ๋ง ๋๋ผ์ด ๊ธฐ์ ์ ๋์น๊ณ ์์ต๋๋ค. :/
Flutter๊ฐ React์ ๊ฐ์ ๋ชจ๋ ์์ ์ ์ํํด์ผ ํ๋ค๊ณ ์ฃผ์ฅํ๋ ์ฌ๋์ ์๋ฌด๋ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ฌ์ค Flutter์ ์์ ฏ ๋ ์ด์ด๋ React์์ ํฌ๊ฒ ์๊ฐ์ ๋ฐ์์ต๋๋ค. ๊ณต์ ๋ฌธ์์ ๋์ ์์ต๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ์์ ฏ์ React ๊ตฌ์ฑ ์์์ ๋์ผํ ์ด์ ๊ณผ ๋์ผํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
์ด๊ฒ์ ๋ํ React๊ฐ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ๋ค๋ฃจ๋ ๋ฐ Flutter๋ณด๋ค ๋ ๋ง์ ๊ฒฝํ์ ๊ฐ์ง๊ณ ์์์ ์๋ฏธํฉ๋๋ค.
๊ทธ๊ฒ์ ๊ทธ๋ค์ ๋ ์ค๋ ๋ง์ฃผํ๊ณ ๋ ์ ์ดํดํ์ต๋๋ค.
๋ฐ๋ผ์ Flutter ๋ฌธ์ ์ ๋ํ ์๋ฃจ์ ์ด React ๋ฌธ์ ์ ๋ํ ์๋ฃจ์ ๊ณผ ์ ์ฌํ๋ค๋ ๊ฒ์ ๋๋ผ์ด ์ผ์ด ์๋๋๋ค.
@Rudiksz Flutter์ ์ฌ์ฉ์ API๋ ๋ด๋ถ API๊ฐ ๋ค๋ฅผ ์ ์์์๋ ๋ถ๊ตฌํ๊ณ React์ ํด๋์ค ๊ธฐ๋ฐ ๋ชจ๋ธ๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ๋๋ ๋ค๋ฅธ ํ๋ ์์ํฌ์์ ํํฌ์ ์ ์ฌํ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์ฌ์ฉํ์ง ์์ ์ฌ๋๋ค์๊ฒ ๊ฑฐ์ ๋ ์ ์ ์ผ๋ก ๊ธฐ๋ฐ์ ๋ ์๊ฒฌ์ ์ด๋ถ๋ฒ์ด ์๋ ๊ฒ ๊ฐ๋ค๊ณ ์์ ์ธ๊ธํ๋ฏ์ด ํํฌ๊ฐ ์๋ React๋ฅผ ์๋ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ ์ฌ์ฑ์ ๊ฐ์ํ ๋, ์์์ ์ธ๊ธํ ๊ฒ์ฒ๋ผ ๋ฌธ์ ์ ๋ํ ์๋ฃจ์ ์ด ์ ์ฌํด ๋ณด์ด๋ ๊ฒ์ ๋๋ผ์ด ์ผ์ด ์๋๋๋ค.
์ ๋ฐ ์๋ก ์ธ์ฐ์ง ์๋๋ก ์ต์ ์ ๋คํฉ์๋ค.
์ธ์์ด ์ฐ๋ฆฌ๋ฅผ ์ด๋ ์ ์ผํ ๊ฒ์ ์ด ํ ๋ก ์ ๋๋ด๊ณ ํด๊ฒฐ์ฑ ์ ์ฐพ์ง ๋ชปํ๋ ๊ฒ๋ฟ์ ๋๋ค.
Flutter๊ฐ React๋ณด๋ค ํจ์ฌ ๋ ํ๋ฅญํ๋ค๊ณ ๋ชจ๋ ์ฌ๋๋ค์ด ์ด๊ดํ๋ ๊ฒ์ ๋ค์์ต๋๋ค. React๊ฐ ํ๋ ๋ชจ๋ ์ผ์ ํ์ง ์๊ธฐ ๋๋ฌธ์ผ๊น์? Flutter๊ฐ React๋ณด๋ค ๋ช ๋ง์ผ ์์ ์๋ค๊ณ ๋งํ ์๋ ์๊ณ ๋ชจ๋ ์์ ์ React์ ๋๊ฐ์ด ์ํํ๋๋ก ์์ฒญํ ์๋ ์์ต๋๋ค.
React ํ์ด ํํฌ๋ฅผ ์๊ฐํด ๋์ ๋ ๋น์ทํ ๋๊ธฐ๊ฐ ์์๋ค๋ ์ ์ ์ง์ ํ๋ฉด์ ์ฌ๊ธฐ์์ ํํํ๋ ์ฐ๋ ค๋ฅผ ํ์ธํฉ๋๋ค. ์ด ์ ํ์ ๊ตฌ์ฑ ์์ ๊ธฐ๋ฐ ํ๋ ์์ํฌ ๋ด์์ ๊ณตํต ์ํ ์ ์ฅ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๊ณ ๊ฒฐํฉํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์์์ ํ์คํ ํ์ธํ๊ณ ๊ฐ๋ ์ฑ, ์ค์ฒฉ ๋ฐ ๋ณด๊ธฐ์ "ํด๋ฌํฐ"์ ๋ํ ์ผ๋ฐ์ ์ธ ๋ฌธ์ ์ ๋ํ ๋ ผ์๋ฅผ ์ด๋ ์ ๋ ๊ฒ์ฆํฉ๋๋ค.
์ด๋ค ๊ฒ์ ๋ํด์๋ ์ด๊ดํ์ง ์๊ณ React์์ ์ผํ ์ ๋ ์๊ณ Flutter๋ฅผ ์ฌ๋ํฉ๋๋ค. ์ฌ๊ธฐ์ ๋ฌธ์ ๋ฅผ ์ฝ๊ฒ ๋ณผ ์ ์์ต๋๋ค.
@Rudiksz ์ค์ ๋ก ์ ์ฉํ ๋๊น์ง ์ค์ ๋ก ์ฑ๋ฅ์ด
@Hixie ์ด๊ฒ์ HookWidget
๋ฐ StatefulWidget
๋ ๋ค๋ก userId์ ์ฌ์ฉ์ ๋๋ค์์ ํ์ํ๊ธฐ ์ํ ์์ ฏ์ ๊ตฌํํ๊ธฐ ์ํด ์ผ๋ฐ ํ๋ฌํฐ ์ฌ์ฉ์๊ฐ ๊ฐ์ง ์ ์๋ ์ฌ์ ์ ์์
๋๋ค.
__ํํฌ ์์ ฏ__
String useUserNickname(Id userid) {
final name = useState("");
useEffect(async () {
name.value = "Loading...";
name.value = await fetchNicknames()[userId;
}, [userId]);
return name.value;
}
class UserNickname extends HookWidget {
final userId;
Widget build(BuildContext context) {
final nickname = useUserNickname(userId);
return Text(nickname);
}
}
__์ํ ์ ์ฅ ์์ ฏ__
class UserNickname extends Widget {
final userId;
// ... createState() ...
}
class UserNicknameState extends State {
String nickname= "";
initState() {
super.initState();
fetchAndUpdate();
}
fetchAndUpdate() async {
setState(() { this.nickname = "Loading..." });
final result = await fetchNicknames()[widget.userId];
setState(() { this.nickname = result });
}
void didUpdateWidget(oldWidget) {
if (oldWidget.userId != widget.userId) {
fetchAndUpdate();
}
}
Widget build(BuildContext context) {
return Text(this.nickname);
}
}
์ง๊ธ๊น์ง ํฅ๋ฏธ๋ก์ด ๊ฒ์ ์์ต๋๋ค. ๋ ์๋ฃจ์
๋ชจ๋ ์๋นํ ์์ฉ ๊ฐ๋ฅํ๊ณ ๊ฐ๋จํ๋ฉฐ ์ฑ๋ฅ์ด ๋ฐ์ด๋ฉ๋๋ค.
์ด์ UserNickname
๋ด๋ถ์์ ListView
UserNickname
๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํฉ๋๋ค. ๋ณด์๋ค์ํผ fetchNicknames๋ ํ๋์ ๋๋ค์๋ฟ๋ง ์๋๋ผ ๋๋ค์์ ๋งต์ ๋ฐํํฉ๋๋ค. ๊ทธ๋์ ๋งค๋ฒ ํธ์ถํ๋ ๊ฒ์ ๋ถํ์ํฉ๋๋ค. ์ฌ๊ธฐ์ ์ ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ์๋ฃจ์
:
fetchNicknames()
ํธ์ถ ๋ก์ง์ ์์ ์์ ฏ์ผ๋ก ์ด๋ํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํฉ๋๋ค.์ฒซ ๋ฒ์งธ ์๋ฃจ์
์ ํ์ฉ๋์ง๋ง 2๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
1 - ์ด์ UserNickname
์ธ๋ชจ์๊ฒ ๋ ๋๋ง๋ฉ๋๋ค. ์๋ํ๋ฉด ์ด๊ฒ์ ์ด์ ๋จ์ง ํ
์คํธ ์์ ฏ์ด๊ณ ๋ค๋ฅธ ๊ณณ์์ ์ฌ์ฉํ๋ ค๋ฉด ์์ ์์ ฏ( ListView
)์์ ์ํํ ์์
์ ๋ฐ๋ณตํด์ผ ํ๊ธฐ ๋๋ฌธ์
๋๋ค. . ๋๋ค์์ ๋ณด์ฌ์ฃผ๋ ๋ก์ง์ UserNickname
ํ์ง๋ง ๋ฐ๋ก โโ์ฎ๊ฒจ์ผ ํฉ๋๋ค.
2 - ๋ค๋ฅธ ๋ง์ ํ์ ํธ๋ฆฌ์์ fetchNicknames()
๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ์์ฉ ํ๋ก๊ทธ๋จ์ ํ ๋ถ๋ถ๋ง์ด ์๋๋ผ ๋ชจ๋ ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ํด ์บ์ํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋ฐ๋ผ์ ์บ์ ๊ด๋ฆฌ์๋ฅผ ์ ํํ๊ณ InheritedWidgets
๋๋ Provider
์๋ CacheManager
ํด๋์ค๋ฅผ ์ ๊ณตํ๋ค๊ณ ์์ํด ๋ณด์ญ์์ค.
์บ์ฑ์ ๋ํ ์ง์์ ์ถ๊ฐํ ํ:
__ํํฌ ์์ ฏ__
String useUserNickname(Id userid) {
final context = useContext();
final cache = Provider.of<CacheManager>(context);
final name = useState("");
useEffect(async () {
name.value = "Loading...";
var cachedValue = cache.get("nicknames");
if (cachedValue == null || cachedValue[widget.userId] == null) {
final result = await fetchNicknames();
cache.set("nicknames", result );
cachedValue = result ;
}
final result = cachedValue[widget.userId];
name.value = result ;
}, [userId]);
return name.value;
}
class UserNickname extends HookWidget {
final userId;
Widget build(BuildContext context) {
final nickname = useUserNickname(userId);
return Text(nickname);
}
}
__์ํ ์ ์ฅ ์์ ฏ__
class UserNickname extends Widget {
final userId;
// ... createState() ...
}
class UserNicknameState extends State {
String nickname= "";
CacheManager cache;
initState() {
super.initState();
fetchAndUpdate();
this.cache = Provider.of<CacheManager>(context);
}
fetchAndUpdate() async {
setState(() { this.nickname = "Loading..." });
var cachedValue = this.cache.get("nicknames");
if (cachedValue == null || cachedValue[widget.userId] == null) {
final result = await fetchNicknames();
this.cache.set("nicknames", result );
cachedValue = result ;
}
final result = cachedValue [widget.userId];
setState(() { this.nickname = result });
}
void didUpdateWidget(oldWidget) {
if (oldWidget.userId != widget.userId) {
fetchAndUpdate();
}
}
Widget build(BuildContext context) {
return Text(this.nickname);
}
}
๋ณ๋ช ์ด ๋ณ๊ฒฝ๋ ๋ ํด๋ผ์ด์ธํธ์๊ฒ ์๋ฆฌ๋ ์์ผ ์๋ฒ๊ฐ ์์ต๋๋ค.
__ํํฌ ์์ ฏ__
String useUserNickname(Id userid) {
final context = useContext();
final cache = Provider.of<CacheManager>(context);
final notifications = Provider.of<ServiceNotifications>(context);
final name = useState("");
fetchData() async {
name.value = "Loading...";
var cachedValue = cache.get("nicknames");
if (cachedValue == null || cachedValue[widget.userId] == null) {
final result = await fetchNicknames();
cache.set("nicknames", result );
cachedValue = result ;
}
final result = cachedValue[widget.userId];
name.value = result ;
}
useEffect(() {
final sub = notifications.on("nicknameChanges", fetchData);
return () => sub.unsubscribe();
}, [])
useEffect(fetchData, [userId]);
return name.value;
}
class UserNickname extends HookWidget {
final userId;
Widget build(BuildContext context) {
final nickname = useUserNickname(userId);
return Text(nickname);
}
}
__์ํ ์ ์ฅ ์์ ฏ__
class UserNickname extends Widget {
final userId;
// ... createState() ...
}
class UserNicknameState extends State {
String nickname= "";
CacheManager cache;
ServerNotification notifications;
CancelableOperation sub;
initState() {
super.initState();
fetchAndUpdate();
this.cache = Provider.of<CacheManager>(context);
this.notifications = Provider.of<ServerNotification>(context);
this.sub = notifications.on("nicknameChanges", fetchAndUpdate);
}
dispose() {
super.dispose();
this.sub.unsubscribe();
}
fetchAndUpdate() async {
setState(() { this.nickname = "Loading..." });
var cachedValue = this.cache.get("nicknames");
if (cachedValue == null || cachedValue[widget.userId] == null) {
final result = await fetchNicknames();
this.cache.set("nicknames", result );
cachedValue = result ;
}
final result = cachedValue [widget.userId];
setState(() { this.nickname = result });
}
void didUpdateWidget(oldWidget) {
if (oldWidget.userId != widget.userId) {
fetchAndUpdate();
}
}
Widget build(BuildContext context) {
return Text(this.nickname);
}
}
์ง๊ธ๊น์ง ๊ตฌํ์ ๋ชจ๋ ์์ฉ ๊ฐ๋ฅํ๊ณ ์ข์ต๋๋ค. IMO statful์ ์์ฉ๊ตฌ๋ ์ ํ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค. ์ฌ์ฉ์์ ๋๋ค์๊ณผ ์๋ฐํ๊ฐ ๋ชจ๋ ์๋ UserInfo
์ ๊ฐ์ ์์ ฏ์ด ํ์ํ ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค. ๋ํ "Welcome [username]"๊ณผ ๊ฐ์ ๋ฌธ์ฅ์ผ๋ก ํ์ํด์ผ ํ๊ธฐ ๋๋ฌธ์ UserNickname
์์ ฏ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
__ํํฌ ์์ ฏ__
useFetchUserNickname(userId) // old code
useUserAvatar(userId) // implementation like `useFetchUserNickname`
class UserNickname extends HookWidget {
final userId;
Widget build(BuildContext context) {
final nickname = useUserNickname(userId);
final avatar = useUserAvatar(userId);
return Row(
children: [Image.network(avatar), Text(nickname)],
);
}
}
ํ์ง๋ง __stateful ์์ ฏ__์ ๊ฒฝ์ฐ ์ฐ๋ฆฌ๊ฐ ์์ฑํ ๋ก์ง์ ๊ทธ๋๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ก์ง์ ํด๋์ค๋ก ์ด๋ํด์ผ ํ๋ฉฐ(์: Property
) ์ฌ์ ํ ์ ์์ ฏ์์ ์์ฑ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ์์ ฏ ๊ธ๋ฃจ๋ฅผ ๋ค์ ์์ฑํด์ผ ํฉ๋๋ค.
์ฒซ ๋ฒ์งธ 3๊ฐ์ ์์์ ๋ณ๊ฒฝ ์ฌํญ์ ๋ณด๋ฉด ์์ ฏ ์์ฒด๋ฅผ ์ ํ ๋ณ๊ฒฝํ์ง ์์์ต๋๋ค. ํ์ํ ๋ณ๊ฒฝ ์ฌํญ์ ์ํ ๋
ผ๋ฆฌ์๋ง ์๊ณ ๋ณ๊ฒฝ๋ ์ ์ผํ ์์น๋ ๋ชจ๋ ์ํ ๋
ผ๋ฆฌ์๊ธฐ ๋๋ฌธ์
๋๋ค.
์ด๊ฒ์ ์ฐ๋ฆฌ์๊ฒ ์ด๋์์๋ ์ฌ์ฉํ ์ ์๋ ๊นจ๋ํ๊ณ (์๊ฒฌ์ด ์๋) ๊ตฌ์ฑ ๊ฐ๋ฅํ๊ณ ์์ ํ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ํ ๋
ผ๋ฆฌ๋ฅผ ์ ๊ณตํ์ต๋๋ค.
IMHO์ ์ ์ผํ ๋ฌธ์ ๋ useUserNickname
ํธ์ถํ๋ ๊ฒ์ด ๋จ์ผ ํจ์๊ฐ ์ด๋งํผ ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ฌด์ญ๋ค๋ ๊ฒ์
๋๋ค.
๊ทธ๋ฌ๋ ๋ฐ์์ ๋ํ ๊ฒฝํ๊ณผ ํ๋ก๋์
rn(ํํฌ๋ฅผ ๋ง์ด ์ฌ์ฉํ๋)์ ์๋ 2๊ฐ์ ์ฑ์์ flutter_hooks
๋ฅผ ์ฌ์ฉํ ๊ฒฝํ์ ์ข์ ์ํ ๊ด๋ฆฌ๊ฐ ์์์ ์ฆ๋ช
ํฉ๋๋ค(์ ๋ MobX ๋ฐ ๊ธฐํ ์ํ ๊ด๋ฆฌ ์๋ฃจ์
์ ์๋ํ์ง๋ง ์์ ฏ์ ์ ์ฐฉ์ ๋ ํญ์ ์กด์ฌํฉ๋๋ค)๊ฐ ํจ์ฌ ๋ ๋ฌด์ญ์ต๋๋ค. ํ๋ก ํธ์๋ ์ฑ์ ๋ชจ๋ ํ๋ฉด์ ๋ํด 5ํ์ด์ง์ ๋ฌธ์๋ฅผ ์์ฑํ ํ์๊ฐ ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ ๋ฆด๋ฆฌ์ค ์ดํ ๋ช ๋ฌ ์์ ๋ด ์ฑ์ ํ์ด์ง๊ฐ ์ด๋ป๊ฒ ์๋ํ๋์ง ์ดํดํ๊ธฐ ์ํด ๋ช ๊ฐ์ง ์์ ๊ธฐ๋ฅ์ ์ถ๊ฐํด์ผ ํ ์๋ ์์ต๋๋ค. ์ฑ์ด ์๋ฒ๋ฅผ ๋๋ฌด ๋ง์ด ํธ์ถํฉ๋๊น? ์ฌ์ด ์์
๊ด๋ จ ํ
์ผ๋ก ์ด๋ํ์ฌ ๋ณ๊ฒฝํ๋ฉด ์ ์ฒด ์ฑ์ด ํด๋น ํ
์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์ ์ฒด ์ฑ์ด ์์ ๋ฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ข์ ์ถ์ํ๋ฅผ ๊ฐ์ง ํํฌ๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์ฑ์์ ๋น์ทํ ๊ฒ์ ๊ฐ์ง ์ ์์ง๋ง ๋ด๊ฐ ๋งํ๋ ๊ฒ์ ํํฌ๊ฐ ์ข์ ์ถ์ํ๋ผ๋ ๊ฒ์
๋๋ค.
@gaearon ์ด ๋๋ณด๋ค ๋ ์
์์ ์๋ฅผ ๋ณด๋ฉด ์์ ์ด๋ค ๋ฐฉ๋ฒ(์ํ ์ ์ฅ ๋ฐ ํํฌ ์์ ฏ)๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ๋ณด๋ค ์ฑ๋ฅ์ด ์ข์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์์ ์ ๊ทธ ์ค ํ๋๊ฐ ์ฌ๋๋ค์ด ์ฑ๋ฅ์ด ์ข์ ์ฝ๋๋ฅผ ์์ฑํ๋๋ก ๊ถ์ฅํ๋ค๋ ๊ฒ์ ๋๋ค.
๋ํ ๋ค์์ ์ฌ์ฉํ์ฌ ์
๋ฐ์ดํธ(์: ์ ๋๋ฉ์ด์
)๊ฐ ๋๋ฌด ๋ง์ ๊ฒฝ์ฐ StreamBuilder
์ฒ๋ผ ์
๋ฐ์ดํธํด์ผ ํ๋ ํ์ ํธ๋ฆฌ๋ง ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค.
1 - HookWidget
๋ฐ StatefulWidget/StatelessWidget
๋ชจ๋์ ๋ํด ์์ ํ ์คํ ๊ฐ๋ฅํ ์ต์
์ธ ์ ์์ ฏ ๋ง๋ค๊ธฐ
2 - flutter_hooks
ํจํค์ง์์ HookWidgetBuilder
์ ์ ์ฌํ ๊ฒ์ ์ฌ์ฉํฉ๋๋ค. ์์ ๋ฐ ํ์ ์์ ฏ ๋ฐ์ดํฐ๊ฐ ๋งค์ฐ ๋ฐ์ ํ๊ฒ ๊ฒฐํฉ๋์ด ์๊ธฐ ๋๋ฌธ์
๋๋ค.
์ฐธ๊ณ ์ฌํญ: ์ด ์ฃผ์ ์ ๋ํด ๋ ผ์ํ๊ณ ์ด ๋ฌธ์ ์ ๋ง์ ์๋์ง๋ฅผ ์์ @Hixie ์ @rrousselGit ์๊ฒ ์ ๋ง ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์ด ํ๋ด์ ๊ฒฐ๊ณผ๊ฐ ์ ๋ง ๊ธฐ๋๋ฉ๋๋ค.
@Hixie ์ ์์์ ์ ๊ธฐ๋ฐ์ผ๋ก ๊ฝค ๋ฉ์ง๊ณ ์ฐ์ํ ์๊ฐ์ ํ๊ณ ์์ต๋๋ค. ์์ง ๊ณต์ ํ ์ค๋น๊ฐ ๋์ง ์์์ง๋ง ๊ฝค ๊ด์ฐฎ์ ์ฝ๋ ์ํ์ ๋ง๋ค ์ ์๊ฒ ๋์๊ณ , ๋๋ฌด ์ด์ง์ ์ผ๋ก ๋ณด์ด๋ ํํฌ๋ณด๋ค apple:apple ์ ๋น๊ตํ๋ ๊ฒ์ด ๋ ์ฌ์ธ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ ์๋ช ์ด ์๋ StatefulWidget์ด ์๋ค๊ณ ์์ํด ๋ณด์ญ์์ค.
class ExampleSimple extends StatefulWidget {
final Duration duration1;
final Duration duration2;
final Duration duration3;
const ExampleSimple({Key key, this.duration1, this.duration2, this.duration3}) : super(key: key);
<strong i="9">@override</strong>
_ExampleSimpleState createState() => _ExampleSimpleState();
}
๋ฐ๋๋ผ ์ ๋๋ฉ์ดํฐ ์ปจํธ๋กค๋ฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ฅผ ๊ตฌํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ต๋๋ค.
class _ExampleSimpleVanillaState extends State<ExampleSimpleVanilla> with SingleTickerProviderStateMixin {
AnimationController _anim1;
AnimationController _anim2;
AnimationController _anim3;
<strong i="13">@override</strong>
void initState() {
_anim1 = AnimationController(duration: widget.duration1, vsync: this);
_anim1.forward();
_anim2 = AnimationController(duration: widget.duration2, vsync: this);
_anim2.forward();
_anim3 = AnimationController(duration: widget.duration3, vsync: this);
_anim3.forward();
super.initState();
}
<strong i="14">@override</strong>
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(vertical: _anim2.value * 20, horizontal: _anim3.value * 30,),
color: Colors.red.withOpacity(_anim1.value),
);
}
<strong i="15">@override</strong>
void didUpdateWidget(ExampleSimpleVanilla oldWidget) {
if (oldWidget.duration1 != widget.duration1) {
_anim1.duration = widget.duration1;
}
if (oldWidget.duration2 != widget.duration2) {
_anim1.duration = widget.duration1;
}
if (oldWidget.duration3 != widget.duration3) {
_anim1.duration = widget.duration1;
}
super.didUpdateWidget(oldWidget);
}
<strong i="16">@override</strong>
void dispose() {
_anim1.dispose();
_anim2.dispose();
_anim3.dispose();
super.dispose();
}
}
StatefulProperty๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋ฉ๋๋ค.
class _ExampleSimpleState extends State<ExampleSimple> with StatefulPropertyManager {
StatefulAnimationProperty _anim1;
StatefulAnimationProperty _anim2;
StatefulAnimationProperty _anim3;
<strong i="6">@override</strong>
void initStatefulProperties({bool firstRun = false}) {
_anim1 = initProperty(_anim1, StatefulAnimationProperty(duration: widget.duration1, playOnInit: true));
_anim2 = initProperty(_anim2, StatefulAnimationProperty(duration: widget.duration2, playOnInit: true));
_anim3 = initProperty(_anim3, StatefulAnimationProperty(duration: widget.duration3, playOnInit: true));
super.initStatefulProperties(firstRun: firstRun);
}
<strong i="7">@override</strong>
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(vertical: _anim2.controller.value * 20, horizontal: _anim3.controller.value * 30,),
color: Colors.red.withOpacity(_anim1.controller.value),
);
}
}
์ฐจ์ด์ ์ ๋ํ ๋ช ๊ฐ์ง ์ฐธ๊ณ ์ฌํญ:
๋์ StatefulPropertyManager๊ฐ ํ๋ ์ผ์ ์ดํดํด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ฒฐ์ ์ ์ผ๋ก ์ด๊ฒ์ ํ ๋ฒ ๋ฐฐ์ฐ๊ณ ๋ชจ๋ ์ ํ์ ๊ฐ์ฒด์ ์ ์ฉ๋๋ค๋ ์ ์ ๋๋ค. SingleTickerProviderMixin์ ์ฃผ๋ก ์ ๋๋ฉ์ดํฐ ์ปจํธ๋กค๋ฌ ์ฌ์ฉ๊ณผ ๊ด๋ จ์ด ์์ผ๋ฉฐ ๋ชจ๋ ์ปจํธ๋กค๋ฌ์๋ ์ฌ์ฉ์ ๋ ์ฝ๊ฒ ํ๊ธฐ ์ํด ์์ฒด ๋ฏน์ฑ์ด ์์ ์ ์์ผ๋ฏ๋ก ์ง์ ๋ถํด์ง๋๋ค. ์ด ๋ชจ๋ ๊ฒ์ ์๊ณ ์๋ ๋ณ๊ฐ์ "StatefulObjects"๋ฅผ ๊ฐ๋ ๊ฒ(๋น๋๊ฐ ํ๋ ๊ฒ์ฒ๋ผ!)์ ํจ์ฌ ๊นจ๋ํ๊ณ ํ์ฅ์ฑ์ด ์ข์ต๋๋ค.
StatefulAnimationProperty์ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
class StatefulAnimationProperty extends BaseStatefulProperty<StatefulAnimationProperty> implements TickerProvider {
final Duration duration;
final TickerProvider vsync;
final bool playOnInit;
StatefulAnimationProperty({<strong i="7">@required</strong> this.duration, <strong i="8">@required</strong> this.vsync, this.playOnInit = false});
AnimationController get controller => _controller;
AnimationController _controller;
Ticker _ticker;
<strong i="9">@override</strong>
Ticker createTicker(onTick) {
_ticker ??= Ticker((elapsed)=>handleTick(elapsed, onTick));
return _ticker;
}
handleTick(Duration elapsed, TickerCallback onTick) {
managerWidget.buildWidget(); //TODO: This just calls setState() on the host widget. Is there some better way to do this?
onTick(elapsed);
}
<strong i="10">@override</strong>
void init(StatefulAnimationProperty old) {
_controller = old?.controller ??
AnimationController(
duration: duration ?? Duration(seconds: 1),
vsync: vsync ?? this,
);
if (playOnInit && old?.controller == null) {
_controller.forward();
}
super.init(old);
}
<strong i="11">@override</strong>
void update(StatefulAnimationProperty old) {
if (duration != old.duration) {
_controller.duration = duration;
}
if (vsync != old.vsync) {
_controller.resync(vsync);
}
super.update(old);
}
<strong i="12">@override</strong>
void dispose() {
_controller?.dispose();
_ticker?.dispose();
super.dispose();
}
}
๋ง์ง๋ง์ผ๋ก, ํ์ฅ์ ์ฌ์ฉํ๋ฉด ๊ฐ๋ ์ฑ์ ๋์ฑ ๋์ผ ์ ์์ผ๋ฏ๋ก ๋ค์๊ณผ ๊ฐ์ด ๋ง๋ค ์ ์์ต๋๋ค.
void initStatefulProperties({bool firstRun = false}) {
_anim1.init(duration: widget.duration1, playOnInit: true);
_anim2.init(duration: widget.duration2, playOnInit: true);
_anim3.init(duration: widget.duration3, playOnInit: true);
super.initStatefulProperties(firstRun: firstRun);
}
[ํธ์ง] ๋ด ๋ง์ ํ์๋ฉด ๋ด ๋ฐ๋๋ผ ์์ ์๋ ๋ฒ๊ทธ๊ฐ ์์ต๋๋ค. didUpdateWidget์ ๊ฐ ์ ๋๋ฉ์ดํฐ์ ์ฌ๋ฐ๋ฅธ ์ง์ ์๊ฐ์ ์ ๋ฌํ๋ ๊ฒ์ ์์์ต๋๋ค. ์ฝ๋ ๋ฆฌ๋ทฐ์์ ์๋ฌด๋ ๋์น์ฑ์ง ๋ชปํ๋ค๋ฉด ์ผ์์์ ๊ทธ ๋ฒ๊ทธ๋ฅผ ์ฐพ๋ ๋ฐ ์ผ๋ง๋ ๊ฑธ๋ ธ์๊น์? ์ฝ๋ ๋์ ์๋ฌด๋ ๊ทธ๊ฒ์ ๋ฐ๊ฒฌํ์ง ๋ชปํ์ต๋๊น? ๊ทธ๋๋ก ๋๋ ๊ฒ์ ํ์ค ์ธ๊ณ์์ ์ผ์ด๋๋ ์ผ์ ๋ํ ์๋ฒฝํ ์์ ๋๋ค.
๋ค์์ ๋นจ๊ฐ์์ผ๋ก ํ์๋ ์์ฉ๊ตฌ์ ํจ๊ป ์กฐ๊ฐ๋์
๋๋ค.
์ด๊ฒ์ ์์ํ ์์ฉ๊ตฌ๋ผ๋ฉด ๊ทธ๋ ๊ฒ ๋์์ง ์์ ๊ฒ์ด๊ณ ์ปดํ์ผ๋ฌ๋ ๊ทธ๊ฒ์ด ์์ผ๋ฉด ๋น์ ์๊ฒ ์๋ฆฌ๋ฅผ ์ง๋ ์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ๋ชจ๋ ์ ํ ์ฌํญ์ ๋๋ค! ๊ทธ๋ฆฌ๊ณ ์๋ตํ๋ฉด ๋ฒ๊ทธ๊ฐ ์์ฑ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์ด๊ฒ์ ์ค์ ๋ก ๋งค์ฐ ๋์ ์ต๊ด์ด๋ฉฐ DRY๊ฐ ์๋๋๋ค. ์ด๊ฒ์ ๋น๋๊ฐ ๋ค์ด์ค๋ ๊ณณ์ด์ง๋ง ๋จ์ํ ์ฌ์ฉ ์ฌ๋ก์๋ง ์ ํฉํฉ๋๋ค.
์ด๊ฒ์ ๋ํด ๋งค์ฐ ํฅ๋ฏธ๋กญ๊ฒ ์๊ฐํ๋ ๊ฒ์ 100๊ฐ์ ๋ผ์ธ๊ณผ State์ ๋ํ ๊ฐ๋จํ ๋ฏน์ค์ธ์ด ๊ธฐ์กด ํด๋์ค๋ฅผ ์ค๋ณต๋๊ฒ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด ์ด์ TickerProviderMixins๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ๊ฑฐ์ ์์ต๋๋ค. TweenAnimationBuilder๋ ์ค์ ๋ก ํ์ ์ปจํ ์คํธ๋ฅผ _์ํ์ง_ ์๋ ํ ๊ฑฐ์ ์ฌ์ฉํ ํ์๊ฐ ์์ต๋๋ค. ํฌ์ปค์ค ์ปจํธ๋กค๋ฌ ๋ฐ textInput ์ปจํธ๋กค๋ฌ ๊ด๋ฆฌ์ ๊ฐ์ ๊ธฐ์กด์ ๋ง์ ๋ฌธ์ ์ ์ด ์๋นํ ์ํ๋์์ต๋๋ค. Streams๋ฅผ ์ฌ์ฉํ๋ฉด ํจ์ฌ ๋ ๋งค๋ ฅ์ ์ด๊ณ ๋ ๋ณต์กํด์ง๋๋ค. ์ฝ๋ ๊ธฐ๋ฐ ์ ์ฒด์์ Builders์ ์ฌ์ฉ์ ์ผ๋ฐ์ ์ผ๋ก ์ค์ด๋ค์ด ๋ ์ฝ๊ฒ grokable ํธ๋ฆฌ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
๋ํ ์ด์ ์ ๋์ด๋ FetchUser ์์ ์ ๊ฐ์ด ํ์ฌ ๊ธฐ๋ณธ์ ์ผ๋ก ๋น๋๊ฐ ํ์ํ ์ฌ์ฉ์ ์ ์ ์ํ ๊ฐ์ฒด๋ฅผ _๋งค์ฐ_ ์ฝ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
๋ค์ Flutter ๊ฐ๋ฐ์ ์ค๋ฌธ์กฐ์ฌ์์ ์ด๊ฒ์ด ๋งค์ฐ ํฅ๋ฏธ๋ก์ด ์ง๋ฌธ์ด ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
์ข์ ์์์ด ๋ ๊ฒ์ ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ๋ค๋ฅธ ๋ถ๋ถ/์ง๋ฌธ์ผ๋ก ๋๋๊ณ ์ด๊ฒ์ด Flutter ๊ฐ๋ฐ์๊ฐ ํด๊ฒฐํ๊ณ ์ ํ๋ ์ค์ ๋ฌธ์ ์ธ์ง ํ์ธํ์ญ์์ค.
๋ช ํํด์ง๋ฉด ์ด ๋ํ๊ฐ ๋ ์ ์ฐฝํ๊ณ ํ๋ถํด์ง ๊ฒ์ ๋๋ค.
๊ฐ ๋๊ธ ์๋์ ์ด๋ชจํฐ์ฝ ๋ฐ์์ ์ปค๋ฎค๋ํฐ๊ฐ ์ด๋ฅผ ๋ฌธ์ ๋ก ๋ณด๋์ง ์ฌ๋ถ์ ๋ํ ๋ช ํํ ์์ด๋์ด๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ๋ฌธ์ ์ ๋ํด 250๊ฐ ์ด์์ ๊ธด ๋๊ธ์ ์ฝ์ ๊ฐ๋ฐ์์ ์๊ฒฌ์ ๋ง์ ์๋ฏธ๊ฐ ์์ต๋๋ค.
@esDotDev ๊ทธ๊ฒ์ ๋ด๊ฐ ๊ฐ์ง๊ณ ๋ค์ง๋ง ๋๋ ๊ทธ๊ฒ์ ๊ณ ๋ คํ์ง ์์์ต๋๋ค. ๊ตฌํ์์ ๋๋ฝ๋ ํ ๊ฐ์ง๋ ์ถ๊ฐํด์ผ ํ๋ค๊ณ ์๊ฐํ๋ TickerMode(TickerProviderStateMixin์ ์์ ) ์ฒ๋ฆฌ์ ๋๋ค.
๋ด๊ฐ ๊ณ ๊ตฐ๋ถํฌํ๋ ์ฃผ์ ๋ฌธ์ ๋ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ์ด ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ValueListenableBuilder๋ ์ฑ๋ฅ์ ์ธก์ ๊ฐ๋ฅํ๊ฒ ๊ฐ์ ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ์์ ์ธ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. Property ์ ๊ทผ ๋ฐฉ์์ผ๋ก ๊ทธ๋ ๊ฒ ํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
@Hixie
์ด์ ๊ฐ์ ์ ๊ทผ ๋ฐฉ์์ ํจ์จ์ฑ ์์ค์ ๋ถ๊ฐํผํ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค. ํ์ง๋ง ์ ๋ ์ฝ๋๋ฅผ ํ๋กํ์ผ๋งํ ํ ์ต์ ํํ๋ ค๋ Flutter์ ์ฌ๊ณ ๋ฐฉ์์ ์ข์ํฉ๋๋ค. Property ์ ๊ทผ ๋ฐฉ์์ ๋ช
ํ์ฑ๊ณผ ๊ฐ๊ฒฐํจ์ ์ด์ ์ ์ป์ ์ ์๋ ์์ฉ ํ๋ก๊ทธ๋จ์ด ๋ง์ด ์์ต๋๋ค. ์ฝ๋๋ฅผ ํ๋กํ์ผ๋งํ๊ณ ๋น๋๋ก ๋ฆฌํฉํฐ๋งํ๊ฑฐ๋ ์์ ฏ์ ์ผ๋ถ๋ฅผ ์์ฒด ์์ ฏ์ผ๋ก ๋ถ๋ฆฌํ๋ ์ต์
์ด ํญ์ ์์ต๋๋ค.
๋ฌธ์๋ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ์ํ๊ณ ์ฅ๋จ์ ์ ๋ช ํํ ํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
๋ด๊ฐ ๊ณ ๊ตฐ๋ถํฌํ๋ ์ฃผ์ ๋ฌธ์ ๋ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ์ด ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ValueListenableBuilder๋ ์ฑ๋ฅ์ ์ธก์ ๊ฐ๋ฅํ๊ฒ ๊ฐ์ ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ์์ ์ธ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. Property ์ ๊ทผ ๋ฐฉ์์ผ๋ก ๊ทธ๋ ๊ฒ ํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
ํ , ์์ฑ์ ์ ์ฒด ์์ ์ ๋น์๊ฐ์ ๊ฐ์ฒด์ ๋ํ ๊ฒ์ ๋๋ค. ๋ญ๊ฐ๊ฐ ํธ๋ฆฌ์ ์ปจํ ์คํธ ์ฌ๋กฏ์ ๊ฐ๊ณ ์ถ๋ค๋ฉด ๊ทธ ๊ฒ์ ๋น๋์ฌ์ผ ํฉ๋๋ค(์ฌ์ค ์ด๊ฒ๋ค์ด ์ง๊ธ ๋น๋์ฌ์ผ ํ๋ค๊ณ ์๊ฐํ๋ ์ ์ผํ ๊ฒ์ ๋๊น?)
๋ฐ๋ผ์ ์ ์ฒด ๋ทฐ๋ฅผ ๋ฐ์ธ๋ฉํ๋ ค๋ ๊ฒฝ์ฐ ๋๋ถ๋ถ ์ฌ์ฉํ๋ StatefulValueListenableProperty๊ฐ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ํธ๋ฆฌ์ ์ผ๋ถ ํ์ ์น์ ์ด ๋ค์ ์์ฑ๋๊ธฐ๋ฅผ ์ํ๋ ๊ฒฝ์ฐ ValueListenableBuilder๋ ์์ต๋๋ค.
์ด๊ฒ์ ๋ํ ๋น๋๋ฅผ ๋ฆฌํ ๋ ธ๋๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ์์ ฏ ํธ๋ฆฌ ์๋จ์ 2 ๋๋ 3์ ์ค์ฒฉํ๋ ๊ฒ๋งํผ ๊ฐ๋ ์ฑ์ ์ง์ฅ์ ์ฃผ์ง ์๊ธฐ ๋๋ฌธ์ ์ค์ฒฉ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค.
@TimWhiting Flutter์ ๋์์ธ ์ฒ ํ์ ํฐ ๋ถ๋ถ์ ์ฌ๋๋ค์ด ์ฌ๋ฐ๋ฅธ ์ ํ์ ํ๋๋ก ์๋ดํ๋ ๊ฒ์ ๋๋ค. ๋๋ ์ฌ๋๋ค์ด ๋ ๋์ ์ฑ๊ณผ๋ฅผ ์ป๊ธฐ ์ํด ๋ฉ๋ฆฌ ๋ ๋์ผ ํ๋ ์คํ์ผ์ ๋ฐ๋ฅด๋๋ก ๋ถ์ถ๊ธฐ๋ ๊ฒ์ ํผํ๊ณ ์ถ์ต๋๋ค. ๋ชจ๋ ์๊ตฌ ์ฌํญ์ ํ ๋ฒ์ ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ ์๋ ์์ง๋ง ํ์คํ ์๋ํด ๋ด์ผ ํฉ๋๋ค.
@Hixie
๊ฑด์ถ์
์์๊ฒ ์ด์ ๊ฐ์ ๊ฒ์ ์ด๋ป์ต๋๊น?
class _ExampleSimpleState extends State<ExampleSimple> with StatefulPropertyManager {
StatefulAnimationProperty _anim1;
StatefulAnimationBuilderProperty _anim2;
<strong i="7">@override</strong>
void initStatefulProperties({bool firstRun = false}) {
_anim1 = initProperty(_anim1, StatefulAnimationProperty(duration: widget.duration1, playOnInit: true));
_anim2 = initProperty(_anim3, StatefulAnimationBuilderProperty(duration: widget.duration3, playOnInit: true));
super.initStatefulProperties(firstRun: firstRun);
}
<strong i="8">@override</strong>
Widget build(BuildContext context) {
return Container(
color: Colors.red.withOpacity(_anim1.controller.value),
child: _anim2(child: SomeChildWidget()),
);
}
}
์์ธํ ์๋ ค์ฃผ์ค ์ ์๋์? ์ ์์ ์ดํดํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๊ทธ๋ StatefulProperty๊ฐ ์๊ฐ์ ๊ตฌ์ฑ ์์๊ฐ ์๋ ์์ฑ์ ๋ํ ์ ํ์ ๋น๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ ์ ์๋ค๊ณ ๋งํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
return Column(
children: [
TopContent(),
_valueProperty.build(SomeChildWidget()),
]
)
๊ฝค ๐ฅ ์ด๋ชจ,
์, ์๋ํ๋์ง ๋ชจ๋ฅด๊ฒ ์ง๋ง ๋น๋์ ๋ค๋ฅธ ์์ฑ์ด ์์ฑ์ ์ํด ์ค์ ๋๋ค๋ ์ ์ ์ ์ธํ๊ณ ๋น๋ ๋ฉ์๋๋ ์ผ๋ฐ ๋น๋์ ๋ง์ฐฌ๊ฐ์ง๋ก ์์์ ์ฌ์ฉํฉ๋๋ค.
๋น๋์ ์ปจํ
์คํธ๊ฐ ํ์ํ ๊ฒฝ์ฐ ๋น๋ ๋ฉ์๋๋ ์ปจํ
์คํธ๋ฅผ ์ ๊ณตํ๋ ๋น๋ ์ธ์๋ฅผ ํ์ฉํฉ๋๋ค.
๋ด๋ถ์ ์ผ๋ก ๋ฉ์๋๋ ์ง์ ๋ ์์ฑ์ ์ฌ์ฉํ์ฌ ์ผ๋ฐ ๋น๋๋ฅผ ๋ง๋ค๊ณ ์์ ์ธ์๋ฅผ ์ผ๋ฐ ๋น๋์ ์ ๋ฌํ๊ณ ์ด๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
๋ค์ ์ฝ๋๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
Widget build(BuildContext context) {
return ExpensiveParent(
child: ValueListenableBuilder(
valueListenable: foo,
child: ExpensiveChild(),
builder: (BuildContext context, value, Widget child) {
return SomethingInTheMiddle(
value: value,
child: child,
);
}
),
);
}
...๊ทธ๊ฒ์ ์ด๋ป๊ฒ ๋ณํํ์๊ฒ ์ต๋๊น?
@esDotDev ์์ฑ ์์ฒด๊ฐ ์์ธ ๊ณต๊ธ์๊ฐ ๋๋ ๋น์ ์ ์์ด๋์ด๊ฐ ๋ง์์
์ด ํํฌ ์คํ์ผ ์ ๊ทผ ๋ฐฉ์์ ๊ฐ์ฅ ๊ฐ๋ ฅํ ์ธก๋ฉด ์ค ํ๋๋ ์ํ ์ ์ฅ ๋ ผ๋ฆฌ๋ฅผ _์์ ํ_ ์บก์ํํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ฐ๋ผ์ ์ด ๊ฒฝ์ฐ AC์ ์ ์ฒด ๋ชฉ๋ก์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
ํ์ฌ 1,3,4๋ฅผ ์๋์ผ๋ก ๋ฐ๋ณต์ ์ผ๋ก ์ฒ๋ฆฌํ๋(๋๋ ์ฒ๋ฆฌํ์ง ์๋) ๊ฐ๋ฐ์์ 2์ โโ5๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ๋ง๋ฒ์ SingleTickerProviderMixin('์ด๊ฒ'์ vsync๋ก ์ ๋ฌํ์ฌ ๋ช ๋ฌ ๋์ ๋๋ฅผ ํผ๋์ค๋ฝ๊ฒ ํ์ต๋๋ค! ). ๊ทธ๋ฆฌ๊ณ SingleTickerProviderMixin ์์ฒด๋ ๋ถ๋ช ํ ์ด๋ฌํ ์ ํ์ ๋ฌธ์ ์ ๋ํ ์์ ์๋์ ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋ชจ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ฌ ๊ฐ ํด๋์ค์ ๋ํด TickerProvider๋ฅผ ๊ตฌํํ๋๋ก ํ๋ ๊ฒ์ด ํจ์ฌ ๋ ๋ช ํํ ๊ฒ์ ๋๋ค.
๋ค์ ์ฝ๋๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
Widget build(BuildContext context) { return ExpensiveParent( child: ValueListenableBuilder( valueListenable: foo, child: ExpensiveChild(), builder: (BuildContext context, value, Widget child) { return SomethingInTheMiddle( value: value, child: child, ); } ), ); }
...๊ทธ๊ฒ์ ์ด๋ป๊ฒ ๋ณํํ์๊ฒ ์ต๋๊น?
class _ExampleSimpleState extends State<ExampleSimple> with StatefulPropertyManager {
StatefulValueListenableBuilder _fooBuilder;
<strong i="10">@override</strong>
void initStatefulProperties({bool firstRun = false}) {
_fooBuilder = initProperty(StatefulValueListenableProperty(valueListenable: widget.foo));
super.initStatefulProperties(firstRun: firstRun);
}
<strong i="11">@override</strong>
Widget build(BuildContext context) {
return ExpensiveParent(
child: SomethingInTheMiddle(
_fooBuilder.value,
_fooBuilder.builder(childBuilder: () => ExpensiveChild()),
),
);
}
}
@Hixie
์๋ฅผ ๋ค์ด ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค. ์ต์ ์ ๋คํ์ต๋๋ค. ๋ด๊ฐ ๋ญ๊ฐ๋ฅผ ๋์ณค์ ์๋ ์์ต๋๋ค.
๋น๋๊ฐ ์์์ ์บ์ํ๋ค๋ ์ ์ ์ ์ํด์ผ ํฉ๋๋ค. ๋ฌธ์ ๋ ์ธ์ ์ค์ ๋ก ์์ด๋ฅผ ์ฌ๊ฑดํด์ผ ํ๋๋๋ ๊ฒ์ ๋๋ค. ์ ๊ธฐํ๋ ค๊ณ ํ๋ ์ง๋ฌธ์ด์๋ ๊ฒ ๊ฐ์๋ฐ..
@Hixie ๋ณด์
จ๋์ https://github.com/flutter/flutter/issues/51752#issuecomment -671104377
์ ๋ง ์ข์ ์ ๋ ์๋ ๊ฒ ๊ฐ์์.
์ ๋ ์ค๋ ValueListenableBuilder๋ฅผ ๋ง์ด ์ฌ์ฉํ์ฌ ๋ฌด์ธ๊ฐ๋ฅผ ๊ตฌ์ถํ๊ณ ์์ผ๋ฉฐ ์ฝ๊ธฐ์ ์ข์ง ์๋ค๊ณ ๋งํ ์ ์์ต๋๋ค.
@Hixie
์๋ฅผ ๋ค์ด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์ต์ ์ ๋คํ์ต๋๋ค. ๋ด๊ฐ ๋ญ๊ฐ๋ฅผ ๋์ณค์ ์๋ ์์ต๋๋ค.
Property๊ฐ ์ ์๋ ์ํ์ ๋ฐ์ธ๋ฉ๋๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ด ์๋ํ์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ฐ๋ผ์ ExpensiveParent๋ ํญ์ ์ฌ๊ธฐ์์ ๋ค์ ์์ฑ๋ฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ Builder ์์ ์์์ ๊ฐ์ด ์์์ ์บ์ฑ๋ ๋ฌธ์ ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ถ๋ชจ ์ํ๊ฐ ๋น๋๋ ๋๋ง ์์์ ๋ค์ ๋น๋ํ๋ ๊ฒ์ผ๋ก ์๊ณ ์์ง๋ง ์ด ๋ฐฉ๋ฒ์์๋ ์์ฑ์ด ์บ์๋ฅผ ๋ฌดํจํํ ๋๋ฅผ ์์ง ๋ชปํฉ๋๋ค(ํ์ง๋ง ์๋ง๋ ์ด ํด๊ฒฐ ๊ฐ๋ฅํ๊ฐ์?)
๊ทธ๋ฌ๋ ์ด๊ฒ์ ์๋ก์ด ์ปจํ ์คํธ๋ฅผ ๋์ ํ๋ ค๋ ๋น๋์๊ฒ ์๋ฒฝํ ์ฌ์ฉ ์ฌ๋ก์ ๋๋ค. StatefulProperties(์์ ์ํ) ๋ฐ StatefulWidget(์ํ ๋ฐ ๋ ์ด์์ ํผํฉ)์ ์ปจํ ์คํธ๋ฅผ ๊ฐ๋ ๊ฒ์ด ๋งค์ฐ ์ฐ์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
์๋์ ์ผ๋ก ํ์ ์ปจํ ์คํธ๋ฅผ ์์ฑํ ๋๋ง๋ค ์ ์์ ๋ฐ๋ผ ํธ๋ฆฌ ์๋์์ ๋ ๋ฉ๋ฆฌ ์ํํ๊ฒ ๋๋ฏ๋ก ๋น๋์ ์ฃผ์ ๋จ์ ์ค ํ๋(์ ์ฒด ํธ๋ฆฌ์ ๊ฐ์ ์ค์ฒฉ)๋ฅผ ๋ฐฉ์งํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
@escamoteur (๊ทธ๋ฆฌ๊ณ ๊ทธ ์๊ฒฌ์ ์์ฑํ @sahandevs ) ์, ์ ๋ ๋ ์ผ์ฐ ๊ณต๋ถํ๊ณ ์์์ต๋๋ค. ์ฌ๋๋ค์ด ์์ ๊ณ ์ถ์ดํ๋ ๊ทธ๋ฐ ๋ ผ๋ฆฌ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ฐ ํ์คํ ๋์์ด ๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ํ์ง๋ง ๋๋ถ๋ถ์ ๋ ผ๋ฆฌ(์: ์บ์ฑ๊ณผ ๊ด๋ จ๋ ๋ชจ๋ ๊ฒ)๊ฐ ์ฑ ์ํ ๋น์ฆ๋์ค ๋ ผ๋ฆฌ์ ์๊ณ ์์ ฏ ๊ทผ์ฒ์๋ ์์ ๊ฒ์ผ๋ก ์์ํ๋ค๋ ์ ์์ ์์ ์์ฒด๊ฐ ์ฝ๊ฐ ๋ชจํธํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ํ ํซ ๋ฆฌ๋ก๋๋ฅผ ์ค๋จํ์ง ์๊ณ ํด๋น ์ฃผ์์์ ์ ์๋ ๋๋ก ๊ตฌ๋ฌธ์ ๊ฐ๋ตํ๊ฒ ๋ง๋๋ ์ข์ ๋ฐฉ๋ฒ์ ๋ณผ ์ ์์ต๋๋ค(์: ์ฌ์ฉ ์ค์ธ ํํฌ ์๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒฝ์ฐ ๋ค์ ๋ก๋ ๋์ ์ํ๋ฅผ ์ ์งํ ์ ์๋ ๋ฐฉ๋ฒ์ด ๋ช ํํ์ง ์์ต๋๋ค. ).
์ฆ, ์์ @esDotDev ๋ฐ @TimWhiting ์์ ์ด ๋งค์ฐ ํฅ๋ฏธ๋กญ๊ณ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. Hooks๋งํผ ์งง์ง๋ ์์ง๋ง ๋ ์์ ์ ์ ๋๋ค. ๊ทธ๋ฐ ๊ฒ์ ํฌ์ฅํ๋ ๊ฒ์ด ์๋ฒฝํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ ์๋ํ๋ค๋ฉด Flutter Favorite๋ ๋ ์ ์์ต๋๋ค. ๊ฑด๋ฌผ ์์ฑ๊ณผ ์ฑ๋ฅ ์ํฅ์ ๋ํ ๋ณต์ก์ฑ๊ณผ ๋ค์ํ ์ฌ๋๋ค์ด ๋ค์ํ ์คํ์ผ์ ์ ํธํ๋ ๋ฐฉ์์ ๊ณ ๋ คํ๋ฉด ๊ฐ์ ์ด ๊ทธ๋ค์ง ์ค์ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ด ํต์ฌ ํ๋ ์์ํฌ ๊ธฐ๋ฅ์ผ๋ก ์๋ฏธ๊ฐ ์๋์ง ํ์ ํ ์ ์์ต๋๋ค. ๊ฒฐ๊ตญ ๋ค๋ฅธ ์ฌ๋๋ค์ด ๋ค๋ฅธ ์คํ์ผ์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ด์ฐฎ์ง๋ง ํต์ฌ ํ๋ ์์ํฌ์ ์ฌ๋ฌ ์คํ์ผ์ด ์๋ ๊ฒ์ ์ํ์ง ์์ต๋๋ค. ์ด๋ ์๋ก์ด ๊ฐ๋ฐ์๋ฅผ ์ค๋ํ ๋ฟ์ ๋๋ค.
Flutter๋ฅผ ๋ฐฐ์ฐ๋ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ ๋จผ์ ์์ ฏ์ ์ดํดํ ๋ค์ ์ถ์ ๊ตฌ๋ฌธ์ผ๋ก ๋ฐ๋ก ๊ฑด๋๋ฐ๊ธฐ ๋ณด๋ค๋ ์์ ฏ์ ์ถ์ํํ๋ ๋๊ตฌ(Hook ๋๋ ๊ธฐํ)๋ฅผ ๋ฐฐ์ฐ๋ ๊ฒ์ด๋ผ๋ ์ฃผ์ฅ๋ ์์ต๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์์คํ ์๋ ๋ฐฉ์์ ํต์ฌ ๊ตฌ์ฑ ์์๋ฅผ ๋์น๊ฒ ๋์ด ์ฑ๋ฅ์ด ์ข์ ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ต๋๋ค.
๋ํ ํซ ๋ฆฌ๋ก๋๋ฅผ ์ค๋จํ์ง ์๊ณ ํด๋น ์ฃผ์์์ ์ ์๋ ๋๋ก ๊ตฌ๋ฌธ์ ๊ฐ๋ตํ๊ฒ ๋ง๋๋ ์ข์ ๋ฐฉ๋ฒ์ ๋ณผ ์ ์์ต๋๋ค(์: ์ฌ์ฉ ์ค์ธ ํํฌ ์๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒฝ์ฐ ๋ค์ ๋ก๋ ๋์ ์ํ๋ฅผ ์ ์งํ ์ ์๋ ๋ฐฉ๋ฒ์ด ๋ช ํํ์ง ์์ต๋๋ค. ).
ํํฌ๋ ๋ฌธ์ ์์ด ํซ ๋ฆฌ๋ก๋์ ํจ๊ป ์๋ํฉ๋๋ค.
์ผ์นํ์ง ์๋ runtimeType์ด ์๋ ์ฒซ ๋ฒ์งธ ํํฌ๋ ๋ชจ๋ ํ์ ํํฌ๋ฅผ ํ๊ดดํฉ๋๋ค.
์ด๊ฒ์ ์ถ๊ฐ, ์ ๊ฑฐ ๋ฐ ์ฌ์ ๋ ฌ์ ์ง์ํฉ๋๋ค.
ํ์ฌ ์กด์ฌํ๋ ๋ถ๋ถ๋ณด๋ค ์์ ํ ์ถ์ํ๊ฐ ๋ฐ๋์งํ๋ค๋ ์ฃผ์ฅ์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์์ฑ์ ์ปจํ ์คํธ์์ Animator๊ฐ ์ด๋ป๊ฒ ์๋ํ๋์ง ์ดํดํ๊ณ ์ถ๋ค๋ฉด ์์ ํ ๋ฌด์ํ๊ฑฐ๋ ๋ฐ์ด๋ค๋ฉด ๋ฉ๋๋ค.
AnimatorController๊ฐ StatefulWidget์ ์ปจํ ์คํธ์์ ์๋ํ๋ ๋ฐฉ์์ ์ดํดํ๋ ค๋ฉด ๊ธฐ๋ณธ ์๋ช ์ฃผ๊ธฐ ํํฌ๋ฅผ ์ดํดํด์ผ ํ์ง๋ง ๊ธฐ๋ณธ ํฑ ๋ฉ์ปค๋์ฆ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ์ดํดํด์ผ ํฉ๋๋ค. ์ด๊ฒ์ ์ด๋ค ์๋ฏธ์์ ๋ ์ธ๊ณ ๋ชจ๋์์ ์ต์ ์ ๋๋ค. '๊ทธ๋ฅ ์๋'ํ๊ฒ ๋ง๋๋ ๋ง๋ฒ์ ์ถฉ๋ถํ์ง ์์ง๋ง ์๋ก์ด ์ฌ์ฉ์๋ฅผ ํผ๋์ค๋ฝ๊ฒ ๋ง๋ค๊ณ ์ผ๋ถ mixin(๊ทธ ์์ฒด๊ฐ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์๋ก์ด ๊ฐ๋ ์)๊ณผ ๋ง๋ฒ์ vsync ์์ฑ์ ๋งน๋ชฉ์ ์ผ๋ก ์ ๋ขฐํ๋๋ก ํ๊ธฐ์๋ ์ถฉ๋ถํฉ๋๋ค.
์ฝ๋ ๊ธฐ๋ฐ์ ๋ค๋ฅธ ์์ ๋ ์ ๋ชจ๋ฅด๊ฒ ์ง๋ง StatefulWidget์ ๋ํด ์ผ๋ถ ๋์ฐ๋ฏธ ๋ฏน์ค์ธ์ด ์ ๊ณต๋์์ง๋ง ํญ์ ์ํํด์ผ ํ๋ ๋ค๋ฅธ ๋ถํธ์คํธ๋ฉ์ด ์๋ ๋ชจ๋ ์ํฉ์ ์ ์ฉ๋ฉ๋๋ค. ๊ฐ๋ฐ์๋ ๋ถํธ์คํธ๋ํ(์ง๋ฃจํ ๋ถ๋ถ)์ ๋ฐฐ์ฐ๊ณ Mixin(ํฅ๋ฏธ๋ก์ด/๋ณต์กํ ๋ถ๋ถ)์ ๋ฌด์ํฉ๋๋ค.
์ฆ, ์์ @esDotDev ๋ฐ @TimWhiting ์์ ์ด ๋งค์ฐ ํฅ๋ฏธ๋กญ๊ณ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. Hooks๋งํผ ์งง์ง๋ ์์ง๋ง ๋ ์์ ์ ์ ๋๋ค.
์ด๊ฒ์ด ์ด๋ป๊ฒ ๋ ์ ๋ขฐํ ์ ์์ต๋๊น?
์กฐ๊ฑด๋ถ๋ก ๋๋ ์๋ช
์ฃผ๊ธฐ ์ธ๋ถ์์ ์์ฑ์ ์์ฑ/์
๋ฐ์ดํธํ ์ ์์ต๋๋ค. ๋์ ์ํ๊ฐ ๋ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์๋ฅผ ๋ค์ด ์์ฑ์ ์กฐ๊ฑด๋ถ๋ก ํธ์ถํ๋ฉด ์กฐ๊ฑด์ด false์ธ ๊ฒฝ์ฐ ์์ฑ์ด ์ญ์ ๋์ง ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ชจ๋ ์์ฑ์ ๋ชจ๋ ์ฌ๊ตฌ์ถ์์ ์ฌ์ ํ ์ฌํ๊ฐ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ ์ฌ์ฉ์๊ฐ NNBD ์ดํ ๋ชจ๋ ๊ณณ์์ !
๋ฅผ ์ฌ์ฉํ๋๋ก ํ๊ฑฐ๋ ์
๋ฐ์ดํธ ์ ์ ์ฌ์ฉ์๊ฐ ์์ฑ์ ์ก์ธ์คํ ์ ์๋๋ก ํ๋ ๋ฑ ์ฌ๋ฌ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
์๋ฅผ ๋ค์ด ๋๊ตฐ๊ฐ didUpdateWidget
๋ด๋ถ์ ์์ฑ์ ์ฝ๋๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
initProperties
๊ฐ ์๋ช
์ฃผ๊ธฐ ์ ์ ์คํ๋์์ต๋๊น? ๊ทธ๋ฌ๋ ์ด๋ ๋น๋๋น ์์ฑ์ ์ฌ๋ฌ ๋ฒ ์
๋ฐ์ดํธํด์ผ ํ ์๋ ์์์ ์๋ฏธํฉ๋๋ค.initProperties
๊ฐ ์คํ๋์์ต๋๊น? ๊ทธ๋ฐ ๋ค์ didUpdateWidget ๋ด๋ถ์ ์์ฑ์ ์ฌ์ฉํ๋ฉด ์ค๋๋ ์ํ๊ฐ ๋ ์ ์์ต๋๋ค.๊ฒฐ๊ตญ, ์ฐ๋ฆฌ๋ ๋ชจ๋ ํํฌ ๋ฌธ์ ๋ฅผ ๊ฐ์ง๊ณ ์์ง๋ง:
๊ฒฐ๊ตญ, ์ฃผ์ด์ง ์๋ ๋ค์๊ณผ ํ๋์ด ๋ค๋ฅด์ง ์์ต๋๋ค.
class Example extends StatelessWidget {
<strong i="29">@override</strong>
Widget build(context) {
final value1 = keyword TweenAnimationBuilder(tween: Tween(begin: 0, end: 1));
final value2 = keyword TweenAnimationBuilder(tween: Tween(begin: 0, end: 1));
final value3 = keyword TweenAnimationBuilder(tween: Tween(begin: 0, end: 1));
return Container(
margin: EdgeInsets.symmetric(vertical: value2 * 20, horizontal: value3 * 30),
color: Colors.red.withOpacity(value1),
child: _anim2(child: SomeChildWidget()),
);
}
}
๊ทธ๋ฌ๋ ์ด ๊ตฌ๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ ํจ์ฌ ๋ ๋ง์ ๊ฒ์ ์ง์ํฉ๋๋ค.
class Example extends StatelessWidget {
<strong i="34">@override</strong>
Widget build(context) {
final value1 = keyword TweenAnimationBuilder(tween: Tween(begin: 0, end: 1));
if (condition) {
return Container();
}
final value2 = keyword TweenAnimationBuilder(tween: Tween(begin: 0, end: 1));
...
}
}
ํ๊ธฐ ๊ฒ์ด๋ค value2
๊ฒฝ์ฐ condition
๊ฑฐ์ง์ผ๋ก ์ ํ
Widget build(context) {
final foo = keyword FooBuilder();
final bar = keyword BarBuilder();
return Text('$foo $bar');
}
๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
Builder<String> LabelBuilder() builder* {
final foo = keyword FooBuilder();
final bar = keyword BarBuilder();
return '$foo $bar';
}
Widget build(context) {
final label = keyword LabelBuilder();
return Text(label);
}
child
๋งค๊ฐ๋ณ์๋ ์ฌ์ ํ ๊ฐ๋ฅํฉ๋๋ค.
Widget build(context) {
final value = keyword StreamBuilder();
return Builder(
builder: (context, child) {
final value2 = keyword TweenAnimationBuilder();
final value = keyword ValueListenableBuilder();
return Whatever(child: child);
},
child: ExpensiveChild()
);
}
์ธ์ด์ ์ผ๋ถ๋ก ๋ค์๊ณผ ๊ฐ์ ๊ตฌ๋ฌธ ์คํ์ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
Widget build(context) {
return Scaffold(
body: {
final value = keyword TweenAnimationBuilder();
final value2 = keyword ValueListenableBuilder();
return Text();
},
);
}
์ธ์ด์ ์ผ๋ถ๋ก ๋ค์๊ณผ ๊ฐ์ ์๋๋ฆฌ์ค๋ฅผ ์ง์ํ ์ ์์ต๋๋ค.
Widget build(context) {
String label;
if (condition) {
label = keyword LabelBuilder();
} else {
label = keyword AnotherBuilder();
}
final value2 = keyword WhateverBuilder();
return ...
}
๊ทธ๋ค์ง ์ ์ฉํ์ง๋ ์์ง๋ง ์ง์๋ฉ๋๋ค. ๊ตฌ๋ฌธ์ด ์ปดํ์ผ๋๊ธฐ ๋๋ฌธ์ ๋ฌ๋ฆฌ ์ฌ์ฉํ ์ ์๋ ๋ฉํ๋ฐ์ดํฐ์ ์์กดํ์ฌ keyword
์ ๊ฐ ์ฌ์ฉ๋ฒ์ ๊ตฌ๋ณํ ์ ์์ต๋๋ค.
๋น๋์ ๊ฐ๋ ์ฑ๊ณผ ๊ด๋ จํ์ฌ ๋ค์์ ์ด์ ์์ ์ด์ง๋ง ๋น๋๋ก ์ํ๋ฉ๋๋ค. ๊ทธ๊ฒ์ ๋ชจ๋ ์์ ์ฑ๊ณผ ์ฝ๋ ์ฌ์ฉ ์๊ตฌ๋ฅผ ํด๊ฒฐํ์ง๋ง, ๋ด ํํธ์๋ ์์ ฏ ํธ๋ฆฌ์ ์ด๋ค ์ํฅ์ ๋ฏธ์ณค๋์ง ์ดํด๋ณด์ธ์.'(
class _ExampleSimpleBuilderState extends State<ExampleSimpleBuilder> {
<strong i="6">@override</strong>
Widget build(BuildContext context) {
return TweenAnimationBuilder<double>(
tween: Tween(begin: 0, end: 1),
duration: widget.duration1,
builder: (_, value1, __) {
return TweenAnimationBuilder<double>(
tween: Tween(begin: 0, end: 1),
duration: widget.duration2,
builder: (_, value2, __) {
return TweenAnimationBuilder<double>(
tween: Tween(begin: 0, end: 1),
duration: widget.duration3,
builder: (_, value3, __) {
return Container(
margin: EdgeInsets.symmetric(vertical: value2 * 20, horizontal: value3 * 30),
color: Colors.red.withOpacity(value1),
);
});
});
});
}
}
์ค์ํ ์ฝ๋๋ฅผ ์ฐพ๋ ๊ฒ์ด ํจ์ฌ ๋ ์ด๋ ต์ต๋๋ค(์ ์ด๋ ๋ด ๋์๋). ๋ํ, fwiw, ๋๋ ์ด๊ฒ์ ์์ฑํ ๋ 3๋ฒ ์ ๋ ๋ค์ ์์ํด์ผ ํ์ต๋๋ค. ์ด๋ค ๋ธ๋ํท์ด ์ด๋์ ์ํ๋์ง, ๋ด ์ธ๋ฏธ ์ฝ๋ก ์ด ์ด๋๋ก ๊ฐ์ผ ํ๋์ง ๋ฑ์ ๊ณ์ํด์ ํผ๋์ค๋ฌ์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ค์ฒฉ ๋น๋๋ ๋ด๋ถ์์ ์์ฑํ๊ฑฐ๋ ์์ ํ๋ ๊ฒ์ด ์ฌ๋ฏธ๊ฐ ์์ต๋๋ค. ํ๋์ ์๋ชป๋ ์ธ๋ฏธ์ฝ๋ก ๊ณผ dartfmt๋ ์ ์ฒด๋ฅผ ์์ ํ ๋ถ์ด๋ฒ๋ฆฝ๋๋ค.
์ด๊ฒ์ด ์ด๋ป๊ฒ ๋ ์ ๋ขฐํ ์ ์์ต๋๊น?
์ด๊ฒ์ด ์ ์ด๊ฒ์ด ํต์ฌ ํ๋ฌ๊ทธ์ธ imo๊ฐ _ํด์ผ_ ํ๋์ง์ ๋ํ ์๋ฒฝํ ์์ ๋๋ค. ์ฌ๊ธฐ์ ํ์ํ ๋๋ฉ์ธ ์ง์์ _deep_์ ๋๋ค. ์ ๋ ์ด์ ๊ฐ์ ๊ฐ๋จํ ์บ์ฑ ์์คํ ์ ๊ตฌํํ๊ธฐ ์ํ ์คํฌ๋ฆฝํ ์ง์์ด ์์ง๋ง ๋ฐ์ํ ์ ์๋ ๋ชจ๋ ์ฃ์ง ์ผ์ด์ค ๋๋ ์ฐ๋ฆฌ๊ฐ ๋ค์ด๊ฐ ์ ์๋ ๋์ ์ํ๋ฅผ ์ ์ ์๋ ๋๋ฉ์ธ ์ง์์ด ๊ฑฐ์ ์์ต๋๋ค. Remi ๋ง๊ณ ๋ Flutter ํ ๋ง๊ณ ๋ ์ด๋ฐ ๊ฑธ ์๋ ๊ฐ๋ฐ์๋ ์ ์ธ๊ณ์ 4๋ช ์ ๋ ์๋ ๊ฒ ๊ฐ์์! (๋ถ๋ช ํ ๊ณผ์ฅ).
Stateless ์์ ฏ์ ์ง์ํ๋ ๋ฌธ์ ๋ ์ข์ ๋ฌธ์ ์ ๋๋ค. ํํธ์ผ๋ก๋ StatefulWidgets๊ฐ ์ด์ํ๊ฒ ์ฅํฉํฉ๋๋ค. ๋ค๋ฅธ ํํธ, ์ฌ๊ธฐ์์ ์ฐ๋ฆฌ๋ ์ง์ ์ผ๋ก ์์ํ ์ฅํฉํจ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์์ต๋๋ค. 2๊ฐ์ ํด๋์ค๋ฅผ ์ ์ํด์ผ ํ๋ ๊ฒฝ์ฐ ๋ฐ์ํ ์ ์๋ ๋ฒ๊ทธ๊ฐ ์์ต๋๋ค. ์๋ง์ผ๋ก ๋ง๋ค ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ผ๋ฉฐ ์ปดํ์ผ๋ฌ๊ฐ ํ์ฉํ์ง ์์ต๋๋ค. StatelessWidget์์ ํ๊ณ ์ถ์ ํฅ๋ฏธ๋ก์ด ์์ ์ด ์ ํ ์์ต๋๋ค. ๊ทธ๋์ ๋๋ ์ด๊ฒ์ด ์ค์ํ ๋ฌธ์ ๋ผ๋ ๊ฒ์ ๋ํด ๋งค๋๋์ง ์์์ต๋๋ค... ํ์คํ ์์ผ๋ฉด ์ข๊ฒ ์ง๋ง, ์ด๊ฒ์ ๋ง์ง๋ง 5% imo์ด๋ฉฐ, ๊ผผ์งํ ํ์๊ฐ ์์ต๋๋ค.
๋ฐ๋ฉด์ ... ํค์๋ ์ง์์ด ์๋ remi์ ๊ตฌ๋ฌธ์ ์ ๋์ ์ผ๋ก ์๋ฆ๋ต๊ณ ์ ์ฐํ๊ณ ๊ฐ๋ ฅํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ StatelessWidget ์ง์์ ๋ฌด๋ฃ๋ก ์ ๊ณตํ๋ค๋ฉด ๊ทธ๊ฑด ์ถ๊ฐ ์ฌํญ์ผ ๋ฟ์ ๋๋ค ๐ฅ
StatelessWidget์ ์ง์ํ๋ ๊ฒ์ ์ค์ํ IMO์ ๋๋ค. ์ ํ ์ฌํญ์ด์ง๋ง ์ฌ์ ํ ๋งค์ฐ ์ข์ต๋๋ค.
๊ทธ๊ฒ์ด ์ค์ํ์ง ์๋ค๋ ๋ฐ ๋์ํ์ง๋ง ์ฌ๋๋ค์ ์ด๋ฏธ StatelessWidget ๋์ ํจ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ํด ์ธ์ฐ๊ณ ์์ต๋๋ค.
์ฌ๋๋ค์ด ๋น๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด StatefulWidget์ ์ฌ์ฉํ๋๋ก ์๊ตฌํ๋ ๊ฒ์(๋๋ถ๋ถ์ ๋น๋๊ฐ ๋์ผํ ์์ฑ์ ๊ฐ์ง ๊ฐ๋ฅ์ฑ์ด ๋๊ธฐ ๋๋ฌธ์) ๊ฐ๋ฑ์ ์ฌํ์ํฌ ๋ฟ์
๋๋ค.
๋ฟ๋ง ์๋๋ผ ๋คํธ์์ ๊ณ ์ฐจ ํจ์๋ฅผ ์์ฑํ ์ ์๋ ์ธ์(https://github.com/dart-lang/language/issues/418)์์๋ ํด๋์ค๋ฅผ ์์ ํ ์ ๊ฑฐํ ์ ์์ต๋๋ค.
<strong i="9">@StatelessWidget</strong>
Widget Example(BuildContext context, {Key key, String param}) {
final value = keyword StreamBuilder();
return Text('$value');
}
๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉ๋ฉ๋๋ค.
Widget build(context) {
// BuildContext and Key are automatically injected
return Example(param: 'hello');
}
์ด๊ฒ์ ํจ์ ๋ฅผ ์์ฑํ๊ณ ํด๋์ค๋ฅผ ์์ฑํ๋ ์ฝ๋ ์์ฑ๊ธฐ์ธ function_widget์์ ์ง์ํ๋ ๊ฒ์
๋๋ค. HookWidget
๋ ์ง์ํฉ๋๋ค.
์ฐจ์ด์ ์ Dart์์ ๊ณ ์ฐจ ํจ์๋ฅผ ์ง์ํ๋ฉด ์ด๋ฌํ ๊ตฌ๋ฌธ์ ์ง์ํ๊ธฐ ์ํด ์ฝ๋๋ฅผ ์์ฑํ ํ์๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค.
@Hixie ๊ฐ ๋ ์์ ์ ์ด๋ผ๋ ์๋ฏธ๊ฐ ๋ฌด์์ ์๋ฏธํ๋์ง ์ถ์ธกํ๊ณ ์์ต๋๋ค. ํํฌ๊ฐ ๊ฐ๋ ์์ ์์/์กฐ๊ฑด๋ถ ๋ฌธ์ ๋ก ๊ณ ํต๋ฐ์ง ์์ต๋๋ค. ์ด๋ ์ํคํ ์ฒ POV์์ ๋งค์ฐ '์ ๋ขฐํ ์ ์๋' ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ฐฐ์ฐ๊ณ ํ ๋ฒ ํ์ตํ๋ฉด ์๋ฐํ์ง ์์).
๊ทธ๋ฌ๋ ํค์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค. ๋๋ new ํค์๋์ ๊ฒฝ์ฐ๊ฐ ๋งค์ฐ ๊ฐ๋ ฅํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ด๊ฐ ๋ง์์ ๋ค์ง ์๋ ์ ์ ์ฐ๋ฆฌ๊ฐ ๋ช ๊ฐ์ง ๊ฐ๋จํ ๊ฐ์ฒด์ ์์ฑ์ ์ฌ๋ฌ ๋ฒ/๋น๋๋ก ์ค์ ํ๋ ๋น์ฉ์ ๋ํด ๊ฑฑ์ ํ๊ณ ์์ง๋ง ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฐฑ๋ง ์์ค์ ์ปจํ ์คํธ์ ๋ง์ ๋ ์ด์์ ๋น์ฉ์ ์์ฑํ๋ ์๋ฃจ์ ์ ์นํธํ๋ค๋ ๊ฒ์ ๋๋ค. ๋ด๊ฐ ์คํดํ๊ณ ์๋ ๊ฑธ๊น?
๋ค๋ฅธ ๋จ์ ์ ์ด๋ฌํ ๋ง๋ฒ์ ์์ด๋์ด์ ๋๋ค. ํ์ง๋ง ๋ง๋ฒ ๊ฐ์ ์ผ์ ํ๋ ค๋ ๊ฒฝ์ฐ ์ ํค์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ปค๋ฎค๋ํฐ์ ์ฝ๊ฒ ๊ฐ์กฐ ํ์ํ๊ณ ์์ฒญํ๊ณ ๊ทธ๊ฒ์ด ๋ฌด์์ธ์ง, ์ด๋ป๊ฒ ์๋ํ๋์ง ์ค๋ช ํ ์ ์๊ธฐ ๋๋ฌธ์ ์๋ก์ด ํค์๋๊ฐ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ด๊ฒ์ Flutter์์ ๋ด๋ ์ ๋ํด ๋๊ตฌ๋ ์ด์ผ๊ธฐํ ์ ์๋ ๋ชจ๋ ๊ฒ์ด ๋ ๊ฒ์ด๋ฉฐ, ๊ฑฐ๊ธฐ์ ์์ฑ๋๋ ๋ฉ์ง ํ๋ฌ๊ทธ์ธ์ ํญ๋ฐ์ ๋ณด๊ฒ ๋ ๊ฒ์ด๋ผ๊ณ ํ์ ํฉ๋๋ค.
@Hixie ๊ฐ ๋ ์์ ์ ์ด๋ผ๋ ์๋ฏธ๊ฐ ๋ฌด์์ ์๋ฏธํ๋์ง ์ถ์ธกํ๊ณ ์์ต๋๋ค. ํํฌ๊ฐ ๊ฐ๋ ์์ ์์/์กฐ๊ฑด๋ถ ๋ฌธ์ ๋ก ๊ณ ํต๋ฐ์ง ์์ต๋๋ค. ์ด๋ ์ํคํ ์ฒ POV์์ ๋งค์ฐ '์ ๋ขฐํ ์ ์๋' ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ฐฐ์ฐ๊ณ ํ ๋ฒ ํ์ตํ๋ฉด ์๋ฐํ์ง ์์).
๊ทธ๋ฌ๋ ํํฌ๋ ์ ์ ์ผ๋ก ๋ถ์ํ ์ ์์ผ๋ฏ๋ก ์ด๋ฌํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์ผ๋ฏ๋ก ์ค์ฉ๋ ๋ ์ปดํ์ผ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
์ด๊ฒ์ ๋ฌธ์ ๊ฐ ๋์ง ์๋๋ค
๋ง์ฐฌ๊ฐ์ง๋ก ์ฌ์ฉ์ ์ง์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์๋ ๊ฒฝ์ฐ ์ด์ ์ ์ธ๊ธํ๋ฏ์ด Property๋ ๋๊ฐ์ ๋ฌธ์ ๋ฅผ ๊ฒช์ต๋๋ค.
์ฐ๋ฆฌ๋ ํฉ๋ฆฌ์ ์ผ๋ก ์ธ ์ ์์ต๋๋ค:
Property property;
<strong i="12">@override</strong>
void initProperties() {
if (condition) {
property = init(property, MyProperty());
}
}
condition
๋ฅผ true์์ false๋ก ์ ํํ๋ฉด ์์ฑ์ด ์ญ์ ๋์ง ์์ต๋๋ค.
๋ฃจํ์์ ์ค์ ๋ก ํธ์ถํ ์๋ ์์ต๋๋ค. ์ผํ์ฑ ๊ณผ์ ์ด๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ์๋ฏธ๊ฐ ์์ต๋๋ค. ๋ฃจํ์์ ์์ฑ์ ์คํํ๋ ์ฌ์ฉ ์ฌ๋ก๋ ๋ฌด์์ ๋๊น?
๊ทธ๋ฆฌ๊ณ ์์ฑ์ ์ด๋ค ์์๋ก๋ ์ฝ์ ์ ์๋ค๋ ์ฌ์ค์ ์ํํ๊ฒ ๋ค๋ฆฝ๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค.
Property first;
Property second;
<strong i="20">@override</strong>
void initProperties() {
// The state of first depends on second, but second is updated after first
// So we could end up in a bad state, similar to how the build method of a Widget should depend
// on the context.size
first = init(property, MyProperty(second?.value));
second = init(property, Whatever());
}
> class _ExampleSimpleBuilderState extends State<ExampleSimpleBuilder> {
> <strong i="5">@override</strong>
> Widget build(BuildContext context) {
> return TweenAnimationBuilder<double>(
> tween: Tween(begin: 0, end: 1),
> duration: widget.duration1,
> builder: (_, value1, __) {
> return TweenAnimationBuilder<double>(
> tween: Tween(begin: 0, end: 1),
> duration: widget.duration2,
> builder: (_, value2, __) {
> return TweenAnimationBuilder<double>(
> tween: Tween(begin: 0, end: 1),
> duration: widget.duration3,
> builder: (_, value3, __) {
> return Container(
> margin: EdgeInsets.symmetric(vertical: value2 * 20, horizontal: value3 * 30),
> color: Colors.red.withOpacity(value1),
> );
> });
> });
> });
> }
> }
๋๋ฌด ์ด์ํ ์์ ๋๋ค. AnimatedContainer๊ฐ ์ด๋ฏธ ์ด ์์ ์ ์ํํ ์ ์๋ค๊ณ ํ์ ํฉ๋๊น?
๋น์ฐํ์ง. ์ฌ๊ธฐ์ ์๋ "X"๋ฅผ ์ํํ๊ธฐ ์ํด ์ผ๋ถ ์์ ฏ์์ 3๊ฐ์ ์ ๋๋ฉ์ด์ ์ ํ์ฉํ๋ ๊ฒ์ ๋๋ค. X๋ ์์ฉ๊ตฌ์ ์์ ๊ฐ์กฐํ๊ธฐ ์ํด ์์ ์์ ์๋์ ์ผ๋ก ๋จ์ํ๋์์ต๋๋ค.
๋ด๊ฐ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง์ ์ง์คํ์ง ๋ง์ญ์์ค. ์ค์ ์์์ ์์ ฏ "์ฝ์ด"๋ 100์ค ์ ๋์ด๊ณ ์ ๋๋ฉ์ด์ ์์ฑ์ ๊ทธ๋ ๊ฒ ๋จ์ํ์ง ์์ผ๋ฉฐ ์ฌ๋ฌ ํธ๋ค๋ฌ ๋ฐ ๊ธฐํ ๊ธฐ๋ฅ์ด ์ ์๋์ด ์์ต๋๋ค. ์์์ ์์ ฏ ์ค ํ๋์์ ์ฒ๋ฆฌ๋์ง ์๋ ์์ ์ ์ํํ๊ณ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค(AnimatedContainer ์ด์ธ์ ๋ค๋ฅธ ๋ชฉ์ ์ ๋งค์ฐ ๋จ์ผ ๋ชฉ์ ์ด๋ฏ๋ก ์ด๋ ต์ง ์์).
์์ ์ ์ด์ ๊ฐ์ ๊ฒ์ ๊ตฌ์ถํ ๋ ๋น๋๊ฐ ์ ์๋ํ์ง ์๋๋ค๋ ๊ฒ์ ๋๋ค. ์ฒ์๋ถํฐ ๊ฐ๋ ์ฑ(๋ฐ ์ฐ๊ธฐ ๊ฐ๋ฅ์ฑ) ๊ตฌ๋ฉ์ ์ง์ด๋ฃ๊ณ ๊ฐ๋จํ ์ฌ์ฉ ์ฌ๋ก์ ์ ํฉํ๋ฏ๋ก "์์ฑ"ํ์ง ์์ต๋๋ค. ์. Compose๋ 2๊ฐ ์ด์์ ํญ๋ชฉ์ผ๋ก ๊ตฌ์ฑ๋ ๊ฒ์ ๋๋ค.
๋ด๊ฐ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง์ ์ง์คํ์ง ๋ง์ญ์์ค. ์ค์ ์์์ ...
...๊ทธ๋ฆฌ๊ณ ๋ค์ ์์ ์ผ๋ก ๋์๊ฐ๋๋ค. ์ค์ ์ฌ๋ก๋ฅผ ๊ฐ์ ธ์ค์ง ์๊ฒ ์ต๋๊น?
๋ณต์กํ ์ ๋๋ฉ์ด์
์ ์ฌ์ฉํ๋ ์ค์ ์๊ฐ ํ์ํ์ญ๋๊น?
https://github.com/gskinnerTeam/flutter_vignettes
์์์ ๋ณต์กํ ์ ๋๋ฉ์ด์ ์ ํ์ํ๋ ๊ฒ์ ์์ ๋ฅผ ๋๋ ํํ๋ ๊ฒ ์ธ์๋ ์๋ฌด ๊ฒ๋ ํ์ง ์์ต๋๋ค. ์ผ๋ถ ์์ ฏ ๋ด์์ ์ฌ๋ฌ ์ ๋๋ฉ์ดํฐ(๋๋ ์์ํ ์ ์๋ ๋ค๋ฅธ ์ํ ์ ์ฅ ๊ฐ์ฒด)๋ฅผ ์ฌ์ฉํ๋ ๋ง์ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์์ต๋๋ค.
๋น์ฐํ์ง. ์ฌ๊ธฐ์ ์๋ "X"๋ฅผ ์ํํ๊ธฐ ์ํด ์ผ๋ถ ์์ ฏ์์ 3๊ฐ์ ์ ๋๋ฉ์ด์ ์ ํ์ฉํ๋ ๊ฒ์ ๋๋ค. X๋ ์์ฉ๊ตฌ์ ์์ ๊ฐ์กฐํ๊ธฐ ์ํด ์์ ์์ ์๋์ ์ผ๋ก ๋จ์ํ๋์์ต๋๋ค.
์์ ฏ "์ฝ์ด"๋ 100์ค ๋๋ ๊ทธ ์ด์์ผ ๊ฒ์ ๋๋ค.
๋ค๋ฅธ ๊ฒ์๋ฌผ์์ "ํต์ฌ"์ ๊ฐ๋ฆฌ๋ ์์ฉ๊ตฌ ์์ ๋ฅผ โโ๊ฒ์ํ์ง๋ง ์ด์ ํต์ฌ์ด ์๋ฐฑ ์ค์ด ๋ ๊ฒ์ด๋ผ๊ณ ๋งํฉ๋๊น? ๊ทธ๋์ ์ค์ ๋ก, ์์ฉ๊ตฌ๋ ์ฝ์ด์ ๋นํด ๋ฏธ๋ฏธํ ๊น์? ๋น์ ์ ๊ทธ๊ฒ์ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๊ฐ์ง ์ ์์ต๋๋ค.
๋น์ ์ ๋์์์ด ๋น์ ์ ์ฃผ์ฅ์ ๋ฐ๊พธ๊ณ ์์ต๋๋ค.
๋ด๊ฐ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง์ ์ง์คํ์ง ๋ง์ญ์์ค. ์ค์ ์์์ ...
...๊ทธ๋ฆฌ๊ณ ๋ค์ ์์ ์ผ๋ก ๋์๊ฐ๋๋ค. ์ค์ ์ฌ๋ก๋ฅผ ๊ฐ์ ธ์ค์ง ์๊ฒ ์ต๋๊น?
๋ค์ํ ์์ด๋์ด๋ฅผ ๊ฐ์ง๊ณ ๋ ธ๋ ๊ฒ๋ง์ผ๋ก๋ ์ค์ ์ฌ๋ก๋ฅผ ๋ง๋๋ ๋ฐ ์๊ฐ์ด ๋ง์ด ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์ผ ๊ฒ์ ๋๋ค. ์๋๋ ๋ ์๊ฐ ์ค์ ์ํฉ์์ ์ด๋ป๊ฒ ์ฌ์ฉ๋ ์ ์๋์ง ์์ํ๋๋ก ํ๋ ๊ฒ์ด์ง ์ฃผ๋ณ์ ๋ฐฉ๋ฒ์ด ์๋ค๋ ๊ฒ์ ์ธ๊ธํ์ง ์์ต๋๋ค. ๋ฌผ๋ก ์ ๋๋ฉ์ด์ ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ ์๋ ์์ง๋ง ์ฌ์ฉํ ์ ์๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น์? ์ ๋๋ฉ์ด์ ์ปจํ ์ด๋๋ง์ผ๋ก ๋ง๋ค๊ธฐ์๋ ๋๋ฌด ๋ณต์กํ๋ค๋ฉด ์ด๋จ๊น์?
์ด์ ์๊ฐ๋ค์ ์ข์ ์๋ ๋์ ๊ฒ์ผ๋ก ๋ณด์ฌ์ง ์ ์๋ ์ง์ ํ ์ค์ ์๋ฅผ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ทธ๊ฒ์ ๋ํ ์๊ฒฌ์ด ์์ต๋๋ค. ๋น๋ฉดํ ๋ฌธ์ ๋ฅผ ์์ ํ ํด๊ฒฐํ์ญ์์ค. ์ด๊ฒ์ ํํฌ ์ง์ง์์ ๋ฐ๋์ ์ฌ์ด์ ํผ๋์ ์ฃผ์ ์์ธ์ธ ๊ฒ ๊ฐ์ต๋๋ค. ๊ฐ๊ฐ์ด ์ด๋ ์ ๋ ์๋ก๋ฅผ ์ง๋์ณ ๋งํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ธฐ ๋๋ฌธ์ ์๋๋ฐฉ์ด "์ค์ " ์๊ฐ ๋ค์๊ณผ ๊ฐ๋ค๊ณ ๋งํ ์ ์๋๋ก ์ค์ ์ฑ์ ๋ง๋ค์๋ Hixie์ ์ ์์ ์ง์งํฉ๋๋ค. ์ ์๋์ง ์์์ผ๋ฉฐ ์ง์ง์๋ ์ค์ ์๋๋ฆฌ์ค๋ฅผ ๋จ์ํ ์์ํด์ผ ํ๋ค๊ณ ๋งํ ์ ์์ต๋๋ค.
๋ฐ์ ์์ฉ๊ตฌ๋ก ๋์ด ์๋ 100์ค์ง๋ฆฌ ํด๋์ค๋ฅผ ๊ฐ๋ ๊ฒ์ ์ด๋ฆฌ์์ ์ผ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก ๋ด๊ฐ ์ฌ๊ธฐ์ ์ค๋ช ํ๋ ๊ฒ์ ๋๋ค. ์ฝ์ด๊ฐ ์๋ฌด๋ฆฌ ํฌ๋๋ผ๋ ์ฌ๋ฌ ๋น๋๋ฅผ ์ฌ์ฉํ ๋ ๋ฐ์ํ๋ ๋ง์ ์์์ผ๋ก ์ธํด ๋๋ ํ๋์ด์๋ ์ ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ทธ ์ด์ ๋ ๋๊ท๋ชจ ์ฝ๋๋ฒ ์ด์ค์์ ์ค์บ ๊ฐ๋ฅ์ฑ, ๊ฐ๋ ์ฑ ๋ฐ ์ ์ง ๊ด๋ฆฌ ๋๋ฌธ์ ๋๋ค. ๋น๋์์ ์ฐ๋ ๊ฒ์ ์ค๊ดํธ ์ง์ฅ์ ๋น ์ง๋ ๊ฒฝํฅ์ด ์๊ธฐ ๋๋ฌธ์ ์์ฐ์ฑ์ ์๊ฒ ๋์ง๋ง ์ค์ ์ฐ๋ ๊ฒ์ ์๋๋๋ค.
๋ค๋ฅธ ๊ฒ์๋ฌผ์์ "ํต์ฌ"์ ๊ฐ๋ฆฌ๋ ์์ฉ๊ตฌ ์์ ๋ฅผ โโ๊ฒ์ํ์ง๋ง ์ด์ ํต์ฌ์ด ์๋ฐฑ ์ค์ด ๋ ๊ฒ์ด๋ผ๊ณ ๋งํฉ๋๊น? ๊ทธ๋์ ์ค์ ๋ก, ์์ฉ๊ตฌ๋ ์ฝ์ด์ ๋นํด ๋ฏธ๋ฏธํ ๊น์? ๋น์ ์ ๊ทธ๊ฒ์ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๊ฐ์ง ์ ์์ต๋๋ค.
๋น์ ์ ๋์์์ด ๋น์ ์ ์ฃผ์ฅ์ ๋ฐ๊พธ๊ณ ์์ต๋๋ค.
๋ค์ ๋งํ์ง๋ง, ์ด ๋ฌธ์ ๋ ์์ฉ๊ตฌ์ ๊ดํ ๊ฒ์ด ์๋๋ผ ๊ฐ๋
์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ์ ๊ดํ ๊ฒ์
๋๋ค.
100์ค์ด๋ฉด ์๊ด์์ต๋๋ค.
์ค์ํ ๊ฒ์ ์ด ๋ผ์ธ์ด ์ผ๋ง๋ ์ฝ๊ธฐ/์ ์ง/์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๊ฐ์
๋๋ค.
๋ ผ์์ด ์์ฉ๊ตฌ์ ๋ํ ๊ฒ์ธ๋ฐ๋ ์ถฉ๋ถํ ๋๋ฑํ ํํ ๋ฐฉ์์ ์ ๊ณตํ๋ ์ฌ์ฉ์์ธ ๋ด๊ฐ ์ ๊ทธ๋ฐ ์์ฉ๊ตฌ๋ฅผ ์ฉ์ธํด์ผ ํฉ๋๊น? ํ๋ก๊ทธ๋๋ฐ์ ์ถ์ํ๋ฅผ ๋ง๋ค๊ณ ์์ ์ ์๋ํํ๋ ๊ฒ์ ๋๋ค. ๋ค์ํ ํด๋์ค์ ํ์ผ์์ ๋์ผํ ์์ ์ ๋ฐ๋ณตํด์ ์ํํ๋ ์์ ์ ์ค์ ๋ก ๋ณด์ง ๋ชปํฉ๋๋ค.
๋ณต์กํ ์ ๋๋ฉ์ด์ ์ ์ฌ์ฉํ๋ ์ค์ ์๊ฐ ํ์ํ์ญ๋๊น?
https://github.com/gskinnerTeam/flutter_vignettes
ํ์คํ, ๋น์ ์ ๋ด๊ฐ ๋น์ ์ ์ ์ฒด ํ๋ก์ ํธ๋ฅผ ํํค์น ๊ฒ์ด๋ผ๊ณ ๊ธฐ๋ํ ์ ์์ต๋๋ค. ์ ํํ ์ด๋ค ํ์ผ์ ๋ด์ผ ํ๋์?
์์์ ๋ณต์กํ ์ ๋๋ฉ์ด์ ์ ํ์ํ๋ ๊ฒ์ ์์ ๋ฅผ ๋๋ ํํ๋ ๊ฒ ์ธ์๋ ์๋ฌด ๊ฒ๋ ํ์ง ์์ต๋๋ค.
์ ๋ฐ๋์ ๋๋ค. ๊ธฐ์กด ์๋ฃจ์ ์ผ๋ก๋ ํด๊ฒฐํ ์ ์๋ ์์์ ๋ณต์กํ ์ ๋๋ฉ์ด์ ์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด ๊ทธ ์์ผ ๊ฒ์ ๋๋ค. Hixie๊ฐ ๊ณ์ํด์ ๋ฌป๊ณ ์๋ ๊ฒ์ ๋๋ค.
gif๋ฅผ ์ค์บํ๊ณ ๊ทธ ์ค ์ผ๋ถ๋ฅผ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ์ ์์ํ๊ธฐ ์์ํ์ญ์์ค. ๊ทธ ์ ์ฅ์๋ ์ค์ ๋ก 17๊ฐ์ ๋ ๋ฆฝ ์คํํ ์ฑ์ ๋๋ค. ๋ํ ๋ณต์กํ ์ ๋๋ฉ์ด์ ์ด ์กด์ฌํ ์ ์๋ค๋ ๊ฒ์ ์ฆ๋ช ํ๊ธฐ ์ํด ๋ด๊ฐ ์์์ ์ ๋๋ฉ์ด์ ์ ์์ฑํ ๊ฒ์ด๋ผ๊ณ ๊ธฐ๋ํ ์๋ ์์ต๋๋ค. ์ ๋ Flash๋ฅผ ์์์ผ๋ก 20๋ ๋์ ๊ทธ๊ฒ๋ค์ ๊ตฌ์ถํด ์์ต๋๋ค. ์ด์จ๋ ์ ๋๋ฉ์ด์ ์๋ง ๊ตญํ๋ ๊ฒ์ ์๋๋ฉฐ ๋ ํฐ ์์ ์ ์ค๋ช ํ๋ ๊ฐ์ฅ ๊ฐ๋จํ ๊ฐ์ฅ ์น์ํ API์ผ ๋ฟ์ ๋๋ค.
์์๋ค์ํผ ์ ๋๋ฉ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ๋งค๋ฒ ํด์ผ ํ๋ 6๊ฐ์ง๊ฐ ์์ง๋ง ์๋ช ์ฃผ๊ธฐ ํํฌ๋ ํ์ํฉ๋๋ค?? ์ข์, ์ด์ ๋งค๋ฒ ์ํํด์ผ ํ๋ 6๋จ๊ณ๊ฐ ์๋ ๋ชจ๋ ๊ฒ์ผ๋ก ํ์ฅํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ 2๊ณณ์์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๋๋ 3๊ฐ๋ฅผ ๋์์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๊ทธ๊ฒ์ ํ๋ฉด์์ ๋ฌธ์ ๊ฐ ๋๋ฌด ๋ถ๋ช ํด์, ์ค๋ช ํ๊ธฐ ์ํด ๋ฌด์์ ๋ ์ถ๊ฐํ ์ ์์์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
ํ๋ก๊ทธ๋๋ฐ์ ์ถ์ํ๋ฅผ ๋ง๋ค๊ณ ์์ ์ ์๋ํํ๋ ๊ฒ์ ๋๋ค. ๋ค์ํ ํด๋์ค์ ํ์ผ์์ ๋์ผํ ์์ ์ ๋ฐ๋ณตํด์ ์ํํ๋ ์์ ์ ์ค์ ๋ก ๋ณด์ง ๋ชปํฉ๋๋ค.
__๋ชจ๋__? ๋ฐ๋ผ์ ์ฑ๋ฅ, ์ ์ง ๋ณด์์ฑ์ ๊ด๋ จ์ด ์์ต๋๊น?
๋ ธ๋์ "์๋ํ"ํ๋ ๊ฒ๊ณผ ๋ ธ๋์ "ํ๋ ๊ฒ"์ด โโ๋์ผํ ์์ ์ด ์ต๋๋ค.
์ฌ๋ฌ๋ถ, ์ค์ ์ฌ๋ก๋ฅผ ๋ง๋ค ์๊ฐ์ด๋ ์ํฅ์ด ์์ด๋ ๊ด์ฐฎ์ต๋๋ค. ํ์ง๋ง ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๊ธฐ ์ํด ์์ ๋ฅผ ๋ง๋๋ ๋ฐ ๊ด์ฌ์ด ์๋ค๋ฉด ์ฌ๋๋ค์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ๋ค๊ณ ์๊ฐํ์ง๋ ๋ง์ธ์( ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ์์ ๋ฅผ ๋ง๋๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ ๋ง์ ์์ ์ ๋๋ค. ์ฌ๊ธฐ์ ์๋ ๋๊ตฌ๋ ๋๊ตฐ๊ฐ๋ฅผ ์ํด ๋ฌด์์ ํด์ค ํ์๊ฐ ์์ต๋๋ค. ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ์๋ก๋ฅผ ๋์ฐ๋ ค๊ณ ๋ ธ๋ ฅํ๋ ์คํ ์์ค ํ๋ก์ ํธ์ ๋๋ค.
@TimWhiting https://github.com/TimWhiting/local_widget_state_approaches ๋ฆฌํฌ์งํ ๋ฆฌ ์ ๋ผ์ด์ ์ค ํ์ผ์ ๋ฃ์ด ์ฃผ์๊ฒ ์ต๋๊น? ์ด๋ค ์ฌ๋๋ค์ ํด๋น ๋ผ์ด์ ์ค(BSD, MIT ๋๋ ์ด์์ ์ผ๋ก๋ ์ ์ฌ) ์์ด๋ ๊ธฐ์ฌํ ์ ์์ต๋๋ค.
๋์ผํ ๊ฒ์ ํํํ๋ ์ถฉ๋ถํ ๋๋ฑํ ๋ฐฉ๋ฒ์ด ์ฃผ์ด์ง๋ฉด ์ฌ์ฉ์์ธ ๋ด๊ฐ ์ด๋ค ๊ฒฝ์ฐ์๋ ๊ทธ๋ฌํ ์์ฉ๊ตฌ๋ฅผ ์ฉ์ธํด์ผ ํ๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
์, ์ ์ง๋ณด์์ฑ๊ณผ ์ฑ๋ฅ์ ๋ฌผ๋ก ์ค์ํฉ๋๋ค. ๋๋ฑํ ์๋ฃจ์ ์ด ์๋ ๊ฒฝ์ฐ ์์ฉ๊ตฌ๊ฐ ์ ๊ณ ์ฝ๊ธฐ ์ฝ๊ณ ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํ ๋ฑ์ ์๋ฃจ์ ์ ์ ํํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ํํฌ์ ์ฑ๋ฅ์ ์ธก์ ํ์ง ์์๊ธฐ ๋๋ฌธ์ ํํฌ๊ฐ ๋ต์ด๋ผ๋ ๋ง์ ์๋์ง๋ง ๊ฒฝํ์ ํํฌ๋ฅผ ์ ์ง ๊ด๋ฆฌํ๊ธฐ๊ฐ ๋ ์ฝ์ต๋๋ค. ํํฌ์ ๊ฐ์ ๊ตฌ์กฐ๊ฐ Flutter ์ฝ์ด์ ์ฝ์ ๋ ๊ฒฝ์ฐ ์์ ์ ์ด๋ค ์ํฅ์ ๋ฏธ์น๋์ง์ ๋ํ ๊ทํ์ ์ฃผ์ฅ์ ๋ํด ์ฌ์ ํ ํ์ ํ ์ ์์ต๋๋ค.
gif๋ฅผ ์ค์บํ๊ณ ๊ทธ ์ค ์ผ๋ถ๋ฅผ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ์ ์์ํ๊ธฐ ์์ํ์ญ์์ค.
gif๋ฅผ ์ค์บํ์ต๋๋ค. ๋น๋ ์์ ฏ์ ์ฌ์ฉํ์ง ์์ต๋๋ค.
๋ง์ ์ ๋๋ฉ์ด์
์ด ๋๋ฌด ๋ณต์กํด์ ๋ ๋์ ์์ค์ ๋น๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํํ๋ค๋ ๊ฒ์ ์์๋ค๋ฉด ์๋ง๋ ํจํค์ง๋ฅผ ์ฌ์ฉํ์ง ์์์ ๊ฒ์
๋๋ค.
์ด์จ๋ ์ด ํ ๋ก ์ ๊ฐ์ธ์ ์ธ ์๊ฒฌ ์ฐจ์ด๊ฐ ๋ ๋ง์ด ๋ฐ์ํ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ฐ๋ฆฌ๋ ๋น๋ฉดํ ์ฃผ์ ์์ ์ ์ง์คํด์ผ ํฉ๋๋ค. ๋ด๊ฐ ์์์ ๋งํ๋ฏ์ด ์๋๊ฐ ์ ๊ธฐ๋ ๋ฌธ์ ๋ฅผ ์ง์ ์ผ๋ก ํด๊ฒฐํ์ง ๋ชปํ๋ ๊ฐ์ ์ฑ ์ ์ฐพ์ ๊ฒฝ์ฐ ํํฌ ์ง์ง์๋ค์ด ์ด๋ป๊ฒ ๋ ์์ ์๋ฅผ ๋ณด์ฌ์ค ์ ์๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ง๊ธ์ @TimWhiting ์ ์ ์ฅ์์ ๊ธฐ์ฌํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ธฐ์กด ์๋ฃจ์ ์ผ๋ก๋ ํด๊ฒฐํ ์ ์๋ ์์์ ๋ณต์กํ ์ ๋๋ฉ์ด์ ์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด ๊ทธ ์์ผ ๊ฒ์ ๋๋ค. Hixie๊ฐ ๊ณ์ํด์ ๋ฌป๊ณ ์๋ ๊ฒ์ ๋๋ค.
์ค๋๋ ๊ฐ๋ฅํ์ง ์์ ๊ฒ์ ์๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ ์ด ๋ฌธ์ ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ฉ๋๋ค.
์ด ๋ฌธ์ ๋ ์ค๋๋ ๊ฐ๋ฅํ์ง ์์ ์ผ๋ถ๋ฅผ ์ฐจ๋จ ํด์ ํ๋ ๊ฒ์ด ์๋๋ผ ์ด๋ฏธ ๊ฐ๋ฅํ ๊ฒ์ ๊ตฌ๋ฌธ์ ๊ฐ์ ํ๋ ๊ฒ์ ๊ดํ ๊ฒ์
๋๋ค.
์ค๋๋ ๊ฐ๋ฅํ์ง ์์ ๊ฒ์ ์ ๊ณตํ๋ผ๋ ์์ฒญ์ ์ฃผ์ ์์ ๋ฒ์ด๋ฌ์ต๋๋ค.
@TimWhiting https://github.com/TimWhiting/local_widget_state_approaches ๋ฆฌํฌ์งํ ๋ฆฌ ์ ๋ผ์ด์ ์ค ํ์ผ์ ๋ฃ์ด ์ฃผ์๊ฒ ์ต๋๊น? ์ด๋ค ์ฌ๋๋ค์ ํด๋น ๋ผ์ด์ ์ค(BSD, MIT ๋๋ ์ด์์ ์ผ๋ก๋ ์ ์ฌ) ์์ด๋ ๊ธฐ์ฌํ ์ ์์ต๋๋ค.
์๋ฃ. ์ฃ์กํฉ๋๋ค. ์์ ์ ๋ํด ์์ ํ ์๊ฐ์ด ๋ง์ง ์์์ง๋ง ์ด๋ฒ ์ฃผ์ ์์ ์ ๋ค์ด๊ฐ ๊ฒ์ ๋๋ค.
๊ธฐ์กด ์๋ฃจ์ ์ผ๋ก๋ ํด๊ฒฐํ ์ ์๋ ์์์ ๋ณต์กํ ์ ๋๋ฉ์ด์ ์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด ๊ทธ ์์ผ ๊ฒ์ ๋๋ค. Hixie๊ฐ ๊ณ์ํด์ ๋ฌป๊ณ ์๋ ๊ฒ์ ๋๋ค.
์ค๋๋ ๊ฐ๋ฅํ์ง ์์ ๊ฒ์ ์๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ ์ด ๋ฌธ์ ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ฉ๋๋ค.
์ด ๋ฌธ์ ๋ ์ค๋๋ ๊ฐ๋ฅํ์ง ์์ ์ผ๋ถ๋ฅผ ์ฐจ๋จ ํด์ ํ๋ ๊ฒ์ด ์๋๋ผ ์ด๋ฏธ ๊ฐ๋ฅํ ๊ฒ์ ๊ตฌ๋ฌธ์ ๊ฐ์ ํ๋ ๊ฒ์ ๊ดํ ๊ฒ์ ๋๋ค.์ค๋๋ ๊ฐ๋ฅํ์ง ์์ ๊ฒ์ ์ ๊ณตํ๋ผ๋ ์์ฒญ์ ์ฃผ์ ์์ ๋ฒ์ด๋ฌ์ต๋๋ค.
๋ด๊ฐ ๋งํ ๊ฒ์ ๋ค์ ๋งํด๋ณด์.
์์ฑํ๊ธฐ ์ด๋ ต๊ณ ์ฑ๋ฅ์ ์ํฅ์ ๋ฏธ์น์ง ์์ผ๋ฉด์ ํฌ๊ฒ ๊ฐ์ ๋ ์ ์๋ ์ ๋๋ฉ์ด์ , ์ํ ๋ฑ ์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด ๊ทธ ์๊ฐ ๋ ๊ฒ์ด๋ฉฐ, ์ด๊ฒ์ด Hixie๊ฐ ๊ณ์ ๋ฌป๋ ๊ฒ์ ๋๋ค.
๋ ์ ์ ์์ฉ๊ตฌ, ๋ ๋ง์ ์ฌ์ฌ์ฉ์ฑ, ๋ ๋ง์ ๋ง๋ฒ์ ๋ํ ์๊ตฌ๋ฅผ ์ดํดํฉ๋๋ค. ๋๋ ์ ์ ์์ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํ๋ ๊ฒ์ ์ข์ํ๊ณ , ๋ ๋ง์ ์์
์ ์ํํ๋ ์ธ์ด/ํ๋ ์์ํฌ๊ฐ ์๋นํ ๋จน์์ง์ค๋ฝ์ต๋๋ค.
์ง๊ธ๊น์ง ์ฌ๊ธฐ์ ์ ์๋ ์์ /์๋ฃจ์
์ฝค๋ณด๋ ์ฝ๋๋ฅผ ํฌ๊ฒ ํฅ์์ํค์ง ๋ชปํ์ต๋๋ค. ์ฆ, ์ผ๋ง๋ ๋ง์ ์ฝ๋ ์ค์ ์์ฑํด์ผ ํ๋์ง ๊ทธ ์ด์์ ๊ด์ฌ์ด ์๋ ๊ฒฝ์ฐ์
๋๋ค.
์ฌ๋ฌ๋ถ, ์ค์ ์ฌ๋ก๋ฅผ ๋ง๋ค ์๊ฐ์ด๋ ์ํฅ์ด ์์ด๋ ๊ด์ฐฎ์ต๋๋ค. ํ์ง๋ง ๋ฌธ์ ๋ฅผ ์ค๋ช ํ๊ธฐ ์ํด ์์ ๋ฅผ ๋ง๋๋ ๋ฐ ๊ด์ฌ์ด ์๋ค๋ฉด ์ฌ๋๋ค์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ๋ค๊ณ ์๊ฐํ์ง๋ ๋ง์ธ์( ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ์์ ๋ฅผ ๋ง๋๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ ๋ง์ ์์ ์ ๋๋ค. ์ฌ๊ธฐ์ ์๋ ๋๊ตฌ๋ ๋๊ตฐ๊ฐ๋ฅผ ์ํด ๋ฌด์์ ํด์ค ํ์๊ฐ ์์ต๋๋ค. ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ์๋ก๋ฅผ ๋์ฐ๋ ค๊ณ ๋ ธ๋ ฅํ๋ ์คํ ์์ค ํ๋ก์ ํธ์ ๋๋ค.
@TimWhiting https://github.com/TimWhiting/local_widget_state_approaches ๋ฆฌํฌ์งํ ๋ฆฌ ์ ๋ผ์ด์ ์ค ํ์ผ์ ๋ฃ์ด ์ฃผ์๊ฒ ์ต๋๊น? ์ด๋ค ์ฌ๋๋ค์ ํด๋น ๋ผ์ด์ ์ค(BSD, MIT ๋๋ ์ด์์ ์ผ๋ก๋ ์ ์ฌ) ์์ด๋ ๊ธฐ์ฌํ ์ ์์ต๋๋ค.
์ ๋ ์ด๋ฌํ ๋ค์ํ ์์ ์ ์ฝ๋ ์กฐ๊ฐ์ ๋ง๋๋ ๋ฐ ์ฝ 6์๊ฐ์ ๋ณด๋์ต๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ๋จ์ง ๊ทธ๊ฒ์ด ์กด์ฌํ ์ ์๋ค๋ ๊ฒ์ ์ฆ๋ช ํ๊ธฐ ์ํด ๋ณต์กํ ์ ๋๋ฉ์ด์ ์ ๊ตฌ์ฒด์ ์ธ ์๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ ์๋ฏธ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์์ฒญ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ด๊ฒ์ AnimatedContainer์์ ์ฒ๋ฆฌํ ์ ์๋ ๊ฒ์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ์ ๋๋ค.
Container(margin: EdgeInsets.symmetric(vertical: value2 * 20, horizontal: value3 * 30), color: Colors.red.withOpacity(value1));
์ด๊ฒ์ ๋ฌธ์ ์ ๋ํด ๊ฑฐ์ ์๋์ ์ผ๋ก ๋๊ฐํ ์ ๋๋ก ์ฌ์ํฉ๋๋ค. ๋ ๊ฐ์ ํ์ค ๋ฒํผ, ์์ง์ด๋ ์ ์, ํฌ๊ธฐ ์กฐ์ ์ค์ ํ์ด๋ ์ธ๋๋ ํ ์คํธ ํ๋ ๋๋ ๋ค์งํ๋ ์นด๋๊ฐ ์์ ์ ์๋ค๊ณ ์์ํ๋ ๊ฒ์ด ๊ทธ๋ ๊ฒ ์ด๋ ต์ต๋๊น? 15๊ฐ์ ๋ ๋ฆฝ๋ ๋ง๋๊ฐ ์๋ ์ฌ์ด๋๋ฐ๋ฅผ ๋ง๋ค๊ณ ์๊ฑฐ๋ ๋ฉ๋ด๋ฅผ ๋ฐ์ด๋ฃ๊ณ ์์ง๋ง ๊ฐ๋ณ ํญ๋ชฉ์ ๋ค์ ๋ฐ์ด๋ด๋ ๊ธฐ๋ฅ์ด ํ์ํ ์๋ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ณ์ํด์, ๊ณ์ํด์. ๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ ์ ๋๋ฉ์ด์ ๋ง์ ์ํ ๊ฒ์ ๋๋ค. ์์ ฏ ์ปจํ ์คํธ์์ ๋ถ๋ด์ด ๋๋ ๋ชจ๋ ์ฌ์ฉ ์ฌ๋ก์ ์ ์ฉ๋ฉ๋๋ค.
๋๋ ๋ ๋น๋์ ๊ธฐ๋ณธ ์ํ ์ฌ์ฌ์ฉ ๋ฌธ์ ์ ๋ํ ํ๋ฅญํ ํ์ค ์ฌ๋ก๋ฅผ ์ ๊ณตํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
https://github.com/flutter/flutter/issues/51752#issuecomment -671566814
https://github.com/flutter/flutter/issues/51752#issuecomment -671489384
1000๊ฐ ์ด์์ ํด๋์ค ํ์ผ๋ก ๊ตฌ์ฑ๋ ํ๋ก์ ํธ์ ๊ด๋ฒ์ํ๊ฒ ํผ์ ธ ์๋ ์ด๋ฌํ ์ธ์คํด์ค ์ค ๋ง์ ๊ฒ์ ์์ํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ํผํ๋ ค๊ณ ํ๋ ๊ฐ๋ ์ฑ ๋ฐ ์ ์ง ๊ด๋ฆฌ ๋ฌธ์ ์ ๋ํ ์๋ฒฝํ ๊ทธ๋ฆผ์ ์ป์ ์ ์์ต๋๋ค.
์ค์ฒฉ์ด ์ฝ๋๋ฅผ ์ฝ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๋ @esDotDev๊ฐ ์ ๊ณตํ ์์ ์ด๋ฏธ์ง๋ ์์ต๋๊น ? ๊ทธ๋ค์๊ฒ ๋ถ์กฑํ ๊ฒ์ ๋ฌด์์ ๋๊น? ์ฑ๋ฅ ๋ฉํธ๋ฆญ์ด ์๋ค๊ณ ๊ฐ์ ํ์ง๋ง @rrousselGit ์ ๋น๋๋ณด๋ค ์ฑ๋ฅ์ด
@esDotDev ๋ด ์๊ฐ์ ํต์ฌ์ ๋ชจ๋ ์๋ช ์ฃผ๊ธฐ ๊ด๋ฆฌ ์๋ฃจ์ ์ ๋น๊ตํ ์ ์๋ ๋จ์ผ ํ์ค ์๋ฅผ ๊ฐ๋ ๊ฒ์ ๋๋ค(ํํฌ๋ฟ๋ง ์๋๋ผ ๋ฏธ๋์ ๋ค๋ฅธ ์๋ฃจ์ ๋ ๊ฐ๋ฅ). TodoMVC์ ๋์ผํ ์์น์ ๋๋ค. React, Vue, Svelte ๋ฑ์ ๋ค์ํ ๊ตฌํ์ ๊ฐ๋ฆฌํฌ ํ์๋ ์์ต๋๋ค. ์ฐจ์ด์ ์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด ๋ชจ๋ ๋์ผํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌํํ๊ธฐ๋ฅผ ์ํ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ฉด ๋น๊ตํ ์ ์์ต๋๋ค.
๊ทธ๊ฒ์ ๋์๊ฒ ์๋ฏธ๊ฐ ์์ง๋ง ํ ํ์ด์ง๋ณด๋ค ๋ ์ปค์ผ ํ๋ ์ด์ ๋ฅผ ์ดํดํ์ง ๋ชปํฉ๋๋ค.
์ฌ๋ฌ ์ ๋๋ฉ์ด์ ์ ๊ด๋ฆฌํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ด๊ณ ๋ง์ ์์ฉ๊ตฌ๋ฅผ ํ์๋ก ํ๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ๊ณ ํ์ฌ ์ข์ ์๋ฃจ์ ์ด ์๋ ์๋ฒฝํ ์์ ๋๋ค. ๊ทธ๊ฒ์ด ์๋ฏธ๊ฐ ์๋ค๋ฉด ์ฌ๋๋ค์ด ์ ๋๋ฉ์ด์ ์ด ์ด๋ป๊ฒ ๋ณต์กํ ์ ์๋์ง์กฐ์ฐจ ์ดํดํ์ง ๋ชปํ๋ค๊ณ ๋งํ ๊ฒ์ด๋ผ๋ฉด ๋ถ๋ช ํ ๋ชจ๋ ์ ์ค ์ผ์ด์ค๋ ์ํคํ ์ฒ ๋ฌธ์ ๊ฐ ์๋๋ผ ์ ์ค ์ผ์ด์ค์ ์ปจํ ์คํธ์ ๋ํด ๋ฌด๋์ง ๊ฒ์ ๋๋ค. ์ค๋ช ํ๋ ค๊ณ ํฉ๋๋ค.
๋ฌผ๋ก @TimWhiting ์ ๋ฆฌํฌ์งํ ๋ฆฌ์๋ ์์ ํ ์ฑ์ด ์์ต๋๋ค. ๋ค๋ฅธ ์ฌ๋๋ค์ด ์๋ฃจ์ ์ ๊ตฌํํ ์ ์๋ ํด๋น ๋ฆฌํฌ์งํ ๋ฆฌ์ ๋ํ ์ ๋๋ฉ์ด์ ์ ํ์ค ์๋ฅผ ๋ง๋ค ์ ์๋ค๋ฉด ๊ทธ๊ฒ์ด ์๋ํ ๊ฒ์ ๋๋ค.
๋๋ ๋ํ ์ฐ๋ฆฌ๊ฐ ๊ฑฐ๋ํ ์ฑ์ด๋ ๋ค๋ฅธ ๊ฒ์ด ํ์ํ๋ค๊ณ ์๊ฐํ์ง ์์ง๋ง TodoMVC์ ์ ์ฌํ ๋ณต์ก์ฑ์ด ์ถฉ๋ถํด์ผํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์๋๋ฐฉ์ด "์ด๋ฐ ์์ผ๋ก ๋ ์ํ ์ ์๋ค"๊ณ ๋งํ ์ ์์ ์ ๋๋ก ์ถฉ๋ถํด์ผ ํฉ๋๋ค.
@Hixie ์ค์ ์ฑ์ด ์ ๊ทผ ๋ฐฉ์์ ๋น๊ตํ๋๋ก ์์ฒญํ๋ ๋ฐ ๊ฒฐํจ์ด ์์ต๋๋ค.
๋ ๊ฐ์ง ๊ฒฐํจ์ด ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์์ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฑํ ์ ์์ต๋๋ค.
final snapshot = keyword StreamBuilder();
๊ตฌํ๋์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋ค.
POC์ ํ๋ก๋์ ์ฝ๋๋ฅผ ๋น๊ตํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ๋ ํ๋จํ ์ ์์ต๋๋ค.
์ค์ฉ์ด ์์ ๋ ์ค๋ฅ๋ฅผ ์ง์ ํ๋ ์ปดํ์ผ๋ฌ ํตํฉ์ด ์๊ธฐ ๋๋ฌธ์ "ํํฌ๋ฅผ ์กฐ๊ฑด๋ถ๋ก ํธ์ถํ ์ ์์ต๋๋ค"์ ๊ฐ์ ํญ๋ชฉ์ด ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ด์ง ์ฌ๋ถ๋ฅผ ํ๊ฐํ ์ ์์ต๋๋ค.
๋์์ธ์ ์ฑ๋ฅ์ ํ๋จํ๊ณ , API ์ฌ์ฉ์ฑ์ ํ๊ฐํ๊ณ , ๊ตฌํํ๊ธฐ ์ ์ ๊ตฌํํ๋ ๊ฒ... ๋ชจ๋ API ๋์์ธ์ ์ผ๋ถ์ ๋๋ค. ๋ด ์ง์ฅ์ ์ค์ ๊ฒ์ ํ์ํฉ๋๋ค. :-) (Flutter ์์: ์ฐ๋ฆฌ๊ฐ dart:ui๋ฅผ ๋ง๋ค๊ธฐ ์ ์ RenderObject์ RenderBox et al์ ์ฒ์ ๋ช ์ฒ ๋ผ์ธ์ด ๊ตฌํ๋์๋ค๋ ๊ฒ์ ์๊ณ ๊ณ์ จ์ต๋๊น?)
๊ทธ๊ฒ์ ๋น์ ์ด ๋ถ๊ฐ๋ฅํ ๊ฒ์ ์๊ตฌํ๋ค๋ ์ฌ์ค์ ๋ฐ๊พธ์ง ์์ต๋๋ค.
์ฌ๊ธฐ์์ ์ ์๋ ์ผ๋ถ๋ ์ธ์ด ๋๋ ๋ถ์๊ธฐ์ ์ผ๋ถ์ ๋๋ค. ์ปค๋ฎค๋ํฐ์์ ๊ตฌํํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
ํ์คํ์ง ์์ต๋๋ค. ๋ค๋ฅธ ํ๋ ์์ํฌ์ ์ธ์ด๊ฐ ํญ์ API ๋์์ธ์ ํ๊ณ ์์ต๋๋ค. ์ฌ๊ธฐ์์๋ ํฌ๊ฒ ๋ค๋ฅด์ง ์๊ฑฐ๋ Flutter๊ฐ ๋ค๋ฅธ ์ธ์ด๋ณด๋ค API ๋์์ธ์ ์์ด ์๋์ ์ธ ์ฐจ์ด์ ์ด๋ ์ด๋ ค์์ด ์๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก ์ปดํ์ผ๋ฌ ๋๋ ๋ถ์๊ธฐ ์ง์ ์์ด ์ํํ๋ฉฐ ๊ฐ๋ ์ฆ๋ช ์ผ ๋ฟ์ ๋๋ค.
๋๋ 3๊ฐ์ ์ ๋๋ฉ์ด์ ์ ์ ํ์ฉํ๋ '๋ณต์กํ' ์ ๋๋ฉ์ด์ ์๋๋ฆฌ์ค์ ์๋ฅผ ๋ง๋ค์์ผ๋ฉฐ, ์์ฉ๊ตฌ์ ์ํฐ๋ฆฌ๋ก ์๋นํ ๋ก๋๋์์ต๋๋ค.
์ค์ํ ๊ฒ์ ์์ ์์น๋ก ํ๋ ์ค๋ ๋ฐฑ(๋ชจ๋ ์์์ ์์ ฏ ์ ๊ฑฐ)์ด ํ์ํ ์ ๋๋ฉ์ด์ ์ด๋ z์ถ์ ํ์ , ๋จ์ผ ์ถ์ ํฌ๊ธฐ ์กฐ์ ๋๋ IW์์ ๋ค๋ฃจ์ง ์๋ ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก๊ฐ ํ์ํ ๋ชจ๋ ์ ๋๋ฉ์ด์ ์ ์ํํ ์ ์๋ค๋ ์ ์ ๋๋ค. ๋๋ ๊ทธ๊ฒ๋ค์ด ์ฌ๊ฐํ๊ฒ ๋ฐ์๋ค์ฌ์ง์ง ์์๊น๋ด(๋ด ๋์์ด๋๋ค์ด ํ๋ฃจ ์ข ์ผ ์ด ๋ฌผ๊ฑด์ ๋์๊ฒ ๊ฑด๋ค์ค ๊ฒ์ด์ง๋ง) ๊ทธ๋์ ๋ 'ํ์ค์ ์ธ ์ธ๊ณ'๋ฅผ ๋ง๋ค์์ต๋๋ค.
์ฌ๊ธฐ ๊ฐ๋จํ ๋น๊ณ๊ฐ ์์ต๋๋ค. ์ฌ๋ผ์ด๋๋ฅผ ์ด๊ณ ๋ซ์ ์ ์๋ 3๊ฐ์ ํจ๋์ด ์์ต๋๋ค. ๊ฐ๋ณ ์ํ๊ฐ ์๋ 3๊ฐ์ ์ ๋๋ฉ์ดํฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด ๊ฒฝ์ฐ์๋ AnimatorController์ ์ ์ฒด ์ ์ด๊ฐ ํ์ํ์ง ์์ต๋๋ค. TweenAnimationBuilder๋ ๊ด์ฐฎ์ง๋ง ํธ๋ฆฌ์ ์ค์ฒฉ๋๋ ๊ฒฐ๊ณผ๋ ๋งค์ฐ ๋ฐ๋์งํ์ง ์์ต๋๋ค. ํจ๋์ด ์๋ก ๊ฐ์ ์ข
์๋์ด ์๊ธฐ ๋๋ฌธ์ TAB๋ฅผ ํธ๋ฆฌ ์๋์ ์ค์ฒฉํ ์ ์์ต๋๋ค. AnimatedContainer๋ ๊ฐ ํจ๋์ด ํ๋ฉด์์ ๋ฏธ๋๋ฌ์ ธ์ผ ํ๊ณ "๋๋ฌ๋ถ์ง" ์๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์๋ ์ต์
์ด ์์ต๋๋ค.
https://i.imgur.com/BW6M3uM.gif
class _SlidingPanelViewState extends State<SlidingPanelView> with TickerProviderStateMixin {
AnimationController leftMenuAnim;
AnimationController btmMenuAnim;
AnimationController rightMenuAnim;
<strong i="12">@override</strong>
void initState() {
// Here I have to pass vsync to AnimationController, so I have to include a SingleTickerProviderMixin and somewhat magically pass 'this' as vsync.
leftMenuAnim = AnimationController(duration: widget.slideDuration, vsync: this);
btmMenuAnim = AnimationController(duration: widget.slideDuration, vsync: this);
rightMenuAnim = AnimationController(duration: widget.slideDuration, vsync: this);
// Here I have to call forward 3 times, cause there's no way to automate this common setup behavior
leftMenuAnim.forward();
btmMenuAnim.forward();
rightMenuAnim.forward();
// Here I have to manually bind to build, cause there is encapsulate this common setup behavior
leftMenuAnim.addListener(() => setState(() {}));
btmMenuAnim.addListener(() => setState(() {}));
rightMenuAnim.addListener(() => setState(() {}));
super.initState();
}
// Following 2 fxn are a blind spot as far as compiler is concerned.
// Things may, or may not be implemented correctly, no warnings, no errors.
<strong i="13">@override</strong>
void dispose() {
btmMenuAnim.dispose();
leftMenuAnim.dispose();
rightMenuAnim.dispose();
super.dispose();
}
<strong i="14">@override</strong>
void didUpdateWidget(SlidingPanelView oldWidget) {
if (leftMenuAnim.duration != widget.slideDuration) {
leftMenuAnim.duration = widget.slideDuration;
btmMenuAnim.duration = widget.slideDuration;
rightMenuAnim.duration = widget.slideDuration;
}
super.didUpdateWidget(oldWidget);
}
// End error-prone blind spot without a single line of unique code
// ~50 lines in we can start to see some unique code
void _toggleMenu(AnimationController anim) {
bool isOpen = anim.status == AnimationStatus.forward || anim.value == 1;
isOpen ? anim.reverse() : anim.forward();
}
<strong i="15">@override</strong>
Widget build(BuildContext context) {
double leftPanelSize = 320;
double leftPanelPos = -leftPanelSize * (1 - leftMenuAnim.value);
double rightPanelSize = 230;
double rightPanelPos = -rightPanelSize * (1 - rightMenuAnim.value);
double bottomPanelSize = 80;
double bottomPanelPos = -bottomPanelSize * (1 - btmMenuAnim.value);
return Stack(
children: [
//Bg
Container(color: Colors.white),
//Content Panel
Positioned(
top: 0,
left: leftPanelPos + leftPanelSize,
bottom: bottomPanelPos + bottomPanelSize,
right: rightPanelPos + rightPanelSize,
child: ChannelInfoView(),
),
//Left Panel
Positioned(
top: 0,
left: leftPanelPos,
bottom: bottomPanelPos + bottomPanelSize,
width: leftPanelSize,
child: ChannelMenu(),
),
//Bottom Panel
Positioned(
left: 0,
right: 0,
bottom: bottomPanelPos,
height: bottomPanelSize,
child: NotificationsBar(),
),
//Right Panel
Positioned(
top: 0,
right: rightPanelPos,
bottom: bottomPanelPos + bottomPanelSize,
width: rightPanelSize,
child: SettingsMenu(),
),
// Buttons
Row(
children: [
Button("left", ()=>_toggleMenu(leftMenuAnim)),
Button("btm", ()=>_toggleMenu(btmMenuAnim)),
Button("right", ()=>_toggleMenu(rightMenuAnim)),
],
)
],
);
}
}
//Demo helpers
Widget Button(String lbl, VoidCallback action) => FlatButton(child: Text(lbl), onPressed: action, color: Colors.grey);
Widget ChannelInfoView() => _buildPanel(Colors.red);
Widget ChannelMenu() => _buildPanel(Colors.pink);
Widget SettingsMenu() => _buildPanel(Colors.blue);
Widget NotificationsBar() => _buildPanel(Colors.grey);
Widget _buildPanel(Color c) => Container(color: c, child: Container(color: Colors.white.withOpacity(.5)), padding: EdgeInsets.all(10));
๋ฐ๋ผ์ ํด๋น ๋ณธ๋ฌธ์ ์๋ 100๊ฐ ์ ๋์ ์ค ์ค ๋๋ต 40% ์ ๋๋ ์์ํ ์์ฉ๊ตฌ์ ๋๋ค. ํนํ ๋๋ฝ๋๊ฑฐ๋ ์๋ชป ์ ๋ ฅ๋ ํญ๋ชฉ์ด ์๋ 15์ค์ ์ฐพ๊ธฐ ํ๋ ๋ฒ๊ทธ๋ฅผ ์ ๋ฐํ ์ ์์ต๋๋ค.
StatefulProperty์ ๊ฐ์ ๊ฒ์ ์ฌ์ฉํ๋ฉด ์์ฉ๊ตฌ๋ฅผ 15% ์ ๋๋ก ์ค์ผ ์ ์์ต๋๋ค(์ฝ 25์ค ์ ์ฝ). ๊ฒฐ์ ์ ์ผ๋ก ์ด๊ฒ์ ๊ต๋ฌํ ๋ฒ๊ทธ ๋ฐ ์ค๋ณต ๋น์ฆ๋์ค ๋ก์ง ๋ฌธ์ ๋ฅผ ์์ ํ ํด๊ฒฐํ ์ ์์ง๋ง, ํนํ 10ํ ํํธ์ธ StatefulWidget์ด ํ์ํ๊ธฐ ๋๋ฌธ์ ์ฌ์ ํ ์ฝ๊ฐ ์ฅํฉํฉ๋๋ค.
'ํค์๋'์ ๊ฐ์ ๊ฒ์ ์ฌ์ฉํ๋ฉด ์์ฉ๊ตฌ ๋ผ์ธ์ ๋ณธ์ง์ ์ผ๋ก 0%๋ก ์ค์ ๋๋ค. ์์ ์ ์ ์ฒด ์ด์ ์ (๊ณ ์ ํ) ๋น์ฆ๋์ค ๋ก์ง๊ณผ ์๊ฐ์ ํธ๋ฆฌ ์์์ ์์ ์ ์์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก StatefulWIdget์ ํจ์ฌ ๋ ๋๋ฌผ๊ฒ ์ฌ์ฉํ๊ณ ๋๋ค์์ ๋ณด๊ธฐ๊ฐ 10~20% ๋ ์ฅํฉํ๊ณ ๋ ์ง์ค๋ฉ๋๋ค.
๋ํ ์์ ํจ๋ ์๋๋ฆฌ์ค๋ ์ค์ ์ธ๊ณ์ด๋ฉฐ ์ค์ ์ธ๊ณ์์ ๋ถ๋ช ํ ์ด ์ ๊ทผ ๋ฐฉ์์ ์ค์ ๋ก ์ข์ง ์์ผ๋ฏ๋ก ์ฌ์ฉํ์ง ์์์ผ๋ฉฐ ์ฝ๋ ๊ธฐ๋ฐ์์ ๋ณผ ์ ์์ต๋๋ค. ๋ํ ์ค์ฒฉ๋ ๋น๋๋ฅผ ์ฌ์ฉํ์ง๋ ์์ต๋๋ค. ๊ทธ ๋น๋๊ฐ ๋ณด๊ธฐ ํํ๊ฒ ๋ณด์ด๋ฏ๋ก ์ฌ์ฉ์๋ ๋ณผ ์ ์์ต๋๋ค.
IsOpen ์์ฑ์ ์ฌ์ฉํ๊ณ ์์ฒด์ ์ผ๋ก ์ด๋ฆฌ๊ณ ๋ซํ๋ ์ ์ฉ SlidingPanel ์์ ฏ์ ๋ง๋ค์์ต๋๋ค. ์ด๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ํน์ ๋์์ด ํ์ํ๊ณ ์ํ ์ ์ฅ ๋ ผ๋ฆฌ๋ฅผ ์ผ๋ถ ์ดํน์ ์์ ฏ์ผ๋ก ์ด๋ํ ๋ค์ ์ฌ์ฉํ๋ ์ด๋ฌํ ์ฌ์ฉ ์ฌ๋ก์ ๋ชจ๋ ๋จ์ผ ์๋ฃจ์ ์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์์ ์ ImplicitlyAnimatedWidget์ ์์ฑํฉ๋๋ค.
์ด๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ์ ์๋ํ์ง๋ง ์ฌ์ ํ ์๊ฐ๊ณผ ๋ ธ๋ ฅ์ด๋ฉฐ, ๋ง ๊ทธ๋๋ก ์ ๋๋ฉ์ด์ ์ด ์กด์ฌํ๋ ์ ์ผํ ์ด์ ๋ ์ ๋๋ฉ์ด์ ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋๋ฌด ์ด๋ ต๊ธฐ ๋๋ฌธ์ ๋๋ค(์ผ๋ฐ์ ์ผ๋ก ์ํ ์ ์ฅ ๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ๋๋ฌด ์ด๋ ต๊ธฐ ๋๋ฌธ์ ๋๋ค). ์๋ฅผ ๋ค์ด Unity ๋๋ AIR์์๋ ๋จ์ผ ์ถ์์ ํจ๋์ ์ด๋ํ๊ธฐ ์ํด ์ ์ฉ ํด๋์ค๋ฅผ ๋ง๋ค์ง ์์์ต๋๋ค. ์ด๊ฑฐ๋ ๋ซ๋ ์ฝ๋ ํ ์ค์ด๋ฉด ๋ฉ๋๋ค. ์ ์ฉ ์์ ฏ์ด ์ํํ ์์ ์ ์์ต๋๋ค. Flutter์์๋ AnimatorController์ ๋ถํธ์คํธ๋ํ ๋ฐ ๋ถํด๋ฅผ ์บก์ํํ๋ ์ ์ผํ ํฉ๋ฆฌ์ ์ธ ๋ฐฉ๋ฒ์ด๊ธฐ ๋๋ฌธ์ Flutter์์ ์ ์ฉ ์์ ฏ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค(TAB์ผ๋ก ์ค์ฒฉ, ์ค์ฒฉ, ์ค์ฒฉํ์ง ์์ผ๋ ค๋ ๊ฒฝ์ฐ)
์ฌ๊ธฐ์ ๋ด ์์ ์ ์ด๋ฐ ์ ํ์ ๊ฒ์ด ์ค์ ์ฌ๋ก๋ฅผ ์ฐพ๊ธฐ ์ด๋ ค์ด ์ด์ ๋ผ๋ ๊ฒ์ ๋๋ค. ๊ฐ๋ฐ์๋ก์ ์ฐ๋ฆฌ๋ ์ด๋ฌํ ๊ฒ๋ค์ด ์ฐ๋ฆฌ ์ฝ๋๋ฒ ์ด์ค์ ๋๋ฌด ๋ง์ด ์กด์ฌํ๋๋ก ํ ์ ์์ผ๋ฏ๋ก ์ด์์ ์ด์ง๋ ์์ง๋ง ํจ๊ณผ์ ์ธ ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋ณผ ๋ ์ด๋ฌํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์ ์ฉ๋๊ณ ๋ชจ๋ ๊ฒ์ด ๊ด์ฐฎ์ ๋ณด์ด์ง๋ง ํ์ด ๋ง๋ค๊ณ ์ ํ๋ ๊ฒ์ด ์๋ ์๋ ์๊ณ ๊ฑฐ๊ธฐ์ ๋๋ฌํ๋ ๋ฐ 20% ๋ ์ค๋ ๊ฑธ๋ ธ์ ์๋ ์์ต๋๋ค. ๋๋ฒ๊ทธํ๋ ๋ฐ ์ด๋ ค์์ด ์์ง๋ง, ์ด ์ค ์ด๋ ๊ฒ๋ ์ฝ๋๋ฅผ ๋ณด๋ฉด ๋ถ๋ช ํ์ง ์์ต๋๋ค.
์์ ์ฑ์ ์ํด ๋น๋๋ก ๋ง๋ ๋์ผํ ์ฌ์ฉ ์ฌ๋ก๊ฐ ์์ต๋๋ค. ์ค ์๊ฐ ํฌ๊ฒ ์ค์ด๋ค๊ณ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ์์ผ๋ฉฐ ์ธ๊ตญ ๊ฐ๋ ์ ๋ฐฐ์ธ ํ์๊ฐ ์์ต๋๋ค. RE TickerProviderMixin... ํ์ง๋ง ์ค์ฒฉ์ ์ฌํ ์ผ์ด๊ณ ๋ค์ํ ๋ณ์๊ฐ ํธ๋ฆฌ ์ ์ฒด์ ๋ฟ๋ ค์ง๋ ๋ฐฉ์(๋์ ์ข ๋ฃ ๊ฐ, ๊ฐ1, ๊ฐ2 ๋ฑ) ) ๋น์ฆ๋์ค ๋ก์ง์ ํ์ ์ด์์ผ๋ก ์ฝ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค.
```๋คํธ
ํด๋์ค _SlidingPanelViewState ํ์ฅ ์ํ
๋ถ์ธ isLeftMenuOpen = true;
๋ถ์ธ isRightMenuOpen = true;
๋ถ์ธ isBtmMenuOpen = true;
@์ฐ์ธํ๋ค
์์ ฏ ๋น๋(BuildContext ์ปจํ
์คํธ) {
TweenAnimationBuilder ๋ฐํ
ํธ์: ํธ์(์์: 0, ๋: isLeftMenuOpen ? 1: 0),
์ง์ ์๊ฐ: widget.slideDuration,
๋น๋: (_, leftAnimValue, __) {
TweenAnimationBuilder ๋ฐํ
ํธ์: ํธ์(์์: 0, ๋: isRightMenuOpen ? 1: 0),
์ง์ ์๊ฐ: widget.slideDuration,
๋น๋: (_, rightAnimValue, __) {
TweenAnimationBuilder ๋ฐํ
ํธ์: ํธ์(์์: 0, ๋: isBtmMenuOpen ? 1: 0),
์ง์ ์๊ฐ: widget.slideDuration,
๋น๋: (_, btmAnimValue, __) {
์ด์ค leftPanelSize = 320;
์ด์ค leftPanelPos = -leftPanelSize * (1 - leftAnimValue);
์ด์ค rightPanelSize = 230;
๋๋ธ rightPanelPos = -rightPanelSize * (1 - rightAnimValue);
์ด์ค bottomPanelSize = 80;
์ด์ค bottomPanelPos = -bottomPanelSize * (1 - btmAnimValue);
๋ฐํ ์คํ(
์ด๋ฆฐ์ด๋ค: [
//๋น์ง
์ฉ๊ธฐ(์์: Colors.white),
//์ฃผ ์ฝํ
์ธ ์์ญ
ํฌ์ง์
๋(
์๋จ: 0,
์ผ์ชฝ: leftPanelPos + leftPanelSize,
ํ๋จ: bottomPanelPos + bottomPanelSize,
์ค๋ฅธ์ชฝ: rightPanelPos + rightPanelSize,
์์: ChannelInfoView(),
),
//์ผ์ชฝ ํจ๋
์์น(
์๋จ: 0,
์ผ์ชฝ: leftPanelPos,
ํ๋จ: bottomPanelPos + bottomPanelSize,
๋๋น: leftPanelSize,
์์: ChannelMenu(),
),
//ํ๋จ ํจ๋
์์น(
์ผ์ชฝ: 0,
์ค๋ฅธ์ชฝ: 0,
ํ๋จ: bottomPanelPos,
๋์ด: bottomPanelSize,
์์: NotificationsBar(),
),
//์ค๋ฅธ์ชฝ ํจ๋
์์น(
์๋จ: 0,
์ค๋ฅธ์ชฝ: rightPanelPos,
ํ๋จ: bottomPanelPos + bottomPanelSize,
๋๋น: rightPanelSize,
์์: SettingsMenu(),
),
// ๋ฒํผ
์ด(
์ด๋ฆฐ์ด๋ค: [
๋ฒํผ("์ผ์ชฝ", () => setState(() => isLeftMenuOpen = !isLeftMenuOpen)),
๋ฒํผ("btm", () => setState(() => isBtmMenuOpen = !isBtmMenuOpen)),
๋ฒํผ("์ค๋ฅธ์ชฝ", () => setState(() => isRightMenuOpen = !isRightMenuOpen)),
],
)
],
);
},
);
},
);
},
);
}
}
๋ง์ง๋ง ๊ฒ์ ํฅ๋ฏธ๋กญ์ต๋๋ค... ์ ๋ ์๋ ๋น๋๊ฐ ์คํ์ด ์๋ ์์น ์ง์ ์์ ฏ ์ฃผ์์ ์์ด์ผ ํ๋ค๊ณ ์ ์ํ๋ ค๊ณ ํ์ง๋ง(๊ทธ๋ฆฌ๊ณ ์ฌ์ ํ ์ผ์ชฝ ๋ฐ ์ค๋ฅธ์ชฝ ํจ๋์ ๋ํด ์ ์ํ ๊ฒ์
๋๋ค) ๋งจ ์๋์ ์๋ ๊ฒ์ด ์ํฅ์ ๋ฏธ์น๋ค๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค. ์ธ ๊ฐ์ง ๋ชจ๋, ๋๋ ๊นจ๋ฌ์๋ค ๋น์ ์๊ฒ ์ผ์์ฃผ๋ ๋น๋ child
์ธ์ ์ค์ ๋ก ๋น์ ์ด ์ ๋ง๋ก ๋ชจ๋ ์ ์งํ๊ธฐ ์ํ๊ธฐ ๋๋ฌธ์, ์ถฉ๋ถํ์ง Container
์ Row
๋ฅผ ํตํด ์ผ์ ์ ๋น๋. ์ฒซ ๋ฒ์งธ ๋น๋ ์์ ๋ง๋ค ์ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
์ฌ๊ธฐ์ ๋ด ์์ ์ ์ด๋ฐ ์ ํ์ ๊ฒ์ด ์ค์ ์ฌ๋ก๋ฅผ ์ฐพ๊ธฐ ์ด๋ ค์ด ์ด์ ๋ผ๋ ๊ฒ์ ๋๋ค. ๊ฐ๋ฐ์๋ก์ ์ฐ๋ฆฌ๋ ์ด๋ฌํ ๊ฒ๋ค์ด ์ฐ๋ฆฌ ์ฝ๋๋ฒ ์ด์ค์ ๋๋ฌด ๋ง์ด ์กด์ฌํ๋๋ก ํ ์ ์์ผ๋ฏ๋ก ์ด์์ ์ด์ง๋ ์์ง๋ง ํจ๊ณผ์ ์ธ ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ๋ณผ ๋ ์ด๋ฌํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์ ์ฉ๋๊ณ ๋ชจ๋ ๊ฒ์ด ๊ด์ฐฎ์ ๋ณด์ด์ง๋ง ํ์ด ๋ง๋ค๊ณ ์ ํ๋ ๊ฒ์ด ์๋ ์๋ ์๊ณ ๊ฑฐ๊ธฐ์ ๋๋ฌํ๋ ๋ฐ 20% ๋ ์ค๋ ๊ฑธ๋ ธ์ ์๋ ์์ต๋๋ค. ๋๋ฒ๊ทธํ๋ ๋ฐ ์ด๋ ค์์ด ์์ง๋ง, ์ด ์ค ์ด๋ ๊ฒ๋ ์ฝ๋๋ฅผ ๋ณด๋ฉด ๋ถ๋ช ํ์ง ์์ต๋๋ค.
์ฐธ๊ณ ๋ก ์ด๊ฒ์ ์ฌ๊ณ ๊ฐ ์๋๋๋ค. ์ด๊ฒ์ ๋งค์ฐ ์๋์ ์ผ๋ก ์ค๊ณ๋ ๊ฒ์ ๋๋ค. ์ด๋ฌํ ์์ ฏ์ ์์ฒด ์์ ฏ์ผ๋ก ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ์ด ํฅ์๋ฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ด๊ฒ์ด ์ฌ๋๋ค์ด Flutter๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ ๋งค์ฐ ์๋ํ์ต๋๋ค. ์ด๊ฒ์ ์์์ "Flutter์ ๋์์ธ ์ฒ ํ์ ํฐ ๋ถ๋ถ์ ์ฌ๋๋ค์ ์ฌ๋ฐ๋ฅธ ์ ํ์ผ๋ก ์๋ดํ๋ ๊ฒ"์ด๋ผ๊ณ ์ธ๊ธํ์ ๋ ์ธ๊ธํ ๊ฒ์ ๋๋ค.
๋๋ ์๋ ๋น๋๊ฐ ์คํ๋ณด๋ค๋ ๋ฐฐ์น๋ ์์ ฏ ์ฃผ์์ ์์ด์ผ ํ๋ค๊ณ ์ ์ํ๋ ค๊ณ ํ์ต๋๋ค(๊ทธ๋ฆฌ๊ณ ๋๋ ์ฌ์ ํ ์ผ์ชฝ ๋ฐ ์ค๋ฅธ์ชฝ ํจ๋์ ๋ํด ์ ์ํ ๊ฒ์ ๋๋ค)
๊ฐ๊ฒฐํจ์ ์ํด ์ค์ ๋ก ์๋ตํ์ง๋ง ์ผ๋ฐ์ ์ผ๋ก ์ฌ๊ธฐ์ Content ์ปจํ ์ด๋๊ฐ ํ์ํ๊ณ 3๊ฐ์ง ๋ฉ๋ด ๋ชจ๋์ ํฌ๊ธฐ๋ฅผ ์ฌ์ฉํ์ฌ ์์ฒด ์์น๋ฅผ ์ ์ํฉ๋๋ค. ์ฆ, 3๊ฐ ๋ชจ๋๊ฐ ํธ๋ฆฌ์ ๋งจ ์์ ์์ด์ผ ํ๋ฉฐ, ๋ค์ ๋น๋ํ๋ ๊ฒฝ์ฐ ์ ์ฒด ๋ณด๊ธฐ๊ฐ ํ์ํ๋ฉฐ ์ฃผ์๋ฅผ ๋์๋ค๋์ง ์๊ณ ๋ค์ ๋น๋ํด์ผ ํฉ๋๋ค. ์ด๊ฒ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ณ ์ ์ ์ธ ๋ฐ์คํฌํ ์คํ์ผ์ ์ค์บํด๋์ ๋๋ค.
๋ฌผ๋ก ์ฐ๋ฆฌ๋ ํธ๋ฆฌ๋ฅผ ๋ถํดํ ์ ์์ต๋๋ค(ํญ์ ์ ํ ์ฌํญ). ์ฐ๋ฆฌ๋ ๋ ํฐ ์์ ฏ์ ๋ง์ด ์ฌ์ฉํ์ง๋ง ์ค์ ๋ก ํ ๋์ grokability๋ฅผ ํฅ์์ํค๋ ๊ฒ์ ๋ณธ ์ ์ด ์์ต๋๋ค. ๋ ์๊ฐ ๊ทธ๊ฒ์ ๋ํด ์ํํด์ผ ํ๋ ์ถ๊ฐ์ ์ธ ์ธ์ง ๋จ๊ณ๊ฐ ์์ต๋๋ค. ๊ฐ๋ฆฌํค๋ค. ๋น์ ์ด ๋๋ฌด๋ฅผ ์ชผ๊ฐ๋ ์๊ฐ, ๊ฐ์๊ธฐ ๋ณ์ ํ ๋น์ ๋นต ๋ถ์ค๋ฌ๊ธฐ ํ์ ์ ๋ฐ๋ผ๊ฐ์ ์ฌ๊ธฐ์ ์ ๋ฌ๋๋ ๊ฒ์ด ๋ฌด์์ธ์ง ํ์ ํ๊ณ ์ ์ฒด๊ฐ ์ด๋ป๊ฒ ํจ๊ป ๋ค์ด๋ง๋์ง ํ์ ํฉ๋๋ค. ์ํ ๊ฐ๋ฅํ ๋๋ฌด๋ก ๋๋ฌด๋ฅผ ์ ์ํ๋ ๊ฒ์ ํญ์ ๋ด ๊ฒฝํ์์ ์ถ๋ก ํ๊ธฐ๊ฐ ๋ ์ฝ์ต๋๋ค.
์๋ง๋ ์ ์ฉ RenderObject์ ๋ํ ์ข์ ์ฌ์ฉ ์ฌ๋ก์ผ ๊ฒ์ ๋๋ค.
๋๋ ์์ ฏ ์๋ช ์ฃผ๊ธฐ์ ์ฐ๊ฒฐํ ์ ์๋ 3๊ฐ์ ์ฝ๊ฒ ๊ด๋ฆฌ๋๋ AnimatorObjects :D
์ด๋ฌํ ์์ ฏ์ ์์ฒด ์์ ฏ์ผ๋ก ์ฌ์ฉํ๋ฉด ์ฑ๋ฅ์ด ํฅ์๋ฉ๋๋ค.
์ฌ๊ธฐ์์ ๊ตฌ์ฒดํํ๊ธฐ ๋๋ฌธ์: ์ด ๊ฒฝ์ฐ ์ด๊ฒ์ ์ค์บํด๋์ด๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ํ์ ๋ณด๊ธฐ๋ ์ด๋ฏธ ์์ฒด ์์ ฏ์ ๋๋ค. ์ด ์ฌ๋์ ์์ ๋ฐฐ์น ๋ฐ ๋ฒ์ญ๋ง ๋ด๋นํฉ๋๋ค. ์์์ BottomMenu(), ChannelMenu(), SettingsView(), MainContent() ๋ฑ์ ๋๋ค.
์ด ๊ฒฝ์ฐ ์ฐ๋ฆฌ๋ ๋จ์ํ ์ด๋์ ๋ํ ์์ฉ๊ตฌ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ์์ฒด ํฌํจ๋ ์์ ฏ์ ๋ฌด๋ฆฌ๋ฅผ ์์ฒด ํฌํจ๋ ์์ ฏ์ ๋ ๋ค๋ฅธ ๋ ์ด์ด๋ก ๋ํํฉ๋๋ค. ๋๋ ์ด๊ฒ์ด ์ฑ๋ฅ ์น๋ฆฌ๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๊น? ์ด ๊ฒฝ์ฐ ์ฐ๋ฆฌ๋ ์ฐ๋ฆฌ๊ฐ ์ค์ ๋ก ํ๊ณ ์ถ์ ๊ฒ์ด ์๋๋ผ ํ๋ ์์ํฌ๊ฐ _์๊ฐํ๋_ ์ฐ๋ฆฌ๊ฐ ํ๊ณ ์ถ์ ๊ฒ, ์ฆ ๋ ๊ฐ๊ฒฐํ๊ณ ์ผ๊ด๋ ๋ฐฉ์์ผ๋ก ๋์ผํ ์ฑ๋ฅ์ ๋ทฐ๋ฅผ ์์ฑํ๋ ๊ฒ์ผ๋ก ๋ฐ์ด๋ถ์ด๊ณ ์์ต๋๋ค.
[ํธ์ง] ์ด ์ปจํ ์คํธ๋ฅผ ์ถ๊ฐํ๊ธฐ ์ํด ์์ ๋ฅผ ์ ๋ฐ์ดํธํ๊ฒ ์ต๋๋ค.
์ ์ฉ RenderObject๋ฅผ ์ ์ํ๋ ์ด์ ๋ ๋ ์ด์์์ ๋ ์ข๊ฒ ๋ง๋ค๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋๋ ์ ๋๋ฉ์ด์ ์ธก๋ฉด์ด ์ํ ์ ์ฅ ์์ ฏ์ ์์ ๊ฒ์ด๋ผ๋ ๋ฐ ๋์ํฉ๋๋ค. ์คํ ์ํ์ ์ฌ์ฉํ๋ ๋์ 3๊ฐ์ 0..1 ๋๋ธ(value1, value2, value3)์ ๋ ๋ ๊ฐ์ฒด๋ก ์ ๋ฌํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ๋๋ถ๋ถ ์ด ํ ๋ก ์ ๋ถ์์ ์ธ ๊ฒ์ ๋๋ค. ์ด ์์ ์ ์ํํ๋ ์์ ์์ ์ํ ์ ์ฅ ์์ ฏ์์ Hooks ๋๋ ์ด์ ์ ์ฌํ ๊ฒ์ผ๋ก ์ ๊ณต๋๋ ๋จ์ํ๋ฅผ ์ํํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค.
๋ ๊ด๋ จ์ฑ์ด ๋์ ๋ฉ๋ชจ์์ @TimWhiting ์ ํ๋ก์ ํธ์ ๋ํ ๋ฐ๋ชจ๋ฅผ ๋ง๋๋ ๋ฐ ๊ท ์ด์ด ์์์ต๋๋ค: https://github.com/TimWhiting/local_widget_state_approaches/pull/1
Hooks ๋ฒ์ ์ ์ด๋ป๊ฒ ์๊ฒผ๋์ง ๊ถ๊ธํฉ๋๋ค. ํนํ ์ฑ๋ฅ ํน์ฑ์ ์ ์งํ๋ ๊ฒ(๋๋ ๊ฐ์ ํ๋ ๊ฒ; ํ์ฌ ์ต์ ์ด ์๋ ๊ณณ์ ๋ณด์ฌ์ฃผ๋ ์ฃผ์์ด ์์)์ ๋ ๊ฐ๋จํ๊ฒ ๋ง๋๋ ์ข์ ๋ฐฉ๋ฒ์ ๋ณผ ์ ์์์ง ํ์ ์ด ์์ง ์์ต๋๋ค.
(๋จ์ํํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ฐพ์ ๊ฒฝ์ฐ ์ฌ๊ธฐ์์ ์ํํ ๊ฒ์ธ์ง ๋๋ ์๋ฃํ๊ธฐ ์ ์ ํด๊ฒฐํด์ผ ํ ์ค์ํ ์ฌํญ์ด ๋๋ฝ๋ ๊ฒ์ธ์ง๋ ๋งค์ฐ ๊ถ๊ธํฉ๋๋ค.)
์ด ์์์ ๋ณต์ ํญ๋ชฉ์ด ์ค์ํฉ๋๊น? ๋๋ ๊ทธ๊ฒ ๋๋ฌธ์ ์ด๋ ค์์ ๊ฒช๊ณ ์์ผ๋ฉฐ RestorationMixin์ด ๋ฌด์์ ํ๋์ง์กฐ์ฐจ ๋ชจ๋ฆ ๋๋ค. ๋๋ ๊ทธ๊ฒ์ด ... ๋๋ฅผ ์ํด ์ด๊ฒ์ ์ดํดํ๋ ๋ฐ ์ฝ๊ฐ์ ์๊ฐ์ด ๊ฑธ๋ฆด ๊ฒ์ด๋ผ๊ณ ๊ฐ์ ํฉ๋๋ค. ๋๋ Remi๊ฐ 4์ด ๋ง์ ํํฌ ๋ฒ์ ์ ์์ฑํ ๊ฒ์ด๋ผ๊ณ ํ์ ํฉ๋๋ค. :)
StatefulHookWidget
๊ฐ ์๋ HookWidget
๋ฅผ ์ฌ์ฉํ์ฌ ๋ณต์ API๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ฌ ์ง์๋์ง ์์ต๋๋ค.
์ด์์ ์ผ๋ก๋ ๋ณ๊ฒฝํ ์ ์์ด์ผ ํฉ๋๋ค.
final value = useState(42);
์์ผ๋ก:
final value = useRestorableInt(42);
๊ทธ๋ฌ๋ ํ์ฌ ๋ณต์ API๋ ์ค์ ๋ก ํํฌ๋ฅผ ์ผ๋์ ๋๊ณ ์ค๊ณ๋์ง ์์๊ธฐ ๋๋ฌธ์ ์ฝ๊ฐ์ ์๊ฐ์ด ํ์ํฉ๋๋ค.
์ฐธ๊ณ ๋ก React hooks์๋ ์ผ๋ฐ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉ๋๋ "ํต์ฌ" ๊ธฐ๋ฅ์ด ์์ต๋๋ค.
int userId;
Future<User> user = useMemo(() => fetchUser(id), [id]);
์ฌ๊ธฐ์ ์ด ์ฝ๋๋ "์ฝ๋ฐฑ ๊ฒฐ๊ณผ๋ฅผ ์บ์ํ๊ณ ๋ฐฐ์ด ๋ด๋ถ์ ๋ณ๊ฒฝ ์ฌํญ์ด ์์ ๋๋ง๋ค ์ฝ๋ฐฑ์ ๋ค์ ํ๊ฐํฉ๋๋ค"๋ฅผ ์๋ฏธํฉ๋๋ค.
Flutter_hooks๋ ์ด๊ฒ์ 1๋1๋ก ๋ค์ ๊ตฌํํ์ง๋ง(๋จ์ง ํฌํธ์ผ ๋ฟ์ด๋ฏ๋ก) Flutter์ ์ต์ ํ๋ ์ฝ๋์ ๋ํด ์ด๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ํ๊ณ ์ถ์ ์ผ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ์๋ง๋ ๋ค์์ ์ํ ๊ฒ์ ๋๋ค:
int userId;
Future<User> user = useMemo1(id, (id) => fetchUser(id));
๋์ผํ ์์ ์ ์ํํ์ง๋ง ๋ชฉ๋ก ํ ๋น์ ํผํ๊ณ ๊ธฐ๋ฅ ํด์ ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์๋ ฅ์ ์ ๊ฑฐํฉ๋๋ค.
์ด ๋จ๊ณ์์๋ ์ค์ํ์ง ์์ง๋ง ์๋ฅผ ๋ค์ด flutter_hooks
๋ฅผ ์ฌ์ฉํ ๊ณํ์ด๋ผ๋ฉด ์ธ๊ธํ ๊ฐ์น๊ฐ ์์ต๋๋ค.
@Hixie ์ ๋๋ฉ์ด์ ์์ ๋ฅผ ํํฌ๋ก ์ด์ํ์ต๋๋ค.
ํฅ๋ฏธ๋ก์ด ์์์ต๋๋ค. ์๊ฐํด์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค!
๊ธฐ๋ณธ์ ์ผ๋ก "active" ๋ฐ "duration"์ ๊ตฌํ์ด ์ด๋์๋ ์๋ค๋ ์ ์์ ์ข์ ์์
๋๋ค(๊ทธ๋ฆฌ๊ณ ๊ทธ ์ ์์ ์๋ก ์์กดํจ).
์์ ๊น์ง ์๋ง์ "if (active)" / "controller.repeat" ํธ์ถ์ด ์์์ต๋๋ค.
๋ฐ๋ฉด ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ชจ๋ ๋ ผ๋ฆฌ๊ฐ ์ ์ธ์ ์ผ๋ก ์ฒ๋ฆฌ๋๊ณ ์ค๋ณต ์์ด ํ ๊ณณ์ ์ง์ค๋ฉ๋๋ค.
์ด ์์ ๋ ๋ํ ๊ฐ์ฒด๋ฅผ ์ฝ๊ฒ ์บ์ํ๊ธฐ ์ํด ํํฌ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. ์ด๋ ExpensiveWidget์ ๋๋ฌด ์์ฃผ ์ฌ๊ตฌ์ถํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
const ์์ฑ์์ ์ด์ ์ ์ป์ง๋ง ๋์ ๋งค๊ฐ๋ณ์์ ํจ๊ป ์๋ํฉ๋๋ค.
์ฐ๋ฆฌ๋ ๋ํ ๋ ๋์ ํซ ๋ฆฌ๋ก๋๋ฅผ ์ป์ต๋๋ค. ๋ฐฐ๊ฒฝ์์ Timer.periodic ๊ธฐ๊ฐ์ ๋ณ๊ฒฝํ๊ณ ์ฆ์ ๋ณ๊ฒฝ ์ฌํญ์ ํ์ธํ ์ ์์ต๋๋ค.
@rrousselGit ๋งํฌ๊ฐ ์์ต๋๊น? @TimWhiting ์ ์ ์ฅ์์์ ์๋ก์ด ๊ฒ์ ๋ณด์ง ๋ชปํ์ต๋๋ค.
StatefulHookWidget
๊ฐ ์๋HookWidget
๋ฅผ ์ฌ์ฉํ์ฌ ๋ณต์ API๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ฌ ์ง์๋์ง ์์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์ด๋ค ์๋ฃจ์ ์ ์ ์ํ๋ , ๋ชจ๋ ๋ง์ง๋ง ๋ฏน์ค์ธ์ ๋ํด ์ ํ์๊ฐ ์๋๋ก ํด์ผ ํฉ๋๋ค. ๋๊ตฐ๊ฐ TickerProviderStateMixin ๋๋ RestorationMixin๊ณผ ๊ฐ์ mixin์ ๋์ ํ๋ ๋ค๋ฅธ ํจํค์ง์ ํจ๊ป ์ฐ๋ฆฌ ์๋ฃจ์ ์ ์ฌ์ฉํ๋ ค๋ ๊ฒฝ์ฐ ๊ทธ๋ ๊ฒ ํ ์ ์์ด์ผ ํฉ๋๋ค.
https://github.com/TimWhiting/local_widget_state_approaches/pull/3
๋์ํ์ง๋ง ๋๋ ๊ทธ๊ฒ์ ๋ํด ๊ฑฑ์ ํ์ง ์์ต๋๋ค. useAnimationController๋ ์๋ฅผ ๋ค์ด ์ฌ์ฉ์๊ฐ SingleTickerProvider์ ๋ํด ์ ๊ฒฝ ์ธ ๊ฒ์ ์๊ตฌํ์ง ์์ต๋๋ค.
AutomaritKeepAlive๋ ๋์ผํ ์น๋ฃ๋ก๋ถํฐ ํํ์ ๋ฐ์ ์ ์์ต๋๋ค.
๋ด๊ฐ ์๊ฐํ ๊ฒ ์ค ํ๋๋ "useKeepAlive(bool)" ํํฌ๋ฅผ ๊ฐ๋ ๊ฒ์
๋๋ค.
์ด๊ฒ์ mixin๊ณผ "super.build(context)"๋ฅผ ๋ชจ๋ ํผํฉ๋๋ค(ํ์๋ ์๋นํ ํผ๋์ค๋ฝ์ต๋๋ค)
๋ ๋ค๋ฅธ ํฅ๋ฏธ๋ก์ด ์ ์ ๋ฆฌํฉํ ๋ง ์ค์ ํ์ํ ๋ณ๊ฒฝ ์ฌํญ์ ๋๋ค.
์๋ฅผ ๋ค์ด ์์ ์ ๊ทผ ๋ฐฉ์๊ณผ ํํฌ์ ๋ํด TickerMode
๋ฅผ ๊ตฌํํ๋ ๋ฐ ํ์ํ ๋ณ๊ฒฝ ์ฌํญ ๊ฐ์ ์ฐจ์ด๋ฅผ ๋น๊ตํ ์ ์์ต๋๋ค.
diff์ ๋ค๋ฅธ ๊ฒ๋ค์ด ์์ฌ ์์ง๋ง, ์ฐ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ ์ฌ์ค์ ์ ์ ์์ต๋๋ค.
์ด๊ฒ์ ๋งค์ฐ ์ค์ํ๋ฉฐ ์ด ์คํ์ผ์ ์์ฒด ํฌํจ๋ ์ํ ๊ฐ์ฒด์์ ์ค์ํ ์น๋ฆฌ์ ๋๋ค. ํธ๋ฆฌ์ ์ค์ฒฉ ์ปจํ ์คํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ๋ชจ๋ ๊ฒ์ ๋ฆฌํฉํ ๋งํ๊ณ ๋ณ๊ฒฝํ๋ ๊ฒ์ ๊ทผ๋ณธ์ ์ผ๋ก ๋ ์ด๋ ต๊ณ ๋ณต์กํฉ๋๋ค. ์ด๋ ํ๋ก์ ํธ๊ฐ ์งํ๋๋ ๋์ ์ฝ๋๋ฒ ์ด์ค์ ์ต์ข ํ์ง์ ๋ณด์ด์ง ์์ง๋ง ํ์คํ ์ํฅ์ ๋ฏธ์นฉ๋๋ค.
๋์!
๋ํ ์ฝ๋ ๊ฒํ ๋ฅผ ํจ์ฌ ์ฝ๊ฒ ์ฝ์ ์ ์์ต๋๋ค.
final value = useSomething();
+ final value2 = useSomethingElse();
return Container(
color: value.color,
- child: Text('${value.name}'),
+ child: Text('${value.name} $value2'),
);
๋:
return SomethingBuilder(
builder: (context, value) {
- return Container(
- color: value.color,
- child: Text('$value'),
+ return SomethingElseBuilder(
+ builder: (context, value2) {
+ return Container(
+ color: value.color,
+ child: Text('${value.name} $value2'),
+ );
+ }
);
},
);
๋ ๋ฒ์งธ diff์์๋ Container
๊ฐ ๋ณ๊ฒฝ๋์ง ์๊ณ Text
๋ณ๊ฒฝ๋์๋ค๋ ๊ฒ์ด ๋ช
ํํ์ง ์์ต๋๋ค.
@rrousselGit ํค์๋ ์ง์์ผ๋ก ์ด๋ป๊ฒ ๋ณด์ผ ์ ์๋์ง ๋ํ๋ด๋ ๋ฒ์ ์ ์๋ํ๊ณ ์ํํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ด๋ผ๊ณ ์๊ฐํ์ญ๋๊น? ์ ์ฉ 'use' ํค์๋๋ง ์๋ ํํฌ์ ์ค์ง์ ์ผ๋ก ์ ์ฌํฉ๋๊น, ์๋๋ฉด ๋ ์ฝ๊ฒ ๋ฐ๋ผ๊ฐ ์ ์์ต๋๊น? useEffect, useMemo ๋ฑ๊ณผ ๊ฐ์ ์ธ๊ตญ ๊ฐ๋ ์ด ๋๋ฌด ๋ง๊ธฐ ๋๋ฌธ์ ํํฌ ์ ๊ทผ ๋ฐฉ์์ ๊ท ์ผํ๊ฒ ๋น๊ตํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค.
์ฃผ๋ชฉํด์ผ ํ ๋ ๋ค๋ฅธ ์ฌํญ์ ์ด ๋ชจ๋ ๊ฒ์ด ์ค์ ๋ก ๋ฌธ์ ๊ฐ ๋๋ ๊ณณ์ ์ฌ๋ฌ ์์ ฏ์ด ์๋ ๊ฒฝ์ฐ ์ด '์์ ์คํ ํ' ๋ ผ๋ฆฌ๋ฅผ ๊ณต์ ํ๋ ๋ฐ ๋ชจ๋ ํ์ํ์ง๋ง ๊ฒฐ๊ณผ ์์์ ์์ ํ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ค๋ ๊ฒ์ ๋๋ค. ํํฌ ์คํ์ผ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ์ฌ์ฌ์ฉํ ์ ์๋ ๋ ผ๋ฆฌ๋ฅผ ๋ฌถ์ด์ ์ฌ์ฉํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ์ฐ๋ฆฌ๊ฐ ๊ฐ์ํ๋ ์ํคํ ์ฒ ์ฝ๋๊ฐ ์์ต๋๋ค. ์ ๋ง ๋ถ๊ฐ์ง๋ก ์ ์ด๋ฉฐ ์ ์ฐํฉ๋๋ค.
Stateful ์ ๊ทผ ๋ฐฉ์์์ ์ฐ๋ฆฌ๋
๋ด๊ฐ ์๊ฐํ๋ ํต์ฌ์ ํ์์ ๊ฒฝ์ฐ ์ฆ์ ์ํคํ ์ฒ ๋ฌธ์ ๊ฐ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ด๊ฒ์ ๋ด ํธ๋ฆฌ์ ์ด๋์ ๋ฃ์ด์ผ ํ๋์ง, ์ด๊ฒ์ ๊ฐ์ฅ ์ ์บก์ํํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋น๋์ฌ์ผ ํฉ๋๊น, ์๋๋ฉด ์ฌ์ฉ์ ์ ์ ์์ ฏ์ด์ด์ผ ํ ๊น์? ์ ์์ ๊ฒฝ์ฐ ์ด ์ฌ์ฌ์ฉ๋ ๋ ผ๋ฆฌ ๋ฉ์ด๋ฆฌ๋ฅผ ์ ์ฅํ ํ์ผ์ด ์ ์ผํ ๊ฒฐ์ ์ด๋ฏ๋ก ํธ๋ฆฌ์ ์ ํ ์ํฅ์ด ์์ต๋๋ค. ์ด๊ฒ์ ์ด๋ฌํ ๋ก์ง ์บก์ํ ์ค ๋ช ๊ฐ์ง๋ฅผ ํจ๊ป ์ฌ์ฉํ๊ฑฐ๋ ๊ณ์ธต ๊ตฌ์กฐ์์ ์์๋๋ก ์ด๋ํ๊ฑฐ๋ ํ์ ์์ ฏ์ผ๋ก ์ด๋ํ๋ ค๋ ๊ฒฝ์ฐ ๋ฑ ๊ตฌ์กฐ์ ์ผ๋ก ๋งค์ฐ ์ข์ต๋๋ค.
๋๋ ๊ฒฐ์ฝ ์ ๋ฌธ ๊ฐ๋ฐ์๊ฐ ์๋๋๋ค. ๊ทธ๋ฌ๋ ๋ ผ๋ฆฌ ๋ฅผ
Vue.js๋ฅผ ์ค๋ซ๋์ ์ฌ์ฉํ์ง ์์์ง๋ง ๋ค์ ๋ฒ์ ์ ์ํ ์์ฒด API(Hooks์์ ์๊ฐ์ ๋ฐ์)๋ ์์ผ๋ฏ๋ก ํ ๋ฒ ์ดํด๋ณด๋ ๊ฒ์ด ์ข์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ CMIIW๋ ๋ฐ์ ํํฌ์ ๊ท์น(์กฐ๊ฑด๋ถ ์ฌ์ฉํ์ง ์์)์ด Composition API์ ์ ์ฉ๋์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ฐ๋ผ์ ๊ท์น์ ์ํํ๊ธฐ ์ํด ๋ฆฐํฐ๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ต๋๋ค.
๋ค์ ๋๊ธฐ๋ถ์ฌ ์น์ ์ ์ฌ๊ธฐ์์ OP๋ฅผ ๊ฐ๋ ฅํ๊ฒ ๊ฐํํฉ๋๋ค.
๋๊ธฐ ๋ถ์ฌ
๋ณต์กํ ๊ตฌ์ฑ ์์์ ์ฝ๋๋ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๊ธฐ๋ฅ์ด ์ฆ๊ฐํจ์ ๋ฐ๋ผ ์ถ๋ก ํ๊ธฐ๊ฐ ๋ ์ด๋ ค์์ง๋๋ค. ์ด๊ฒ์ ํนํ ๊ฐ๋ฐ์๊ฐ ์์ ์ด ์์ฑํ์ง ์์ ์ฝ๋๋ฅผ ์ฝ์ ๋ ๋ฐ์ํฉ๋๋ค.
[๋ฌธ์ ๊ฐ ์์๋ค] ์ฌ๋ฌ ๊ตฌ์ฑ ์์ ๊ฐ์ ๋ ผ๋ฆฌ๋ฅผ ์ถ์ถํ๊ณ ์ฌ์ฌ์ฉํ๊ธฐ ์ํ ๊นจ๋ํ๊ณ ๋น์ฉ์ด ๋ค์ง ์๋ ๋ฉ์ปค๋์ฆ์ด ๋ถ์กฑํ์ต๋๋ค.
ํต์ฌ ๋จ์ด๋ "๊นจ๋ํ"๊ณผ "๋น์ฉ ๋ฌด๋ฃ"์ ๋๋ค. Mixin์ ๋น์ฉ์ด ๋ค์ง ์์ง๋ง ๊นจ๋ํ์ง๋ ์์ต๋๋ค. ๋น๋๋ ๊นจ๋ํ์ง๋ง ๊ฐ๋ ์ฑ ์ธก๋ฉด์์ ๋น์ฉ์ด ๋ค์ง ์์ผ๋ฉฐ, ๊ณ์ธต ๊ตฌ์กฐ ์ธก๋ฉด์์ ํธ๋ฆฌ๋ฅผ ์ด๋ํ๊ณ ์ถ๋ก ํ๊ธฐ๊ฐ ๋ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ์์ ฏ ์ํคํ ์ฒ ์ธก๋ฉด์์ ๋น์ฉ์ด ๋ค์ง ์์ต๋๋ค.
๋๋ ๋ํ ์ด๊ฒ์ด ๊ฐ๋ ์ฑ ๋ ผ์์์ ์ธ๊ธํ๋ ๊ฒ์ด ์ค์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. "_๊ฐ๋ฐ์๊ฐ ์์ฑํ์ง ์์ ์ฝ๋๋ฅผ ์ฝ์ ๋ ํนํ ๋ฐ์_". ๋ฌผ๋ก _๋น์ ์_ ์ค์ฒฉ ๋น๋๋ ์ฝ๊ธฐ ์ฌ์ธ ์ ์๊ณ , ๊ฑฐ๊ธฐ์ ๋ฌด์์ด ์๋์ง ์๊ณ ํธ์ํ๊ฒ ๊ฑด๋๋ธ ์ ์์ต๋๋ค. ๋ค๋ฅธ ์ฌ๋์ ์ฝ๋๋ฅผ ์ฝ๊ณ ์๋ ๊ฒ์ ๋๋ค. ๋น์ ์ด ๋ ํฐ ํ๋ก์ ํธ์์ ํ๋ ๊ฒ์ฒ๋ผ ๋๋ ๋ช ์ฃผ/mth ์ ์ ์ฝ๋๋ฅผ ์ฝ๊ณ ์๋ ๊ฒ์ ๋๋ค. ์ด๋ฌํ ๊ฒ๋ค์ ํ์ฑํ๊ณ ๋ฆฌํฉํ ๋งํ๊ธฐ ์ด๋ ต์ต๋๋ค.
๋ค๋ฅธ ํนํ ๊ด๋ จ ์น์ .
๋จ์ํ ๊ตฌ์ฑ ์์๋ฅผ ๊ฐ๋ ๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ ์ด์ :
... ๊ตฌ์ฑ ์์๋ฅผ ์์ฑํ๋ฉด ์ธํฐํ์ด์ค์ ๋ฐ๋ณต ๊ฐ๋ฅํ ๋ถ๋ถ๊ณผ ํด๋น ๊ธฐ๋ฅ์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ฝ๋ ์กฐ๊ฐ์ผ๋ก ์ถ์ถํ ์ ์์ต๋๋ค. ์ด๊ฒ๋ง์ผ๋ก๋ ์ฐ๋ฆฌ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ง๋ณด์์ฑ๊ณผ ์ ์ฐ์ฑ ์ธก๋ฉด์์ ๊ฝค ๋ฉ๋ฆฌ ๊ฐ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ์ ์งํฉ์ ์ธ ๊ฒฝํ์ ์ด๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ ์ ์์์ ์ ์ฆํ์ต๋๋ค. ํนํ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ ๋ง ์ปค์ง ๋ ์๋ฐฑ ๊ฐ์ ๊ตฌ์ฑ ์์๋ฅผ ์๊ฐํด ๋ณด์ญ์์ค. ์ด๋ฌํ ๋๊ท๋ชจ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ฒ๋ฆฌํ ๋ ์ฝ๋ ๊ณต์ ๋ฐ ์ฌ์ฌ์ฉ์ด ํนํ ์ค์ํฉ๋๋ค.
๋ ผ๋ฆฌ์ ๋จํธํ๋ฅผ ์ค์ด๊ณ ๋ ๊ฐ๋ ฅํ๊ฒ ์บก์ํํ๋ ๊ฒ์ด ์น๋ฆฌ์ธ ์ด์ :
๋จํธํ๋ ๋ณต์กํ ๊ตฌ์ฑ ์์๋ฅผ ์ดํดํ๊ณ ์ ์ง ๊ด๋ฆฌํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค. ์ต์ ์ ๋ถ๋ฆฌ๋ ๊ทผ๋ณธ์ ์ธ ๋ ผ๋ฆฌ์ ๋ฌธ์ ๋ฅผ ํ๋ฆฌ๊ฒ ํฉ๋๋ค. ๋ํ ํ๋์ ๋ ผ๋ฆฌ์ ๋ฌธ์ ์ ๋ํด ์์ ํ ๋ ๊ด๋ จ ์ฝ๋์ ๋ํ ์ต์ ๋ธ๋ก ์ฃผ์๋ฅผ ์ง์์ ์ผ๋ก "์ ํ"ํด์ผ ํฉ๋๋ค. ๋์ผํ ๋ ผ๋ฆฌ์ ๋ฌธ์ ์ ๊ด๋ จ๋ ์ฝ๋๋ฅผ ํจ๊ป ๋ฐฐ์นํ ์ ์๋ค๋ฉด ํจ์ฌ ์ข์ ๊ฒ์ ๋๋ค.
์ ๊ฐ ์ ์ถํ ๊ฒ ์ธ์ ๊ฐ์ ํ๋ ค๊ณ ํ๋ ํ์ค ์์ ์ ๋ํ ๋ค๋ฅธ ์ ์์ด ์๋์ง ๊ถ๊ธํฉ๋๋ค.
์ฌ๋๋ค์ด ์ฌ์ฉํ๊ณ ์ถ์ดํ๋ ์ถ๋ฐ์ ์ด๋ผ๋ฉด ํ๋ฅญํฉ๋๋ค. ๊ทธ๋ฌ๋ ํ์ฌ ๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ ์ฅํฉํ ํํ์ด๋ผ๊ณ ๋งํ๊ณ ์ถ์ต๋๋ค. ์ด ์์ ์์๋ ์ฌ์ฌ์ฉํ ์ฝ๋๊ฐ ๋ง์ง ์์ต๋๋ค. ๋ฐ๋ผ์ OP์ ์ค๋ช
๋ ๋๋ก ๋ฌธ์ ๋ฅผ ์ ๋ํ๋ด๋์ง ํ์คํ์ง ์์ต๋๋ค.
๊ฐ์ธ์ ์ผ๋ก ์๋ฃจ์
์์ ์ฐพ๊ณ ์ ํ๋ ํน์ฑ์ ํํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ข ๋ ์๊ฐํ๊ณ ์์๊ณ , ํ์ฌ Hooks ์ ์์์ ๋ณผ ์ ์๋ ํฐ ๋ฌธ์ ์ค ํ๋๋ฅผ ๊นจ๋ซ๊ฒ ๋์์ต๋๋ค. Flutter ํ๋ ์์ํฌ์ ๋ณํฉํ๊ณ ์ถ์ต๋๋ค: Locality and Encapsulation, ๋๋ ์คํ๋ ค ๋ถ์กฑํฉ๋๋ค. Hooks์ ๋์์ธ์ ์ ์ญ ์ํ๋ฅผ ์ฌ์ฉํฉ๋๋ค(์: ํ์ฌ ๋น๋ ์ค์ธ ์์ ฏ์ ์ถ์ ํ๋ ์ ์ ). IMHO ์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ํผํด์ผ ํ๋ ๋์์ธ ํน์ฑ์
๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ฐ๋ฆฌ๋ API๋ฅผ ๋
๋ฆฝ์ ์ผ๋ก ๋ง๋ค๋ ค๊ณ ํ๋ฏ๋ก ํ๋์ ๋งค๊ฐ๋ณ์๋ก ํจ์๋ฅผ ํธ์ถํ๋ฉด ํด๋น ๋งค๊ฐ๋ณ์ ์ธ๋ถ์ ๊ฐ์ผ๋ก ์๋ฌด ๊ฒ๋ ํ ์ ์๋ค๋ ํ์ ์ด ์์ด์ผ ํฉ๋๋ค(์ด๊ฒ์ด ์ฐ๋ฆฌ๊ฐ BuildContext๋ฅผ ์ ๋ฌํ๋ ์ด์ ์
๋๋ค. , useContext
ํด๋นํ๋ ๋์ ). ์ด๊ฒ์ด ๋ชจ๋ ์ฌ๋์ด ํ์ฐ์ ์ผ๋ก ์ํ๋ ํน์ฑ์ด๋ผ๊ณ ๋งํ๋ ๊ฒ์ด ์๋๋๋ค. ๋ฌผ๋ก ์ฌ๋๋ค์ Hooks๊ฐ ๋ฌธ์ ๊ฐ ๋์ง ์๋๋ค๋ฉด Hooks๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. Flutter์์ ๋ ๋ง์ ์์
์ ์ํํ์ง ์์ผ๋ ค๋ ๊ฒ์
๋๋ค. ์ฐ๋ฆฌ๊ฐ ์ ์ญ ์ํ(์: ๋ฐ์ธ๋ฉ์์)๋ฅผ ๊ฐ์ง ๋๋ง๋ค ์ฐ๋ฆฌ๋ ๊ฒฐ๊ตญ ๊ทธ๊ฒ์ ํํํ๊ฒ ๋์์ต๋๋ค.
Hooks๋ ์๋ง๋ ์ปจํ ์คํธ์ ๋ํ ๋ฉ์๋์ผ ์ ์์ง๋ง(๋๋ ๊ทธ๋ค์ด ์ด๊ธฐ ๋ฒ์ ์ ์์๋ค๊ณ ์๊ฐํฉ๋๋ค), ์์งํ, ์ ๋ ๊ทธ๊ฒ๋ค์ ํ์ฌ์ฒ๋ผ ๋ณํฉํ๋ ๋ฐ ๋ง์ ๊ฐ์น๋ฅผ ๋ณด์ง ๋ชปํฉ๋๋ค. ๋ณํฉ์ ์ฑ๋ฅ ํฅ์์ด๋ ํน์ ๋๋ฒ๊น ๋๊ตฌ๋ฅผ ์ฐ๊ฒฐํ๋ ๊ฒ๊ณผ ๊ฐ์ด ํจํค์ง๋ฅผ ๋ถ๋ฆฌํ๋ ๋ฐ ์ฝ๊ฐ์ ์ด๋๋ฒค์ณ๊ฐ ํ์ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ํผ๋๋ง ๊ฐ์ค์ํฌ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด ๋ฆฌ์ค๋๋ธ์ ์์ ํ๋ ๊ณต์์ ์ธ 3๊ฐ์ง ๋ฐฉ๋ฒ(AnimatedBuilder, StatefulWidget ๋ฐ useListenable)์ด ์์ต๋๋ค.
๊ทธ๋์ ๋์๊ฒ ๊ฐ์ผ ํ ๊ธธ์ ์ฝ๋ ์์ฑ์ ๊ฐ์ ํ๋ ๊ฒ์ ๋๋ค. ๋ช ๊ฐ์ง ๋ณ๊ฒฝ ์ฌํญ์ ์ ์ํ์ต๋๋ค. https://github.com/flutter/flutter/issues/63323
์ด๋ฌํ ์ ์์ด ์ค์ ๋ก ๊ตฌํ๋๋ค๋ฉด ์ฑ์์ ๋ง๋ฒ ๊ฐ์ SwiftUI์ ๊ฐ์ ์๋ฃจ์ ์ ์ํ๋ ์ฌ๋๋ค์ ๋ค๋ฅธ ์ฌ๋์ ๊ท์ฐฎ๊ฒ ํ์ง ์๊ณ ํจํค์ง๋ง ๋ง๋ค ์ ์์ต๋๋ค.
๋ด๊ฐ ์๋ ํ ์ด ๋ฌธ์ ์ ๋ํด ์์ง ๋์ํ์ง ์๊ธฐ ๋๋ฌธ์ ํํฌ์ ์ ํจ์ฑ์ ๋ํด ๋ ผ์ํ๋ ๊ฒ์ ํ ๋จ๊ณ์์ ์ฃผ์ ์์ ๋ฒ์ด๋ ๊ฒ์ ๋๋ค.
์ด ๋ฌธ์ ์์ ๋ช ๋ฒ ์ธ๊ธํ๋ฏ์ด ๋ค๋ฅธ ๋ง์ ์๋ฃจ์
์ด ์์ผ๋ฉฐ ๊ทธ ์ค ๋ค์๋ ์ธ์ด ๊ธฐ๋ฅ์
๋๋ค.
ํํฌ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ํํ๋ก ๊ตฌํํ๊ธฐ์ ๋น๊ต์ ์ ๋ ดํ ๋ค๋ฅธ ๊ธฐ์ ์ ๊ธฐ์กด ์๋ฃจ์
์ ํฌํธ์ผ ๋ฟ์
๋๋ค.
์ด ๊ธฐ๋ฅ์ SwiftUI ๋๋ Jetpack Compose๊ฐ ์ํํ๋ ๊ฒ๊ณผ ๊ฐ์ด ํํฌ์ ์์ ํ ๋ค๋ฅธ ๊ฒฝ๋ก๋ฅผ ์ทจํ ์ ์์ต๋๋ค. "named mixin" ์ ์ ๋๋ Builders ์ ์์ ๋ํ ๊ตฌ๋ฌธ ์คํ.
๋๋ ์ด ๋ฌธ์ ์ ํต์ฌ์ด StreamBuilder์ ๊ฐ์ ํจํด์ ๋จ์ํ๋ฅผ ์๊ตฌํ๋ค๋ ์ฌ์ค์ ์ฃผ์ฅํฉ๋๋ค.
์ง๊ธ๊น์ง์ ๋ชจ๋ ์ฃผ์์ ๋ค๋ฅธ ๋์(์ผํ์ฉ ๊ฐ์ฒด ์์ฑ, HTTP ์์ฒญ ๋ง๋ค๊ธฐ ๋ฑ) ๋๋ ๋ค๋ฅธ ๊ตฌ๋ฌธ ์ ์์ ๋ํ StreamBuilder์ ๋์์ ์ธ๊ธํ์ต๋๋ค.
๋ ์ด์ ๋ฌด์จ ๋ง์ ํด์ผ ํ ์ง ์ ๋ชจ๋ฅด๊ฒ ์ด์ ์ด๋ป๊ฒ ๋ ๋ฐ์ ํ ์ ์์์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
@Hixie ์ด ์ง์ ์์ ์ดํดํ์ง ๋ชปํ๊ฑฐ๋ ๋์ํ์ง ์๋ ๊ฒ์ ๋ฌด์์
๋๊น?
@rrousselGit ์ด๊ฒ์ ๋ณด์ฌ์ฃผ๋ ๋ฐ๋ชจ ์ฑ์ ๋ง๋ค ์ ์์ต๋๊น? ๋๋ ๋ด๊ฐ ๋ฌธ์ ๋ผ๊ณ ์ดํดํ ๊ฒ์ ๋ณด์ฌ์ฃผ๋ ๋ฐ๋ชจ ์ฑ์ ๋ง๋ค๋ ค๊ณ ์๋ํ์ง๋ง ๋ถ๋ช ํ ๋๋ โโ๊ทธ๊ฒ์ ์ ๋๋ก ์ดํดํ์ง ๋ชปํ์ต๋๋ค. ("StreamBuilder์ ๊ฐ์ ํจํด"๊ณผ ๋ฐ๋ชจ ์ฑ์์ ์ํํ ์์ ์ ์ฐจ์ด์ ์ด ๋ฌด์์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.)
- StreamBuilder๋ ์ค์ฒฉ์ผ๋ก ์ธํด ๊ฐ๋ ์ฑ/์ฐ๊ธฐ์ฑ์ด ์ข์ง ์์ต๋๋ค.
๋น์ ์ ์ด๋ฏธ ์ฅํฉํ ๊ฒ์ด ๋ฌธ์ ๊ฐ ์๋๋ผ๊ณ ๋งํ์ต๋๋ค. ์ค์ฒฉ์ ์ฅํฉํจ์ ๋ ๋ค๋ฅธ ์ธก๋ฉด์ผ ๋ฟ์ ๋๋ค. ์ค์ฒฉ์ด ์ค์ ๋ก ๋ฌธ์ ๋ผ๋ฉด Padding, Expanded, Flexible, Center, SizedBox ๋ฐ ์ค์ ์ด์ ์์ด ์ค์ฒฉ์ ์ถ๊ฐํ๋ ๊ธฐํ ๋ชจ๋ ์์ ฏ์ ๋ฐ๋ผ์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ค์ฒฉ์ ๋ชจ๋๋ฆฌ์ ์์ ฏ์ ๋ถํ ํ์ฌ ์ฝ๊ฒ ํด๊ฒฐํ ์ ์์ต๋๋ค.
๋ชจ๋ StatefulWidget์์ StreamBuilder ๊ตฌํ์ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ๋ ๊ฒ์ ํฉ๋ฆฌ์ ์ด์ง ์์ต๋๋ค.
StatefulWidget์ด ์์ฑ ๋ฐ ํ๊ธฐํด์ผ ํ๋ ์คํธ๋ฆผ์ ์์ฑ ๋ฐ ํ๊ธฐํ๋ ์ฝ๋ ํ์ ๋ณต์ฌํ์ฌ ๋ถ์ฌ๋ฃ๋๋ค๋ ์๋ฏธ์ ๋๊น? ๋ค, ์ ๋ง ํฉ๋ฆฌ์ ์ ๋๋ค.
์์ฒด ์คํธ๋ฆผ์ ์์ฑ/ํ๊ธฐํด์ผ ํ๋ ์๋ฐฑ ๊ฐ์ _different_ ์ฌ์ฉ์ ์ ์ StatefulWidget์ด 10๊ฐ ๋๋ ์ ์ด ๊ธ์ง๋์ด ์๋ค๋ฉด(ํํฌ ์ฉ์ด์์ "์ฌ์ฉ"), ""๋ ผ๋ฆฌ" ์ฌ์ฌ์ฉ ๋๋ ์ค์ฒฉ๋ณด๋ค ๊ฑฑ์ ํด์ผ ํ ๋ ํฐ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๊ฑฑ์ ํ ๊ฒ์ ๋๋ค. ๋ด ์ฑ์ด ์ฒ์๋ถํฐ ๊ทธ๋ ๊ฒ ๋ง์ ๋ค๋ฅธ ์คํธ๋ฆผ์ ๋ง๋ค์ด์ผ ํ๋ ์ด์ ์ ๋ํด.
๊ณต์ ํ๊ฒ ๋งํ์๋ฉด, ๋๊ตฐ๊ฐ๊ฐ ์์ ์ ์ฑ์์ ํน์ ํจํด์ด ํฉ๋ฆฌ์ ์ด์ง ์๋ค๊ณ ์๊ฐํ๋ ๊ฒ์ ๊ด์ฐฎ๋ค๊ณ ์๊ฐํฉ๋๋ค. (๊ทธ๋ ๋ค๊ณ ํ๋ ์์ํฌ๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ด๋ฅผ ์ง์ํด์ผ ํ๋ค๋ ์๋ฏธ๋ ์๋์ง๋ง ์ต์ํ ํจํค์ง๊ฐ ์ด๋ฅผ ํด๊ฒฐํ๋๋ก ํ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.) ๋๊ตฐ๊ฐ๊ฐ stream.listen
๋๋ StreamBuilder(stream)
์ฌ์ฉํ๊ณ ์ถ์ง ์์ ๊ฒฝ์ฐ
๊ณต์ ํ๊ฒ ๋งํ์๋ฉด, ๋๊ตฐ๊ฐ๊ฐ ์์ ์ ์ฑ์์ ํน์ ํจํด์ด ํฉ๋ฆฌ์ ์ด์ง ์๋ค๊ณ ์๊ฐํ๋ ๊ฒ์ ๊ด์ฐฎ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋๋ ๋น์ ๊ณผ ๊ฐ์ ํ์ด์ง์ 100%์
๋๋ค.
๋ฌผ๋ก ์ฌ๋๋ค์ ์ฑ์์ ์ํ๋ ๋๋ก ๋ฌด์์ด๋ ํ ์ ์์ต๋๋ค. ๋ด๊ฐ ์ป์ผ๋ ค๊ณ ํ๋ ๊ฒ์ ์ด ์ค๋ ๋์์ ์ค๋ช
ํ๋ ๋ชจ๋ ๋ฌธ์ ์ ์ด๋ ค์์ด ์๋ชป๋ ํ๋ก๊ทธ๋๋ฐ ์ต๊ด์ ๊ฒฐ๊ณผ์ด๋ฉฐ ์ค์ ๋ก Dart ๋๋ Flutter์ ๊ฑฐ์ ๊ด๋ จ์ด ์๋ค๋ ๊ฒ์
๋๋ค. ๊ทธ๊ฒ์ ์ ์๊ฐ์ผ ๋ฟ์
๋๋ค. ํ์ง๋ง ๋๊ตฐ๊ฐ๊ฐ ๊ณณ๊ณณ์ ์์ญ ๊ฐ์ ์คํธ๋ฆผ์ ์์ฑํ๋ ์ฑ์ ์์ฑํ๊ณ ์๋ค๋ฉด ํ๋ ์์ํฌ์ "๊ฐ์ "์ ์์ฒญํ๊ธฐ ์ ์ ์ฑ ๋์์ธ์ ๊ฒํ ํด์ผ ํ ๊ฒ์
๋๋ค.
์๋ฅผ ๋ค์ด ์์ ๋ฆฌํฌ์งํ ๋ฆฌ์ ๋ง๋ ํํฌ ๊ตฌํ์ ๋๋ค.
<strong i="10">@override</strong>
Widget build(BuildContext context) {
final value = useAnimation(animation);
final screenHeight = MediaQuery.of(context).size.height;
final textHeight =
useMemoized(() => math.sqrt(screenHeight), [screenHeight]);
return Text(
'Change Duration',
style: TextStyle(fontSize: 10.0 + value * textHeight),
);
}
๋๋ ์ด๊ฒ์ ๋ํด ์ข์ง ์์ ๋๋์ด ๋ค์์ต๋๋ค. ๊ทธ๋์ ๋ด๋ถ์ ์ผ๋ถ๋ฅผ ํ์ธํ๊ณ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ํ์ธํ๊ธฐ ์ํด ๋๋ฒ๊ทธ ์ธ์๋ฅผ ์ถ๊ฐํ์ต๋๋ค.
์๋ ์ถ๋ ฅ์์ โโListenable ํํฌ๊ฐ ๋ชจ๋ ์ ๋๋ฉ์ด์
ํฑ์์ ์
๋ฐ์ดํธ๋ ๋ ์จ๋ฅผ ํ์ธํ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฆฌ์ค๋๋ธ์ "์ฌ์ฉ"ํ๋ ์์ ฏ์ด ์
๋ฐ์ดํธ๋์์ต๋๊น? ๊ธฐ๊ฐ์ด ๋ณ๊ฒฝ๋์๋์? ์ธ์คํด์ค๊ฐ ๊ต์ฒด๋์์ต๋๊น?
๋ฉ๋ชจ๋ ํ
, ๊ทธ๊ฒ ๋ญ์ง๋ ๋ชจ๋ฅด๊ฒ ์ด. ์๋ง๋ ๊ฐ์ฒด๋ฅผ ์บ์ํ๊ธฐ ์ํ ๊ฒ์ผ ์ ์์ง๋ง ๋ชจ๋ ๋จ์ผ ๋น๋์์ ์์ ฏ์ ๊ฐ์ฒด๊ฐ ๋ณ๊ฒฝ๋์๋์ง ํ์ธํฉ๋๊น? ๋ญ๋ผ๊ณ ์? ์์? ๋ฌผ๋ก ์ํ ์ ์ฅ ์์ ฏ ๋ด๋ถ์์ ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ํธ๋ฆฌ ์์ ๋ค๋ฅธ ์์ ฏ์ด ๊ฐ์ ๋ณ๊ฒฝํ ์ ์์ผ๋ฏ๋ก ๋ณ๊ฒฝ ์ฌํญ์ ํด๋งํด์ผ ํฉ๋๋ค. ์ด๊ฒ์ "๋ฐ์ํ" ํ๋ก๊ทธ๋๋ฐ๊ณผ ์ ๋ฐ๋์ธ ๋ฌธ์ ๊ทธ๋๋ก์ ํด๋ง ๋์์
๋๋ค.
์ค์๊ฐ์์ผ๋ก "new" ๋ฐ "old" ํํฌ๋ ๋ชจ๋ ๋์ผํ ์ธ์คํด์ค ์ ํ์ ๊ฐ์ง๋ฉฐ ๋ ๋ค ๋์ผํ ๊ฐ์ ๊ฐ์ง๋ง ํจ์๋ ๊ฐ์ด ๋ณ๊ฒฝ๋์๋์ง ํ์ธํ๊ธฐ ์ํด ๊ฐ์ ๋ฐ๋ณตํฉ๋๋ค. _๋ชจ๋ ๋จ์ผ ์ ๋๋ฉ์ด์ ํฑ_์.
์ด๊ฒ์ด ๋ด๊ฐ ์ป์ ๊ฒฐ๊ณผ์ ๋๋ค. ๋ฌดํ๋์ ๋๋ค.
/flutter (28121): Use hook:_ListenableHook
I/flutter (28121): Is this the current hook:false
I/flutter (28121): 1: --- inside shouldPreserveState ----
I/flutter (28121): Hook1:Instance of '_ListenableHook'
I/flutter (28121): Hook1 keys:null
I/flutter (28121): Hook2 :Instance of '_ListenableHook'
I/flutter (28121): Hook2 keys:null
I/flutter (28121): 2. Shoud we preserve the state of _ListenableHook:true
I/flutter (28121): 3: --------------
I/flutter (28121): checking if the listenable did change
I/flutter (28121): Did the listenable change?false
I/flutter (28121): Use hook:_MemoizedHook<double>
I/flutter (28121): Is this the current hook:false
I/flutter (28121): 1: --- inside shouldPreserveState ----
I/flutter (28121): Hook1:Instance of '_MemoizedHook<double>'
I/flutter (28121): Hook1 keys:[1232.0]
I/flutter (28121): Hook2 :Instance of '_MemoizedHook<double>'
I/flutter (28121): Hook2 keys:[1232.0]
I/flutter (28121): iterating over the hooks keys
I/flutter (28121): 2. Shoud we preserve the state of _MemoizedHook<double>:true
I/flutter (28121): Use hook:_ListenableHook
I/flutter (28121): Is this the current hook:false
I/flutter (28121): 1: --- inside shouldPreserveState ----
I/flutter (28121): Hook1:Instance of '_ListenableHook'
I/flutter (28121): Hook1 keys:null
I/flutter (28121): Hook2 :Instance of '_ListenableHook'
I/flutter (28121): Hook2 keys:null
I/flutter (28121): 2. Shoud we preserve the state of _ListenableHook:true
์ด ๋ชจ๋ ์์
์ ๋ชจ๋ ๋จ์ผ ์ ๋๋ฉ์ด์
ํฑ์์ ์ํ๋ฉ๋๋ค. "final color = useAnimation"๊ณผ ๊ฐ์ ๋ค๋ฅธ ํํฌ๋ฅผ ์ถ๊ฐํ๋ฉด
๋๋ ์ฌ๊ธฐ ์์์ ์ฑ ์ํ๋ ์์ ฏ ๋๋ ์์ ฏ ํธ๋ฆฌ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ์๋ค๋ก ์์ง์ด๋ ํ ์คํธ๋ฅผ ๋ณด๊ณ ์์ง๋ง ์ฌ์ ํ ํํฌ๋ ํธ๋ฆฌ/์์ ฏ์ด ์ ๋ฐ์ดํธ๋์๋์ง ์ง์์ ์ผ๋ก ํ์ธํ๊ณ ์์ต๋๋ค. ์ด๋ฌํ ํน์ ํํฌ๋ฅผ "์ฌ์ฉ"ํ๋ ๋ชจ๋ ์์ ฏ์ด ์ด ํด๋ง ๋์์ ์ํํ๋๋ก ํ๋ ๊ฒ์ ์ข์ง ์์ต๋๋ค.
๋น๋ ๋ฉ์๋ ๋ด์์ ์ํ ๊ฐ์ฒด์ ์ด๊ธฐํ/์
๋ฐ์ดํธ/ํ๊ธฐ ๋
ผ๋ฆฌ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ ์๋ชป๋ ๋์์ธ์ผ ๋ฟ์
๋๋ค. ์ฌ์ฌ์ฉ์ฑ, ํซ๋ฆฌ๋ก๋ ๋๋ ์ธ์ง ๋ถํ์์ ์ป์ ๊ฐ์ ์ฌํญ์ด ์ฑ๋ฅ์ ๋ฏธ์น๋ ์ํฅ์ ์ ๋นํํ์ง ๋ชปํฉ๋๋ค.
๋ค์ ๋งํ์ง๋ง, ๋ด ์๊ฐ์๋. ํํฌ๋ ํจํค์ง์ด๋ฏ๋ก ์ด๋์ด ์ค๋ฒํค๋๋ฅผ ์ ๋นํํ๋ค๊ณ ์๊ฐํ๋ฉด ๋๊ตฌ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ํ ๋น๋ ํ๋ก์ธ์ค ๋ด๋ถ์ ๋ชจ๋ ๊ฒ์ ์ถ์ํํ๋ ค๋ ๊ฒฝ์ฐ ์ธ์ด ๊ธฐ๋ฅ, ์ปดํ์ผ๋ฌ ๋ง์ ๋๋ ์ถ์ํ๊ฐ ๊ทธ๋ฌํ ๋ถํ์ํ ๊ฒ์ฌ๋ฅผ ๋ฐฉ์งํ ์ ์๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์ StatefulWidget์ ํ์ฅํ๋ ๊ฒ๊ณผ ๊ฐ์ ๋์์ด ๋จ์ ์์ต๋๋ค. ์ด๋ฏธ ํ ์ ์๋ ์ผ, ์์์ด ํด๊ณ ๋ ์ผ.
@Hixie ๋น์ ์ ์ง๋ฌธ์ ๋๋ตํ์ง ์์์ต๋๋ค. ์์ ๋์ด๋ ๊ธ๋จธ๋ฆฌ ๊ธฐํธ ๋ชฉ๋ก์์ ์ดํดํ์ง ๋ชปํ๊ฑฐ๋ ๋์ํ์ง ์๋ ๊ฒ์ ๋ฌด์์ ๋๊น?
๋๋ ๋น์ ์ด ๋ด๊ฐ ๋ฌด์์ ๋ณด์ฌ์ฃผ๊ธฐ๋ฅผ ์ํ๋์ง ๋ชจ๋ฅธ ์ฑ ์๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
@Rudiksz ํ์คํ ์ฐ๋ฆฌ๊ฐ ์ค์ ๋ก ๊ณ ๋ คํ๋ ๋ชจ๋ ์๋ฃจ์ ์ ์ํฉ์ ์ ํ์ํค์ง ์๋๋ก ํ๋กํ์ผ๋งํ๊ณ ๋ฒค์น๋งํนํด์ผ ํฉ๋๋ค. @TimWhiting์ ์ ์ถํ ๋ฐ๋ชจ ์ฑ์ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ ์ค ์ผ๋ถ๋ ์๋ง์ด ๋๊ธฐ ์ฌ์ด ์ ํ์ ํจํด์ ์ ํํ ๋ค๋ฃจ๊ธฐ ์ํ ๊ฒ์ ๋๋ค. (๊ทธ๋ฆฌ๊ณ ์์ ์ธ๊ธํ๋ฏ์ด ๊ฐ์ ์ ์ฌ์ง๊ฐ ์์ต๋๋ค. ์ฝ๋์ TODO๋ฅผ ์ฐธ์กฐํ์ญ์์ค.)
@rrousselGit ๋๋ฌด ์ฃผ๊ด์ ์ด๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ํด ์ก์ด์
์ผ๋ฐ์ ์ผ๋ก ๊ทํ๊ฐ ๋ณด๊ณ ์๋ ๋ฌธ์ ๋ฅผ ๋ด๊ฐ ๊ฒฝํํ๋์ง ์ฌ๋ถ๋ ๊ด๋ จ์ด ์์ต๋๋ค. ๋น์ ์ ๊ฒฝํ์ ๋ด ์๊ฒฌ๊ณผ ์๊ด์์ด ์ ํจํฉ๋๋ค. ๋๋ ๋น์ ์ด ๊ฒฝํํ๋ ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ ์ ์ฐพ๊ธฐ ์ํด ์ผํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค. ๋น๋ก ๋ด๊ฐ ๊ทธ ๋ฌธ์ ๋ฅผ ๋๋ผ์ง ์๋๋ผ๋ ๋ง์ ๋๋ค. ๋ด๊ฐ ์ง์ ๋ฌธ์ ๋ฅผ ๊ฒฝํํ์ง ์๋ ๊ฒ์ ์ ์ผํ ํจ๊ณผ๋ ์ด ํ ๋ก ์์ ๋ณด์๋ฏ์ด ๋ด๊ฐ ๋ฌธ์ ๋ฅผ ์ ์ดํดํ๋ ๊ฒ์ด ๋ ์ด๋ ต๋ค๋ ๊ฒ์ ๋๋ค.
๋ด๊ฐ ๋น์ ์ด ์ฆ๋ช ํ๊ณ ์ถ์ ๊ฒ์ ๋น์ ์ด ๋๊ตฐ๊ฐ๊ฐ ์๋ฃจ์ ์ ๋ง๋ค ๋, ๋น์ ์ด ๋ค๋ฅธ ์ํฉ์์ ๋ ์ฌ์ฉํ๊ธฐ ์ด๋ ค์ด๋ฐ์ ์ ์์์ ๋งํ์ฌ ํด๊ณ ํ์ง ์์ ๊ฒ์ด๋ผ๊ณ ์๋นํ ์ ๋๋ก๋ ๊ทธ ๋ฐ๋ชจ์, ๋ฐ์ ๋ค์ผ ์๊ฐํ๋ ์ฝ๋ฉ ํจํด (์ฆ, ๋ชจ๋ ๊ด๋ จ ์ํฉ์ ํฌํจํฉ๋๋ค. ์๋ฅผ ๋ค์ด "์ ๋ฐ์ดํธ" ๋ถ๋ถ ๋๋ ์ฒ๋ฆฌํด์ผ ํ ์ค์ํ๋ค๊ณ ์๊ฐํ๋ ๋ค๋ฅธ ๋ถ๋ถ์ ํฌํจํด์ผ ํจ) ๋๋ ์๋ฃจ์ ์ด ํ ๊ฐ์ง ๊ฒฝ์ฐ์๋ ์๋ํ์ง๋ง ์ผ๋ฐ์ ์ธ ๊ฒฝ์ฐ์๋ ์๋ํ์ง ์๋๋ค๊ณ ๋งํฉ๋๋ค(์: ์ด์ ํผ๋๋ฐฑ์ ํตํด ๋งค๊ฐ๋ณ์๊ฐ ์ฌ๋ฌ ์์น์์ ์ ๊ณต๋๊ณ ์ฌ๋ฌ ์ํฉ์์ ์ ๋ฐ์ดํธ๋์ด ์์ ์์ฑ๊ณผ ๊ฐ์ ์๋ฃจ์ ์ด ์ผ๋ฐ์ ์ธ ์ฝ๋๋ฅผ ์ ์ธํ์ง ์์ ๊ฒ์ด๋ผ๋ ์ ์ ๋ถ๋ช ํ ํฉ๋๋ค.
๋ฌธ์ ๋ ๋น์ ์ด ๋์๊ฒ "๋ช ๋ฐฑํ" ์์ญ์ ์๋ ๋ฌด์ธ๊ฐ์ ๋ํ ์๋ฅผ ์๊ตฌํ๊ณ ์๋ค๋ ๊ฒ์ ๋๋ค.
๋๋ ๋ช ๊ฐ์ง ์๋ฅผ ๋ง๋๋ ๋ฐ ์ ๊ฒฝ ์ฐ์ง ์์ง๋ง, ๋น์ ์ด ์ดํดํ์ง ๋ชปํ๋ ๊ฒ์ ์ดํดํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ๋น์ ์ด ๋ฌด์์ ๊ธฐ๋ํ๊ณ ์๋์ง ์ ํ ๋ชจ๋ฆ ๋๋ค.
ํ ๋ง์ ์ด๋ฏธ ๋ค ํ์ต๋๋ค.
๋น์ ์ด ์ดํดํ์ง ๋ชปํ๋ ๊ฒ์ ์ดํดํ์ง ์๊ณ ๋ด๊ฐ ํ ์ ์๋ ์ ์ผํ ๊ฒ์ ๋ ์์ ์ ๋ฐ๋ณตํ๋ ๊ฒ์
๋๋ค.
์ฌ๊ธฐ์์ ์ผ๋ถ ์ค๋ํซ์ ์คํํ ์ ์์ง๋ง ์ด๋ ๋ ์์ ์ ๋ฐ๋ณตํ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
์ค ๋ํซ์ด ์ ์ฉํ์ง ์์ ๊ฒฝ์ฐ ์คํํ ์ ์๋ค๊ณ ํด์ ์๋ฌด ๊ฒ๋ ๋ณ๊ฒฝ๋์ง ์๋ ์ด์ ๋ฅผ ์ ์ ์์ต๋๋ค.
๋ฏน์ค์ธ๊ณผ ํจ์๊ฐ StreamBuilder์ ๋ํ ๊ฐ๋ฅํ ๋์์ด ๋ ์ ์๋์ง ์ฌ๋ถ์ ๊ดํด์๋ Hooks๊ฐ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์คํธ๋ฆผ์ ์์ ํ ์ ์๋ค๋ ๊ฒ์ ๊ฝค ์ ๋ณด์ฌ์ฃผ๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ํด๊ฒฐ์ฑ ์ด ๋ ์๋ ์์ต๋๋ค.
ํํฌ๋ฅผ ํจ์๋ก ๊ฐ์ฃผํด์๋ ์ ๋ฉ๋๋ค.
Iterable/Stream๊ณผ ์ ์ฌํ ์๋ก์ด ์ธ์ด ๊ตฌ์กฐ์
๋๋ค.
ํจ์๋ ํํฌ๊ฐ ํ๋ ์ผ์ ํ ์ ์์ต๋๋ค. ์ํ ๋๋ ์์ ฏ์ ๋ค์ ๋น๋ํ ์ ์๋ ๊ธฐ๋ฅ์ด ์์ต๋๋ค.
mixins์ ๋ฌธ์ ๋ OP์์ ์ค๋ช ๋ฉ๋๋ค. TL;DR: ๋ณ์์ ์ด๋ฆ ์ถฉ๋์ด ์๊ณ ๋์ผํ ๋ฏน์ค์ธ์ ์ฌ๋ฌ ๋ฒ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
@rrousselGit ๊ธ์์, ๋ช ๊ฐ์ง ์์ ๋ฅผ ๋ง๋ค์ด๋ ์๊ด์๊ณ ์ ๊ฐ ์๊ตฌํ๋ ์์ ๋ ๋ถ๋ช ํ๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ช ๊ฐ์ง ๋ถ๋ช ํ ์์ ๋ก ์์ํ์ฌ ๊ฑฐ๊ธฐ์์ ๋ฐ๋ณตํด ๋ณด๊ฒ ์ต๋๋ค.
๋๋ ์๊ฐ ๋ช
๋ฐฑํ๋ค๊ณ ๋งํ์ง ์์์ง๋ง ๋ฌธ์ ๋์
๋๋ค.
๋ด๊ฐ ์๋ฏธํ๋ ๋ฐ๋ ์๋ก์ด ์๋ฅผ ๋ง๋ค ์ ์๋ค๋ ๊ฒ์
๋๋ค. ๋ด๊ฐ ๋งํด์ผ ํ ๋ชจ๋ ๊ฒ์ ์ด๋ฏธ ์ด ์ค๋ ๋์ ์์ต๋๋ค.
์ด ์์ ์ถ๊ฐํ ๊ฒ์ด ์๊ฐ๋์ง ์์ต๋๋ค.
ํ์ง๋ง FWIW ์ ๋ Riverpod๋ฅผ ์ฌ์ฉํ์ฌ ์คํ ์์ค ๋ ์จ ์ฑ์ ๋ง๋ค๊ณ ์์ต๋๋ค. ์๋ฃ๋๋ฉด ์ฌ๊ธฐ์ ๋งํฌํ๊ฒ ์ต๋๋ค.
์ฌ๊ธฐ์์ ๋ ผ์๋ ๋ฌธ์ ์ ๊ด๋ จ๋ ๋น๋์ ๋ํด ๋ช ๊ฐ์ง ์ง๋ฌธ์ ํ๋ ํธ์ํฐ ์ค๋ฌธ์กฐ์ฌ๋ฅผ ํ์ต๋๋ค.
https://twitter.com/remi_rousselet/status/1295453683640078336
ํฌํ๋ ์์ง ๋ณด๋ฅ ์ค์ด์ง๋ง ํ์ฌ ์ซ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
200๋ช ์ ์ฌ๋๋ค ์ค 86%๊ฐ ์ค์ฒฉ์ ํฌํจํ์ง ์๋ ๋น๋๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ํ๋ค๋ ์ฌ์ค ์์ฒด๊ฐ ๋งํด์ค๋๋ค.
๋ถ๋ช ํ ๋ง์๋๋ฆฌ์๋ฉด ์ ๋ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ๋ง๋ผ๊ณ ์ ์ํ ์ ์ด ์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ๊ทธ๊ฒ์ ํด๊ฒฐํด์๋ ์ ๋๋ค๊ณ ์๊ฐํ๋ค๋ฉด, ๊ทธ ๋ฌธ์ ๋ ์ข ๊ฒฐ๋ ๊ฒ์ ๋๋ค.
๋๋ ๋น์ ์ด ๋งํฌ ํ ์ค ๋ํซ์ ์ฌ์ฉํ๋ ์๋ฅผ ๋ง๋ค๋ ค๊ณ ๋ ธ๋ ฅํ ๊ฒ์ ๋๋ค.
๋งํฌ๋ ์ค๋ํซ์ ๊ธฐ๋ฐ์ผ๋ก ์์ ๋ฅผ ๋ง๋๋ ๋ฐ ๋์์ ๋๋ฆด ์ ์์ง๋ง ์ด ์ค๋ํซ์ด ์ถฉ๋ถํ์ง ์์ ์ด์ ๋ฅผ ์์์ผ ํฉ๋๋ค.
๊ทธ๋ ์ง ์์ผ๋ฉด ๋ด๊ฐ ํ ์ ์๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ์ด๋ฌํ ์ค๋ํซ์ ์ปดํ์ผํ๋ ๊ฒ์
๋๋ค. ํ์ง๋ง ๊ทธ๊ฒ์ด ๋น์ ์ด ์ํ๋ ๊ฒ์ธ์ง ์์ฌ์ค๋ฝ์ต๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์์ ์๋ง์ ValueListenableBuilder+TweenAnimationBuilder https://gist.github.com/rrousselGit/a48f541ffaaafe257994c6f98992fa73์ ๋ํ ์์ง์ ๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์์ ์๋ง์ ValueListenableBuilder+TweenAnimationBuilder https://gist.github.com/rrousselGit/a48f541ffaaafe257994c6f98992fa73์ ๋ํ ์์ง์ ๋๋ค.
FWIW, ์ด ํน์ ์๋ mobx์์ ๋ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
์ค์ ๋ก ํํฌ ๊ตฌํ๋ณด๋ค ์งง์ต๋๋ค.
Mobx์ ์ต์ ๋ฒ๋ธ์ ์คํ
๋ก์ด๋์ ValueNotifier์ด๊ณ Observer ์์ ฏ์ Flutter์ ValueListenableBuilder๊ฐ ์งํํ ๊ฒ์
๋๋ค. ์ด๊ฒ์ ํ๋ ์ด์์ ValueNotifier๋ฅผ ์์ ํ ์ ์์ต๋๋ค.
ValueNotifier/ValueListenableBuilder ์ฝค๋ณด์ ๋ํ ๋๋กญ์ธ ๋์ฒด๊ฐ ๋๋ค๋ ๊ฒ์ ์ค์ ๋ก ์ค์ํ ์์์ธ ๊ด์ฉ์ Flutter ์ฝ๋๋ฅผ ๊ณ์ ์์ฑํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์ฌ์ ํ Flutter์ ๋ด์ฅ๋ Tween ๋น๋๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์์ ์๋ก์ด ์์ ฏ/ํํฌ๋ฅผ ํ์ต/๊ตฌํํ ํ์๊ฐ ์์ผ๋ฉฐ(์ฆ, ์๋ก์ด ๊ธฐ๋ฅ์ด ํ์ํ์ง ์์ต๋๋ค) ํํฌ์ ์ฑ๋ฅ ์ ํ๋ ์์ต๋๋ค.
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'counters.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
<strong i="13">@override</strong>
Widget build(BuildContext context) {
return MaterialApp(
home: Home1(),
);
}
}
var counters = Counters();
class Home1 extends StatelessWidget {
<strong i="14">@override</strong>
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Observer(
builder: (context) => TweenAnimationBuilder<int>(
duration: const Duration(seconds: 5),
curve: Curves.easeOut,
tween: IntTween(end: counters.firstCounter),
builder: (context, value, child) {
return Text('$value');
},
),
),
RaisedButton(
onPressed: () => counters.firstCounter += 100,
child: Text('+'),
),
// Both counters have voluntarily a different Curve and duration
Observer(
builder: (context) => TweenAnimationBuilder<int>(
duration: const Duration(seconds: 2),
curve: Curves.easeInOut,
tween: IntTween(end: counters.secondCounter),
builder: (context, value, child) {
return Text('$value');
},
),
),
RaisedButton(
onPressed: () => counters.secondCounter += 100,
child: Text('+'),
),
const Text('total:'),
// The total must take into account the animation of both counters
Observer(
builder: (context) => TweenAnimationBuilder<int>(
duration: const Duration(seconds: 5),
curve: Curves.easeOut,
tween: IntTween(
end: counters.firstCounter + counters.secondCounter),
builder: (context, value, child) {
return Text('$value');
},
),
),
],
),
),
);
}
}
Counters.dart๋ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋จํฉ๋๋ค.
part 'counters.g.dart';
class Counters = _Counters with _$Counters;
abstract class _Counters with Store {
<strong i="18">@observable</strong>
int firstCounter = 0;
<strong i="19">@observable</strong>
int secondCounter = 0;
}
์ ๋๋ฉ์ด์ ๋น๋๊ฐ ํ์ํ์ง ์์ ๋ ๋ค๋ฅธ ๊ตฌํ์ด ์์ต๋๋ค. ์์ ฏ์ ๋น๋ ๋ฐฉ๋ฒ์ ํ ํ๋ฆฟ๊ณผ ๊ฐ์ ์๋ฏธ๋ก ์ html ํ์ผ๊ณผ ๊ฐ์ด ์ต๋ํ ์์ํฉ๋๋ค.
https://gist.github.com/Rudiksz/cede1a5fe88e992b158ee3bf15858bd9
@Rudiksz "์ด๊ณ" ํ๋์ ๋์์ด ์ค๋ํซ์์ ๊นจ์ก์ต๋๋ค. ๋ ์นด์ดํฐ๊ฐ ํจ๊ป ์ ๋๋ฉ์ด์
์ ์ ์ฉํ ์ ์์ง๋ง ๋ค๋ฅธ ์๊ฐ๊ณผ ๋ค๋ฅธ ๊ณก์ ์ผ๋ก ์ ๋๋ฉ์ด์
์ ์๋ฃํ๋ ์์ ์ ์ผ์นํ์ง ์์ต๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ์ด ์์ ๊ฐ ValueListenableBuilder
๋ณํ์ ๋ฌด์์ ์ถ๊ฐํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๋ง์ง๋ง ์์ ์ ๊ดํด์๋ TickerMode
์ง์ํ์ง ์์ผ๋ฉฐ ๋ฆฌ์ค๋๊ฐ ์ ๊ฑฐ๋๊ฑฐ๋ ์ปจํธ๋กค๋ฌ๊ฐ ํ๊ธฐ๋์ง ์์ผ๋ฏ๋ก TickerProvider
๊ฐ ๊นจ์ก์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ Mobx๋ ์ฃผ์ ์์ ๋ฒ์ด๋ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ฐ๋น์ธํธ ์ํ/ValueListenable vs Stores vs Streams๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ๋ ผ์ํ๋ ๊ฒ์ด ์๋๋ผ, Mobx๊ฐ ์ด๋ค ์์ผ๋ก๋ ํด๊ฒฐํ์ง ๋ชปํ๋ ๋ก์ปฌ ์ํ/์ค์ฒฉ ๋น๋๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด ๋ ผ์ํ๊ณ ์์ต๋๋ค.
โโโโ
๋ํ ํํฌ ์์์ useAnimatedInt
๋ ํจํค์ง๋ก ์ถ์ถ๋ ์/์์ด์ผ ํ๋ฉฐ ๊ฐ๋ณ ํ
์คํธ ์ ๋๋ฉ์ด์
๊ณผ ์ด๊ณ ์ฌ์ด์ ์ง์ ์๊ฐ/๊ณก์ ์ด ์ค๋ณต๋์ง ์๋๋ค๋ ์ ์ ๋ช
์ฌํ์ญ์์ค.
๊ณต์ฐ์ ๊ฒฝ์ฐ Hooks๋ฅผ ์ฌ์ฉํ๋ฉด ๋จ์ผ ์์๋ง ๋ค์ ๋น๋ํ๋ ๋ฐ๋ฉด Builders๋ 2-4๊ฐ ๋น๋๋ฅผ ๋ค์ ๋น๋ํฉ๋๋ค.
๋ฐ๋ผ์ Hooks๋ ํจ์ฌ ๋ ๋น ๋ฅผ ์ ์์ต๋๋ค.
์ค๋ํซ์์ "์ด๊ณ" ํ๋์ ๋์์ด ๊นจ์ก์ต๋๋ค. ๋ ์นด์ดํฐ๊ฐ ํจ๊ป ์ ๋๋ฉ์ด์ ์ ์ ์ฉํ ์ ์์ง๋ง ๋ค๋ฅธ ์๊ฐ๊ณผ ๋ค๋ฅธ ๊ณก์ ์ผ๋ก ์ ๋๋ฉ์ด์ ์ ์๋ฃํ๋ ์์ ์ ์ผ์นํ์ง ์์ต๋๋ค.
๋น์ ์ ๋ถ๋ช ํ ์์ ๋ฅผ ์คํํ๋ ค๊ณ ํ์ง๋ ์์์ต๋๋ค. ๊ทธ๊ฒ์ ๋น์ ์ ์ฝ๋์ ๋๊ฐ์ด ๋์ํฉ๋๋ค.
๋ง์ง๋ง ์์ ์ TickerMode๋ฅผ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ TickerProvider๊ฐ ๊นจ์ก์ต๋๋ค.
์ด๊ฒ ๋ฌด์จ ๋ง์ธ์ง ๋ชจ๋ฅด๊ฒ ๋ค์. TickerMode๋ฅผ ์ฌ์ฉํ์ง ์๋ _your_ ์์ ๋ฅผ ๋ฆฌํฉํ ๋งํ์ต๋๋ค. ๋ค์ ์๊ตฌ ์ฌํญ์ ๋ณ๊ฒฝํ๊ณ ์์ต๋๋ค.
๊ณต์ฐ์ ๊ฒฝ์ฐ Hooks๋ฅผ ์ฌ์ฉํ๋ฉด ๋จ์ผ ์์๋ง ๋ค์ ๋น๋ํ๋ ๋ฐ๋ฉด Builders๋ 2-4๊ฐ ๋น๋๋ฅผ ๋ค์ ๋น๋ํฉ๋๋ค. ๋ฐ๋ผ์ Hooks๋ ํจ์ฌ ๋ ๋น ๋ฅผ ์ ์์ต๋๋ค.
์๋ ๊ทธ๋ฅ ์๋. ํํฌ ์์ ฏ์ ๋ชจ๋ ๋จ์ผ ๋น๋์์ ๋ณ๊ฒฝ ์ฌํญ์ ์ง์์ ์ผ๋ก ํด๋งํฉ๋๋ค. valuelistenables๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ๋น๋๋ "๋ฐ์ํ"์ ๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ์ด ์์ ๊ฐ ValueListenableBuilder ๋ณํ์ ๋ฌด์์ ์ถ๊ฐํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค .
๊ทธ๋ฆฌ๊ณ Mobx๋ ์ฃผ์ ์์ ๋ฒ์ด๋ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค. ์ฐ๋ฆฌ๋ ์ฐ๋น์ธํธ ์ํ/ValueListenable vs Stores vs Streams๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ ผ์ํ๋ ๊ฒ์ด ์๋๋ผ, Mobx๊ฐ ์ด๋ค ์์ผ๋ก๋ ํด๊ฒฐํ์ง ๋ชปํ๋ ๋ก์ปฌ ์ํ/ ์ค์ฒฉ ๋น๋ ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด ๋ ผ์ํ๊ณ ์์ต๋๋ค.
๋๋ด์ด์๊ตฐ์. ๋๋ ๋น์ ์ ์๋ฅผ ๋ค์ด ์ค์ฒฉ๋ ValueListenableBuilders *์ ํธ์ ๋น๋๋ฅผ "๋ค๋ค์ต๋๋ค"?! ๊ตฌ์ฒด์ ์ผ๋ก ๋ฌธ์ ๋ก ์ ๊ธฐํ ์ .
๊ทธ๋ฌ๋ ์ฌ๊ธฐ ์ด ๋ฌธ์ฅ์ ์ด ํ ๋ก ์ ๋ํ ๋น์ ์ ์ ์ฒด์ ์ธ ํ๋๋ฅผ ์ค๋ช
ํฉ๋๋ค. ํํฌ๊ฐ ์๋ ๊ฒฝ์ฐ "์ฃผ์ ์์ ๋ฒ์ด๋จ"์ด์ง๋ง ์๋ฃจ์
์ผ๋ก ์ฌ์ฉํ ํํฌ์ธ์ง ์ฌ๋ถ๋ ์ ๊ฒฝ ์ฐ์ง ์๋๋ค๊ณ ๋งํฉ๋๋ค.
์ฌ๊ฒ ํด์ค
๋น์ ์ ๋ถ๋ช ํ ์์ ๋ฅผ ์คํํ๋ ค๊ณ ํ์ง๋ ์์์ต๋๋ค. ์ฝ๋์ ๋๊ฐ์ด ์๋ํฉ๋๋ค.
๊ทธ๋ ์ง ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ ์นด์ดํฐ๋ 5์ด ๋์, ๋ ๋ฒ์งธ ์นด์ดํฐ๋ 2์ด ๋์ ์์ง์ด๋ฉฐ ๋ ๋ค ๋ค๋ฅธ ๊ณก์ ๋ ์ฌ์ฉํฉ๋๋ค.
๋ด๊ฐ ์ค ๋ ์ค๋ํซ์ ์ฌ์ฉํ์ฌ ๋ ์นด์ดํฐ๋ฅผ ๋์์ ์ฆ๊ฐ์ํฌ ์ ์์ผ๋ฉฐ ์ ๋๋ฉ์ด์ ์ ๋ชจ๋ ๋จ์ผ ํ๋ ์ ๋์ "์ด๊ณ"๊ฐ ์ ํํ ๊ฒ์ ๋๋ค. ์ฒซ ๋ฒ์งธ ์นด์ดํฐ๊ฐ ๊ณ์ ์์ง์ด๋ ๋์ ๋ ๋ฒ์งธ ์นด์ดํฐ๊ฐ ์ ๋๋ฉ์ด์ ์ ์ค์งํ๋๋ผ๋
๋ฐ๋ฉด์ ๊ตฌํ์์๋ 2๊ฐ์ TweenAnimationBuilder๋ฅผ ํ๋๋ก ๋ณํฉํ๊ธฐ ๋๋ฌธ์ ์ด ๊ฒฝ์ฐ๋ฅผ ๊ณ ๋ คํ์ง ์์ต๋๋ค.
์ด๋ฅผ ์์ ํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์์ฑํด์ผ ํฉ๋๋ค.
Observer(
builder: (context) {
return TweenAnimationBuilder<int>(
duration: const Duration(seconds: 5),
curve: Curves.easeOut,
tween: IntTween(end: counters.firstCounter),
builder: (context) {
return Observer(
valueListenable: secondCounter,
builder: (context, value2, child) {
return TweenAnimationBuilder<int>(
duration: const Duration(seconds: 2),
curve: Curves.easeInOut,
tween: IntTween(end: counters.secondCounter),
builder: (context, value2, child) {
return Text('${value + value2}');
},
);
},
);
},
);
},
)
๋ ๊ฐ์ TweenAnimationBuilders
๋ ๋ ์นด์ดํฐ ๋ชจ๋ ๊ฐ๋ณ์ ์ผ๋ก ์ ๋๋ฉ์ด์
ํ ์ ์๋ค๋ ์ฌ์ค์ ์กด์คํ๋ ๋ฐ ํ์ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฒซ ๋ฒ์งธ Observer
๋ counters.secondCounter
๊ด์ฐฐํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ ๊ฐ์ Observer
๊ฐ ํ์ํฉ๋๋ค.
์๋ ๊ทธ๋ฅ ์๋. ํํฌ ์์ ฏ์ ๋ชจ๋ ๋จ์ผ ๋น๋์์ ๋ณ๊ฒฝ ์ฌํญ์ ์ง์์ ์ผ๋ก ํด๋งํฉ๋๋ค. valuelistenables๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ๋น๋๋ "๋ฐ์ํ"์ ๋๋ค.
Element
๊ฐ ํ๋ ์ผ์ ๋ฌด์ํ๊ณ ์์ต๋๋ค. ์ด๋ ํํฌ๊ฐ ํ๋ ์ผ๊ณผ ๋์ผํฉ๋๋ค. ์ฆ runtimeType๊ณผ ํค๋ฅผ ๋น๊ตํ๊ณ ์ ์์๋ฅผ ๋ง๋ค์ง ๊ธฐ์กด ์์๋ฅผ ์
๋ฐ์ดํธํ ์ง ๊ฒฐ์ ํฉ๋๋ค.
๋๋ ๋น์ ์ ์๋ฅผ ์ทจํ๊ณ ์ค์ฒฉ๋ ValueListenableBuilders * ๋ฐ ํธ์ ๋น๋๋ฅผ "๋ค๋ฃจ์์ต๋๋ค"
์ด ๊ฐ์ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์๋ค๊ณ ๊ฐ์ ํ๋ฉด ์ด๋ค ์ค์ฒฉ์ด ์ ๊ฑฐ๋์์ต๋๊น?
Observer(
builder: (context) => TweenAnimationBuilder<int>(
duration: const Duration(seconds: 5),
curve: Curves.easeOut,
tween: IntTween(end: counters.firstCounter),
builder: (context, value, child) {
return Text('$value');
},
),
),
๋ค์๊ณผ ๋ค๋ฅด์ง ์์ต๋๋ค.
ValueListenableBuilder<int>(
valueListenable: firstCounter,
builder: (context, value, child) => TweenAnimationBuilder<int>(
duration: const Duration(seconds: 5),
curve: Curves.easeOut,
tween: IntTween(end: value),
builder: (context, value, child) {
return Text('$value');
},
),
),
์ค์ฒฉ ์ธก๋ฉด์์.
์์ ์ ์ธ๊ธํ๋ ๊ฒฝ์ฐ ์ด์ ์ ์ธ๊ธํ๋ฏ์ด ์ด ์ ๊ทผ ๋ฐฉ์์ TickerProvider
/ TickerMode
์ค๋จํฉ๋๋ค. vsync
๋ SingleTickerProviderClientStateMixin
๋ฅผ ์ฌ์ฉํ์ฌ ์ป์ด์ผ ํ๋ฉฐ ๊ทธ๋ ์ง ์์ผ๋ฉด ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์๋ ์์๊ฑฐ ๋
ผ๋ฆฌ๋ฅผ ์ง์ํ์ง ์์ต๋๋ค.
๋ด ๊ธฐ์ฌ์์ ์ด๊ฒ์ ์ค๋ช
ํ์ต๋๋ค. https://dash-overflow.net/articles/why_vsync/
๊ทธ๋ฆฌ๊ณ ์ด ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ์๋ TweenAnimationBuilder๊ฐ ํ์ํ ๋ชจ๋ ์์น์์ Tween ๋ ผ๋ฆฌ๋ฅผ ๋ค์ ๊ตฌํํด์ผ ํฉ๋๋ค. ํนํ ๋ ผ๋ฆฌ๊ฐ ๊ทธ๋ ๊ฒ ์ฌ์ํ์ง ์๋ค๋ ์ ์ ๊ณ ๋ คํ๋ฉด ์๋นํ ์ค๋ณต์ด ๋ฐ์ํฉ๋๋ค.
๋ด๊ฐ ์ค ๋ ์ค๋ํซ์ ์ฌ์ฉํ์ฌ ๋ ์นด์ดํฐ๋ฅผ ๋์์ ์ฆ๊ฐ์ํฌ ์ ์์ผ๋ฉฐ ์ ๋๋ฉ์ด์ ์ ๋ชจ๋ ๋จ์ผ ํ๋ ์ ๋์ "์ด๊ณ"๊ฐ ์ ํํ ๊ฒ์ ๋๋ค. ์ฒซ ๋ฒ์งธ ์นด์ดํฐ๊ฐ ๊ณ์ ์์ง์ด๋ ๋์ ๋ ๋ฒ์งธ ์นด์ดํฐ๊ฐ ์ ๋๋ฉ์ด์ ์ ์ค์งํ๋๋ผ๋
๋ฐ๋ฉด์ ๊ตฌํ์์๋ 2๊ฐ์ TweenAnimationBuilder๋ฅผ ํ๋๋ก ๋ณํฉํ๊ธฐ ๋๋ฌธ์ ์ด ๊ฒฝ์ฐ๋ฅผ ๊ณ ๋ คํ์ง ์์ต๋๋ค.
๋ค, ๊ทธ๊ฑด ์ ๊ฐ ๊ธฐ๊บผ์ด ํ๋ ค๊ณ ํ๋ ์ ์ถฉ์์ ๋๋ค. ์ ๋๋ฉ์ด์ ์ด ๋ณ๊ฒฝ ์ฌํญ์ ๋ํ ์๊ฐ์ ํผ๋๋ฐฑ์ผ ๋ฟ์ด๊ณ ์ ํ์ฑ์ด ์ค์ํ์ง ์์ ๊ฒฝ์ฐ๋ฅผ ์ฝ๊ฒ ์์ํ ์ ์์ต๋๋ค. ๊ทธ๊ฒ์ ๋ชจ๋ ์๊ตฌ ์ฌํญ์ ๋ฌ๋ ค ์์ต๋๋ค.
๋๋ ๋น์ ์ด ์ด์๋ฅผ ์ ๊ธฐํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๊ธฐ ๋๋ฌธ์ ์ด ์ ํํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋์์ ์ฝ๋๋ฅผ ๋์ฑ ๊น๋ํ๊ฒ ๋ง๋๋ ๋ ๋ฒ์งธ ๋ฒ์ ์ด ์์ต๋๋ค.
์์ ์ ์ธ๊ธํ๋ ๊ฒฝ์ฐ ์ด์ ์ ์ธ๊ธํ๋ฏ์ด ์ด ์ ๊ทผ ๋ฐฉ์์ TickerProvider/TickerMode๋ฅผ ์ค๋จํฉ๋๋ค. vsync๋ SingleTickerProviderClientStateMixin์ ์ฌ์ฉํ์ฌ ๊ฐ์ ธ์์ผ ํ๋ฉฐ ๊ทธ๋ ์ง ์์ผ๋ฉด ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์๋ ์์๊ฑฐ ๋ ผ๋ฆฌ๋ฅผ ์ง์ํ์ง ์์ต๋๋ค.
๋ฐ๋ผ์ ์์ ฏ์์ tickerprovider๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผ ์นด์ดํฐ์ ์ ๋ฌํฉ๋๋ค. ๋ํ ์ ๋๋ฉ์ด์ ์ปจํธ๋กค๋ฌ๋ ํ๊ธฐํ์ง ์์์ต๋๋ค. ์ด๋ฌํ ์ธ๋ถ ์ฌํญ์ ๊ตฌํํ๊ธฐ๊ฐ ๋๋ฌด ์ฌ์์ ์์ ์ ์๋ฌด๊ฒ๋ ์ถ๊ฐํ ๊ฒ ๊ฐ์ง ์์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๊ธฐ์์ ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ๋ค์ ์ฟ๋ณด๊ณ ์์ต๋๋ค.
๋๋ Counter() ํด๋์ค๋ฅผ ๊ตฌํํ์ฌ ๊ทํ์ ์์ ์ ๊ทธ ์ด์์ ์ํํ์ง ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ์๋ TweenAnimationBuilder๊ฐ ํ์ํ ๋ชจ๋ ์์น์์ Tween ๋ ผ๋ฆฌ๋ฅผ ๋ค์ ๊ตฌํํด์ผ ํฉ๋๋ค. ํนํ ๋ ผ๋ฆฌ๊ฐ ๊ทธ๋ ๊ฒ ์ฌ์ํ์ง ์๋ค๋ ์ ์ ๊ณ ๋ คํ๋ฉด ์๋นํ ์ค๋ณต์ด ๋ฐ์ํฉ๋๋ค.
๋ญ๋ผ๊ณ ์? ์์? ์ค๋ช ํด์ฃผ์ธ์. Counter ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ๋ ๊ฐ ์ด์ ๋ง๋ค๊ณ ๋ค์ํ ์์ ฏ์์ ์ฌ์ฉํ ์ ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
@Rudiksz ๊ทํ์ ์๋ฃจ์ ์ด ์ค์ ๋ก ์ ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๋น์ ์ ๋งํ๋ค
๋๋ Counter() ํด๋์ค๋ฅผ ๊ตฌํํ์ฌ ๊ทํ์ ์์ ์ ๊ทธ ์ด์์ ์ํํ์ง ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์์ง
๋ค, ๊ทธ๊ฑด ์ ๊ฐ ๊ธฐ๊บผ์ด ํ๋ ค๊ณ ํ๋ ์ ์ถฉ์์ ๋๋ค. ์ ๋๋ฉ์ด์ ์ด ๋ณ๊ฒฝ ์ฌํญ์ ๋ํ ์๊ฐ์ ํผ๋๋ฐฑ์ผ ๋ฟ์ด๊ณ ์ ํ์ฑ์ด ์ค์ํ์ง ์์ ๊ฒฝ์ฐ๋ฅผ ์ฝ๊ฒ ์์ํ ์ ์์ต๋๋ค. ๊ทธ๊ฒ์ ๋ชจ๋ ์๊ตฌ ์ฌํญ์ ๋ฌ๋ ค ์์ต๋๋ค.
๋ฐ๋ผ์ ์์ ฏ์์ tickerprovider๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผ ์นด์ดํฐ์ ์ ๋ฌํฉ๋๋ค. ๋ํ ์ ๋๋ฉ์ด์ ์ปจํธ๋กค๋ฌ๋ ํ๊ธฐํ์ง ์์์ต๋๋ค. ์ด๋ฌํ ์ธ๋ถ ์ฌํญ์ ๊ตฌํํ๊ธฐ๊ฐ ๋๋ฌด ์ฌ์์ ์์ ์ ์๋ฌด๊ฒ๋ ์ถ๊ฐํ ๊ฒ ๊ฐ์ง ์์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๊ธฐ์์ ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ๋ค์ ์ฟ๋ณด๊ณ ์์ต๋๋ค.
@rrousselGit ์ ํํฌ ๋ฒ์ ๊ณผ ํ๋ฉด์ ์ผ๋ก๋ง ๋์ผํ ์ฝ๋๋ฅผ ์ ๊ณตํ์ง๋ง, ํํฌ ๋ฒ์ ์ ํฌํจ๋ ๋ถ๋ถ์ ์๋ตํ๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก๋ ๋์ผํ์ง ์์ต๋๋ค. ๊ทธ๋ฐ ๊ฒฝ์ฐ์๋ ๋น๊ต๊ฐ ๋์ง ์์ฃ ? ์ ์๋ ์๋ฃจ์ ๊ณผ ์๋ฃจ์ ์ ๋น๊ตํ๋ ค๋ฉด ์๋ฃจ์ ์ ํฌํจํ์ง ์์ ์ด์ ์ ๋ํด ์ด์ผ๊ธฐํ๋ ๋์ ์๊ตฌ ์ฌํญ๊ณผ ์ ํํ ์ผ์นํ๋๋ก ํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๋ค. ์ด๊ฒ์ด @TimWhiting ์ ์ ์ฅ์๋ฅผ ๋ง๋๋ ์ด์ ์ ๋๋ค. ๋ชจ๋ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๋ค๊ณ ์๊ฐ๋๋ ๊ฒฝ์ฐ ์๋ฃจ์ ์ ์ ์ถํ ์ ์์ต๋๋ค.
๋น์ ์ ๋ถ๋ช ํ ์์ ๋ฅผ ์คํํ๋ ค๊ณ ํ์ง๋ ์์์ต๋๋ค. ์ฝ๋์ ๋๊ฐ์ด ์๋ํฉ๋๋ค.
์๋ ๊ทธ๋ฅ ์๋.
๋๋ด์ด์๊ตฐ์. ๋๋ ๋น์ ์ ์๋ฅผ ์ทจํ๊ณ ์ค์ฒฉ๋ ValueListenableBuilders * ๋ฐ ํธ์ ๋น๋๋ฅผ "๋ค๋ฃจ์์ต๋๋ค"
์ด๋ฌํ ๋น๋์ ์ผ๊ฐํด ์ฃผ์ญ์์ค. ์ด๋ฌํ ๋น๋์ ๊ทผ๋ณธ์ ์ธ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ์๊ณ ์ด ์ค๋ ๋๋ฅผ ์ ๋ํ๊ฒ ๋ง๋ค ๋ฟ์ ๋๋ค. ์๋๋ฐฉ์ ๋น๋ฐฉํ๊ฑฐ๋ ๋น๋ฐฉํ๊ฑฐ๋ ํ๋ด์ง ์๊ณ ์์ ์ ๋งํ ์ ์์ต๋๋ค. ์ด๊ฒ์ด ์ ๊ฐ ์ด ์ค๋ ๋์์ ๋ณธ ๋๊ธ์ ํจ๊ณผ์ ๋๋ค. ๋ํ ์์ ์ ๊ฒ์๋ฌผ์ ์ด๋ชจํฐ์ฝ์ผ๋ก ๋ฐ์ํ๋ ํจ๊ณผ๊ฐ ๋ฌด์์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
@rrousselGit
๋งํฌ๋ ์ค๋ํซ์ ๊ธฐ๋ฐ์ผ๋ก ์์ ๋ฅผ ๋ง๋๋ ๋ฐ ๋์์ ๋๋ฆด ์ ์์ง๋ง ์ด ์ค๋ํซ์ด ์ถฉ๋ถํ์ง ์์ ์ด์ ๋ฅผ ์์์ผ ํฉ๋๋ค.
๊ทธ๋ ์ง ์์ผ๋ฉด ๋ด๊ฐ ํ ์ ์๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ์ด๋ฌํ ์ค๋ํซ์ ์ปดํ์ผํ๋ ๊ฒ์ ๋๋ค. ํ์ง๋ง ๊ทธ๊ฒ์ด ๋น์ ์ด ์ํ๋ ๊ฒ์ธ์ง ์์ฌ์ค๋ฝ์ต๋๋ค.
๋ด๊ฐ ๋จ์ํ ์ค๋ํซ๋ณด๋ค ๋ ์ ๊ตํ ์ฑ์ ์์ฒญํ๋ ์ด์ ๋ ๋ด๊ฐ ๊ทํ์ ์ค๋ํซ ์ค ํ๋๋ฅผ ์ฒ๋ฆฌํ ์์ ๋ฅผ ๊ฒ์ํ์ ๋, ๋น์ ์ด ๊ทธ๊ฒ์ด ์ ์ ํ์ง ์์ ๋ค๋ฅธ ๊ฒฝ์ฐ๋ ์ฒ๋ฆฌํ์ง ์์๊ธฐ ๋๋ฌธ์ ์ถฉ๋ถํ์ง ์๋ค๊ณ ๋งํ๊ธฐ ๋๋ฌธ์ ๋๋ค. '(์: didUpdateWidget์ ์ฒ๋ฆฌํ์ง ์์๊ฑฐ๋ ์ด๋ฌํ ์ค๋ํซ ์ค ๋ ๊ฐ๋ฅผ ๋๋ํ ๋๋ ๊ฒ์ ์ฒ๋ฆฌํ์ง ์์๊ฑฐ๋ ์ฒ๋ฆฌํ๊ณ ์ ํ๋ ๊ธฐํ ์๋ฒฝํ๊ฒ ํฉ๋ฆฌ์ ์ธ ๊ฒ). ์ข ๋ ์ ๊ตํ ์ฑ์ ์ฌ์ฉํ๋ฉด ์๋ฃจ์ ์ด ํ๋ณด๋๋ฉด ์ฒ๋ฆฌํด์ผ ํ๋ ์๋ก์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ "๊ณ ๋ฏผ" ์๊ฐ์ด ์๋๋ก ์ถฉ๋ถํ ์ ๊ตํ๊ฒ ๋ง๋ค ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๋ถ๋ช ํ ์ฐ๋ฆฌ ๋ชจ๋๊ฐ ์ฒ๋ฆฌํด์ผ ํ๋ ๋ฌด์ธ๊ฐ๋ฅผ ๋์น ๊ฐ๋ฅ์ฑ์ด ์์ง๋ง ์์ด๋์ด๋ ๊ธฐํ๋ฅผ ์ต์ํํ๋ ๊ฒ์ ๋๋ค.
๊ทธ๋ค์ง ํ์๋ฐ์ง ๋ชปํ๋ ์ต๊ทผ ๊ฒ์๋ฌผ๊ณผ ๊ด๋ จํ์ฌ ์ฌ๋ฌ๋ถ, ์์ ์์ ๋ก ์๋ค ๊ฐ๋ค ํ๋ ๊ฒ๋ณด๋ค @TimWhiting ์ repo์์ ์์ ๋ฅผ ๋ง๋๋ ๋ฐ ์ง์คํฉ์๋ค. ์ฐ๋ฆฌ๊ฐ ์ด๋ฏธ ๋ ผ์ํ ๋ฐ์ ๊ฐ์ด, ์์ ์๋ ๋์์ด ์ค์ ๋ก ์ ์๋ํจ์ ์ ์ฆํ๊ธฐ์ ์ถฉ๋ถํ ๋ํํ ๋งํผ ์ถฉ๋ถํ ์ ๊ตํ์ง ์์ ๊ฒ์ ๋๋ค.
๋ชจ๋ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ๋ค๊ณ ์๊ฐ๋๋ ๊ฒฝ์ฐ ์๋ฃจ์ ์ ์ ์ถํ ์ ์์ต๋๋ค.
์ฌ์ค ์ดํ์ ์๊ตฌ ์ฌํญ์ด ๋ณ๊ฒฝ๋์์ต๋๋ค. ๋๋ ๋ ๊ฐ์ง ํด๊ฒฐ์ฑ ์ ์ ์ํ๋ค. ํํ์ ํ๋ ๊ฒ(๋งค์ฐ ํฉ๋ฆฌ์ ์ธ ๊ฒ)๊ณผ ์ ๊ณต๋ ์์ ๋ฅผ ์ ํํ ๊ตฌํํ๋ ๊ฒ.
@rrousselGit ์ ํํฌ ๋ฒ์ ๊ณผ ํ๋ฉด์ ์ผ๋ก๋ง ๋์ผํ ์ฝ๋๋ฅผ ์ ๊ณตํ์ง๋ง ์ค์ ๋ก๋ ๋์ผํ์ง ์์ต๋๋ค.
"ํํฌ ์๋ฃจ์ "์ ๊ตฌํํ์ง ์๊ณ ValueListenableBuilder ์์ ๋ฅผ ๊ตฌํํ์ผ๋ฉฐ ํนํ "์ค์ฒฉ ๋ฌธ์ "์ ์ค์ ์ ๋ก๋๋ค. ํํฌ๊ฐ ํ๋ ๋ชจ๋ ์ผ์ ํ๋ ๊ฒ์ ์๋๋๋ค. ์ ๋ ๋จ์ํ ๋ถ๋ง ๋ชฉ๋ก์ ํ ํญ๋ชฉ์ ๋์ฒด ์๋ฃจ์ ์ ์ฌ์ฉํ์ฌ ๋จ์ํํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ์์ต๋๋ค.
ํ ๋ก ์ ์ธ๋ถ ํจํค์ง๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค๋ฉด ์ ๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค.
์ฌ์ฌ์ฉ์ฑ: ์๋ ๋ฆฌํฌ์งํ ๋ฆฌ์ ์๋ฅผ ์ดํด๋ณด์ธ์.
https://github.com/Rudiksz/cbl_example
๋ฉ๋ชจ:
ํธ์ง: ์ด ์์ ์๋ ๋ฒ๊ทธ๊ฐ ์์ต๋๋ค. ๋ณ๊ฒฝ ์ฌํญ์ด ์ ๋๋ฉ์ด์ ๋๋ ๋์ "์ฆ๊ฐ"๋ฅผ ์์ํ๋ฉด ์นด์ดํฐ๊ฐ ์ฌ์ค์ ๋๊ณ ํ์ฌ ๊ฐ์์ ์ฆ๊ฐํฉ๋๋ค. ์ด "์นด์ดํฐ"์ ๋ํ ์ ํํ ์๊ตฌ ์ฌํญ์ ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ์ผ๋ถ๋ฌ ์์ ํ์ง ์์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฆ๊ฐ/๊ฐ์ ๋ฐฉ๋ฒ์ ๋ณ๊ฒฝํ๋ ๊ฒ์ ๊ฐ๋จํฉ๋๋ค.
๊ทธ๊ฒ ๋ค์ผ.
@Hixie ๋ด ์(https://github.com/TimWhiting/local_widget_state_approaches/blob/master/lib/hooks/animated_counter.dart)๊ฐ ์ถฉ๋ถํ์ง ์๋ค๊ณ ๋งํ๋ ๋ฐฉ์์ผ๋ก ๊ทํ์ ์๊ฒฌ์ ํด์ํด์ผ ํฉ๋๊น?
๋ํ Zoom/Google ๋ชจ์ ํตํ๋ฅผ ํ ์ ์์ต๋๊น?
๋ํ ์์ ์ ๊ฒ์๋ฌผ์ ์ด๋ชจํฐ์ฝ์ผ๋ก ๋ฐ์ํ๋ ํจ๊ณผ๊ฐ ๋ฌด์์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
์๋ฌด๊ฒ๋. ๊ทธ๊ฒ์ ์ ํ ๊ด๋ จ์ด ์์ต๋๋ค. ์ ๊บผ๋์ด?
@rrousselGit ์ถฉ๋ถํ ์ข์์ง ๋ณธ์ธ ๋ง์ด ์ ์ ์์ต๋๋ค. ํด๋น ์์ ๋ฅผ ๋ฆฌํฉํ ๋งํ์ฌ ๊น๋ํ๊ณ ์งง๊ณ ์ค๋ณต ์ฝ๋๊ฐ ์๋๋ก ํ๋ ๋ฐฉ๋ฒ์ ์ฐพ์ผ๋ฉด ๋ง์กฑํ์ค๊น์? ์๋๋ฉด ์ด ๋ฒ๊ทธ๋ฅผ ์ถฉ์กฑ์ํค๊ธฐ ์ํด ์ฒ๋ฆฌํด์ผ ํ๋ ํด๋น ์์ ์์ ์ฒ๋ฆฌ๋์ง ์๋ ์ง์ํด์ผ ํ๋ค๊ณ ์๊ฐํ๋ ํญ๋ชฉ์ด ์์ต๋๊น?
์ถฉ๋ถํ ์ข์์ง ๋น์ ๋ง์ด ์ ์ ์์ต๋๋ค
๋๋ ๊ทธ๊ฒ์ ๋ํด ํ๋จํ ์ ์๋ค. ์ฐ์ , ์ ํํ ์์ฉ ํ๋ก๊ทธ๋จ ์งํฉ์ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํฌ์ฐฉํ ์ ์๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
๋๋ ๋น์ ์ด ์ํ๋ ๋๋ก ์ผํ๋ ๊ฒ์ ์ ๊ฒฝ ์ฐ์ง ์์ง๋ง ๊ทธ๊ฒ์ด ์ฐ๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ๋ฐ์ ์ํฌ์ง ์ดํดํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ์ง๋๊ฐ ํ์ํฉ๋๋ค.
์ฐ๋ฆฌ์ ๊ด์ ์์ ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๋ ์๋ง์ ์ฝ๋ ์กฐ๊ฐ์ ์ ๊ณตํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ํ์๋ ์์ ๊ฐ ์ํํ์ง ์๋ ๊ฒฝ์ฐ ๋ ๋ง์ ์ฝ๋ ์์ ๋ฅผ ํตํด ๋ ๋ช ํํด์ง ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์ฝ๊ธฐ์ ๋์ฐํ ์ฌ๋ฌ ์ค์ฒฉ ๋น๋๋ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ๋ง์ 50์ค์ ์์ ์์ฉ๊ตฌ๋ฅผ ๋ณด๊ณ ๋ ๋ฌธ์ ๋ฅผ ์ถฉ๋ถํ ๊ฐ๋ ฅํ๊ฒ ์ ์ฆํ์ง ๋ชปํ๋ค๋ฉด ๊ฐ ๊ณณ์ด ์์ต๋๋ค.
์ ์ฒด ์์ฒญ์ด ์บก์ํ๋ ์ํ ์ผ ๋ ๋ฏน์ค์ธ์ ์ ์ํ๊ณ ํจ์๊ฐ ์๋ฃจ์ ์ธ ๊ฒ์ ๋งค์ฐ ์ด์ํฉ๋๋ค. ๋ค์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ํจ์๋ ์ํ๋ฅผ ์ ์งํ ์ ์์ต๋๋ค. ๋ฏน์ค์ธ์ ์บก์ํ๋์ง ์์ต๋๋ค. ์ด ์ ์์ ์ ๊ณต๋ ๋ชจ๋ ์์ ๊ทผ๊ฑฐ์ ์์ ์ ๋์น๊ณ ์ฌ์ ํ ์ง๋ฌธ์ ๋ํ ๊น์ ์คํด๋ฅผ ๋ณด์ฌ์ค๋๋ค.
์ ์๊ฐ์๋ ์ฐ๋ฆฌ๊ฐ 2์ ์ ์ด๊ธฐ๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ ์ชฝ๋ ์ฌ๊ฐํ๊ฒ ๋ ผ์ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
์ฌ๋ฌ ๋ฒ ์ธ๊ธํ๋ฏ์ด Remi์ ์ค๋ฌธ์กฐ์ฌ์์๋ ๊ฐ๋จํ ๋งํด์: ์ฐ๋ฆฌ๋ builder์ ์ฅํฉํจ๊ณผ ์ค์ฒฉ๋ ํด๋ก์ ์์ด builder์ ๊ธฐ๋ฅ์ ์ํฉ๋๋ค. ๊ทธ๊ฒ์ด ์์ ํ ์์ฝ๋์ง ์์ต๋๊น? ์ฌ๊ธฐ์ ๊ณ์ ์งํํ๋ ค๋ฉด ์ถ๊ฐ ์ฝ๋ ์์ ๊ฐ ํ์ํ ์ด์ ๊ฐ ์์ ํ ํผ๋์ค๋ฝ์ต๋๋ค.
Remi์ ์ค๋ฌธ์กฐ์ฌ์ ๋ฐ๋ฅด๋ฉด Flutter ๊ฐ๋ฐ์์ 80%๋ ๊ฐ๋ฅํ ๊ฒฝ์ฐ ์ฝ๋์์ ์ค์ฒฉ๋ ๋น๋๋ฅผ ํผํ๋ ์ผ์ข ์ ๊ธฐ๋ฅ์ ์ ํธํฉ๋๋ค. ์ด๊ฒ์ ์ ๋ง๋ก ๊ทธ ์์ฒด๋ก ๋งํด์ค๋๋ค. ์ปค๋ฎค๋ํฐ ๊ฐ์ ์ด ๋งค์ฐ ๋ช ํํ ๋ ์ด ์ค๋ ๋์์ ์ฐ๋ฆฌ์๊ฒ์ ๊ทธ๊ฒ์ ๊ฐ์ ธ๊ฐ ํ์๊ฐ ์์ต๋๋ค.
๋ด ๊ด์ ์์ ๋ฌธ์ ๋ ๋ช ํํ๋ฉฐ ์ฌ๊ธฐ์์ ๊ทผ๊ฑฐ๋ฅผ ์ค๋ช ํ๋ ๋ฐ ๋จ๋ฝ์ ์ง์ ํ๋ ๊ฒฝ์ ํ๋ ์์ํฌ๋ฅผ ๋ณด๋ฉด ํจ์ฌ ๋ ๋ช ํํด์ง๋๋ค. Vue, React, Flutter๋ ๋ชจ๋ ์ฌ์ด์ด๋ฉฐ ๋ชจ๋ React์์ ํ์๋์์ผ๋ฉฐ ์์ ฏ ์๋ช ์ฃผ๊ธฐ์ ์ฐ๊ฒฐํด์ผ ํ๋ ์ฌ์ฌ์ฉ ์ํ์ ๊ด๋ จ๋ ์ด ๋ฌธ์ ์ ๋ชจ๋ ์ง๋ฉดํฉ๋๋ค. ๊ทธ๋ค์ ๋ชจ๋ ์ ์ด์ ๊ฐ์ ๊ฒ์ ๊ตฌํํ๋์ง ์์ธํ ์ค๋ช ํฉ๋๋ค. ๊ด์ฐฎ์ต๋๋ค. ๋ชจ๋ ๊ด๋ จ์ด ์์ต๋๋ค.
@rrousselGit ์ฌ๋ฌ ๊ฐ์ ํํฌ๊ฐ ์๋ ์๋ฅผ ๋ง๋ค ์ ์์ต๋๊น? ์๋ฅผ ๋ค์ด, ์์ญ ๊ฐ์ AnimationController๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋๋ฉ์ด์ ์ ๋ง๋ค๊ณ ์์ต๋๋ค. ์ผ๋ฐ Flutter๋ก ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
List<AnimationController> controllers = [];
int numAnimationControllers = 50;
<strong i="7">@override</strong>
void initState() {
for (int i = 0; i < numAnimationControllers; i++)
controllers.add(AnimationController(...));
}
<strong i="8">@override</strong>
void dispose() {
for (int i = 0; i < numAnimationControllers; i++)
controllers[i].dispose();
}
๊ทธ๋ฌ๋ ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฃจํ์์ useAnimationController
๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค. ๋๋ ์ด๊ฒ์ด ์ฌ์ํ ์๋ผ๊ณ ์๊ฐํ์ง๋ง ์ค์ ๋ก ์ด๋ฌํ ์ ํ์ ์ฌ์ฉ ์ฌ๋ก์ ๋ํ ์๋ฃจ์
์ ์ฐพ์ ์ ์์์ต๋๋ค.
@satvikpendem
ํ๋ก๋์ ์ค์ธ ๋ด ์ฑ์ ๋ช ๊ฐ์ง ์(ํ์ด์ง ๋งค๊น๊ณผ ํจ๊ป ์์ฒญ ๋ณด๋ด๊ธฐ์ ๊ฐ์ ์ผ๋ถ ํํฌ๋ ๋จ์ผ ํํฌ๋ก ๋ณํฉ/๋ฆฌํฉํฐ๋งํ ์ ์์ง๋ง ์ฌ๊ธฐ์๋ ๊ด๋ จ์ด ์์):
ํ์ด์ง ๋งค๊น์ผ๋ก ๊ฐ๋จํ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ:
final selectedTab = useState(SelectedTab.Wallet);
final isDrawerOpen = useValueNotifier(false);
final pageNo = useValueNotifier(0);
final generalData = useValueNotifier(initialData);
final services = useXApi();
final isLoading = useValueNotifier(false);
final waybillData = useValueNotifier<List<WaybillResponseModel>>([]);
final theme = useTheme();
final router = useRouter();
fetchNextPage() async {
if (isLoading.value || selectedTab.value != SelectedTab.Wallet) return;
isLoading.value = true;
final request = WaybillRequestModel()..pageNo = pageNo.value;
final result = await services.waybillGetList(model: request);
if (result.isOk && result.data.length > 0) {
pageNo.value += 1;
waybillData.value = [...waybillData.value, ...result.data];
}
isLoading.value = false;
}
// first fetch
useEffect(() {
fetchNextPage();
return () {};
}, []);
์์ ๋ ผ๋ฆฌ(์ ํ๋ฒํธ ํ์ธ ๋ฐ ์ฌ์ ์ก ํ์ด๋จธ๊ฐ ์๋ ๋ก๊ทธ์ธ ์์):
final theme = useTheme();
final loginState = useValueNotifier(LoginState.EnteringNumber);
final error = useValueNotifier<String>(null);
final phoneNumberController = useTextEditingController(text: "");
final phoneNumberFocusNode = useMemoized(() => FocusNode(), []);
final otpFocusNode = useMemoized(() => FocusNode(), []);
final otpController = useTextEditingController(text: "");
final appState = Provider.of<AppStateController>(context);
final services = useXApi();
final router = useRouter();
final resendTimerValue = useValueNotifier(0);
useEffect(() {
var timer = Timer.periodic(Duration(seconds: 1), (t) async {
if (resendTimerValue.value > 0) resendTimerValue.value--;
});
return () => timer.cancel();
}, []);
final doLogin = () async {
// login
loginState.value = LoginState.LoggingIn;
final loginResult = await services.authLoginOrRegister(
mobileNumber: phoneNumberController.text,
);
if (loginResult.isOk) {
loginState.value = LoginState.EnteringOtpCode;
WidgetsBinding.instance.addPostFrameCallback((_) {
FocusScope.of(context).requestFocus(otpFocusNode);
});
resendTimerValue.value = 30;
} else {
error.value = loginResult.errorMessage;
loginState.value = LoginState.EnteringNumber;
WidgetsBinding.instance.addPostFrameCallback((_) {
FocusScope.of(context).requestFocus(phoneNumberFocusNode);
});
}
};
์ ๋๋ฉ์ด์ ์ ๊ฒฝ์ฐ @rrousselGit์ด ์ด๋ฏธ ์ถฉ๋ถํ ์๋ฅผ ์ ๊ณตํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํํฌ์ ๊ตฌ์ฑ ๊ฐ๋ฅํ ํน์ฑ์ผ๋ก ์ธํด ์ ์ฝ๋์ ๋ฆฌํฉํ ๋ง์ด ํจ์ฌ ๋ ์ฝ๊ณ , ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๊ณ , ๊น๋ํด์ง ์ ์๋ค๋ ์ ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์ถ์ง๋ ์์ง๋ง, ์ํ์ ๋ค๋ฉด ๋ฆฌํฉํ ๋ง๋ ๋ฒ์ ๋ ๊ฒ์ํ ์ ์์ต๋๋ค.
์ฌ๋ฌ ๋ฒ ์ธ๊ธํ๋ฏ์ด Remi์ ์ค๋ฌธ์กฐ์ฌ์์๋ ๊ฐ๋จํ ๋งํด์: ์ฐ๋ฆฌ๋ builder์ ์ฅํฉํจ๊ณผ ์ค์ฒฉ๋ ํด๋ก์ ์์ด builder์ ๊ธฐ๋ฅ์ ์ํฉ๋๋ค. ๊ทธ๊ฒ์ด ์์ ํ ์์ฝ๋์ง ์์ต๋๊น? ์ฌ๊ธฐ์ ๊ณ์ ์งํํ๋ ค๋ฉด ์ถ๊ฐ ์ฝ๋ ์์ ๊ฐ ํ์ํ ์ด์ ๊ฐ ์์ ํ ํผ๋์ค๋ฝ์ต๋๋ค.
๋๋ ๋ง ๊ทธ๋๋ก Remi๊ฐ ์ ๊ณตํ ์์ ๋ฅผ ์ฌ์ฉํ์ฌ ์ฅํฉํจ์ ์ค์ด๊ณ ๋น๋์ ์ค์ฒฉ์ ํผํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ํ ์์ ๋ฅผ ์ ๊ณตํ์ต๋๋ค.
๋๋ ๊ทธ์ ์ฝ๋๋ฅผ ๋ด ์ฑ์ ์ง์ด๋ฃ๊ณ ์คํํ๊ณ ๋ค์ ์์ฑํ์ต๋๋ค. ๊ธฐ๋ฅ์ ๊ดํ ํ ์ต์ข
๊ฒฐ๊ณผ๋ ๊ฑฐ์ ๋์ผํ์ต๋๋ค. ์ฝ๋์ ์๊ตฌ ์ฌํญ์ด ์์๊ธฐ ๋๋ฌธ์ ์ฝ๋๋ฅผ ์คํํ๋ ๊ฒ๋ง์ผ๋ก๋ ์ ์ ์์์ต๋๋ค. ๋ฌผ๋ก ์ฐ๋ฆฌ๋ ๊ทน๋จ์ ์ธ ๊ฒฝ์ฐ์ ์ ์ฌ์ ์ธ ๋ฌธ์ ์ ๋ํด ๋
ผ์ํ ์ ์์ง๋ง ๊ทธ ๋์ ์ฃผ์ ๋ฅผ ๋ฒ์ด๋ ๊ฒ์ผ๋ก ๋ถ๋ ธ์ต๋๋ค.
๊ฐ๋จํ ์ฌ์ฉ ์ฌ๋ก์๋ Builders๋ฅผ ์ฌ์ฉํ๊ณ ๋ณต์กํ ์ฌ์ฉ ์ฌ๋ก์๋ Builders๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค. ์ฌ๊ธฐ์ ์ฃผ์ฅ์ ๋น๋๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๊ฐ๊ฒฐํ๊ณ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ฝ๋๋ฅผ ์์ฑํ๋ ์ฌ์ด ๋ฐฉ๋ฒ์ด ์๋ค๋ ๊ฒ์ ๋๋ค. ์์์ ์ผ๋ก ์ด๋ Builders๊ฐ ๋ฐ๋์ ์์ด์ผ ํ๋ฉฐ Flutter ์ฑ์ ๊ฐ๋ฐํ๋ ์ ์ผํ ๋ฐฉ๋ฒ์ด๋ผ๋ ์๋ฏธ์ด๊ธฐ๋ ํฉ๋๋ค. ๊ทธ๊ฒ์ ๋ช ๋ฐฑํ ๊ฑฐ์ง์ ๋๋ค.
๋ฐฉ๊ธ ์๋ํ๋ ๊ฐ๋
์ฆ๋ช
์ฝ๋๋ฅผ ๋ณด์ฌ์ฃผ์์ต๋๋ค. ๋น๋๋ ํํฌ๋ฅผ ์ฌ์ฉํ์ง ์์์ผ๋ฉฐ ์ด ํน์ github ๋ฌธ์ ๊ฐ ํด๊ฒฐํ๊ณ ์ ํ๋ "๋ฌดํํ ๋ฌธ์ ์ธํธ"๋ฅผ 100% ๋ค๋ฃจ์ง ์์ต๋๋ค. ์ฃผ์ ๋ฅผ ๋ฒ์ด๋ ๊ฒ์ด๋ผ๊ณ ํ์ต๋๋ค.
์ฐธ๊ณ ๋ก, ๋ฒค์น๋งํฌ๊ฐ ์์ด๋ ๋น๋ ์์ ฏ์ ๋ฅ๊ฐํ ์ ๋๋ก ๋งค์ฐ ํจ์จ์ ์
๋๋ค. ์๋ชป๋ ๊ฒ์ผ๋ก ํ๋ช
๋๋ฉด ๋ง์์ ๋ฐ๊พธ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค. Mobx๊ฐ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ด ๋๋ ๊ฒ์ ๋ฐ๊ฒฌํ๋ฉด ์ฆ์ Mobx๋ฅผ ๋ฒ๋ฆฌ๊ณ ๋ฐ๋๋ผ ๋น๋๋ก ์ ํํ ๊ฒ์
๋๋ค.
Hixie๋ Google์์ ์ผํ๊ธฐ ๋๋ฌธ์ ์ธ๋ด์ฌ์ ๊ฐ๊ณ ์์ ๋ฐ๋ฅด๊ฒ ๋ํด์ผ ํ๋ฉฐ ์ฐธ์ฌ๊ฐ ๋ถ์กฑํ๋ค๊ณ ๋ถ๋ฅผ ์ ์์ต๋๋ค. ๊ทธ๊ฐ ํ ์ ์๋ ์ต์ ์ ๋ ๋ง์ ์๋ฅผ ์ ์ํ๋ ๊ฒ์ ๋๋ค.
๋๋ ๋๊ตฌ์ ์ด๋ฆ๋ ๋ถ๋ฅด์ง ์์๊ณ ์ธ์ ๊ณต๊ฒฉ๋ ํ์ง ์์๋ค. ๋๋ ์ฌ๊ธฐ์ ์ ์๋ ์ฃผ์ฅ์๋ง ๋ฐ์ํ์ผ๋ฉฐ ๋ด ์๊ฒฌ์ ๊ณต์ ํ์ต๋๋ค.
(๋ด๊ฐ ์๋ ๊ฒ์ ์ธ๊ธฐ๊ฐ ์๊ณ ์์์ ๋ถ๊ณผํจ) ์ฌ์ง์ด ์ค์ ์นด์ดํฐ ์์ ๋ฅผ ์ฝ๋๋ก ์ ์ํ๋ ค๊ณ ์๋ํ์ต๋๋ค. ๋ ๋ง์ ๊ฒ์ ํ ์ ์์ต๋๋ค. ์ ์ฌ๋ก๊ฐ ๋ถ์กฑํ ๋ถ๋ถ์ ๋ํด ๋
ผ์ํ๊ณ ์ด๋ฅผ ๊ฐ์ ํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ชจ์ํ๊ณ ์ถ์ง๋ง, ์ฃผ์ ์์ ๋ฒ์ด๋๋ ๊ฒ์ ์ผ์ข
์ ๋ถ์พํ ์ผ์
๋๋ค.
๋๋ ๊ธ์ง๋นํ๋ ๊ฒ ์ธ์๋ ์์ ๊ฒ์ด ์๊ธฐ ๋๋ฌธ์ ๋น์ ์ ๋ถ๋ฌ๋ ์๊ด์์ต๋๋ค.
๋น์ ์ด ๊ฒฝํํ๋ ๋ฌธ์ ๊ฐ ๋ฌด์์ด๋ ๊ฐ์ ํํฌ๊ฐ ์ ์ผํ ํด๊ฒฐ์ฑ
("React๊ฐ ๊ทธ๊ฒ์ ์ํํ๊ธฐ ๋๋ฌธ์")์ด๊ณ ๋์์ด ๋น์ ์ด ์์ํ๋ "๋ฌดํํ ๋ฌธ์ ์ธํธ"๋ฅผ 100% ์ฑ์ฐ์ง ์๋ ํ, ๋น์ ๋์ ์ฃฝ์ ์ธํธ๋ผ๋ ๊ฒ์ด ๋ถ๋ช
ํฉ๋๋ค. ๋น์ ์ ์ฐธ์ฌ๋ฅผ ๊ณ ๋ คํ์ง ์์ ๊ฒ์
๋๋ค.
์ด๋ ํฉ๋ฆฌ์ ์ด์ง ์์ผ๋ฉฐ ์ง์ ์ผ๋ก ์ฐธ์ฌํ๋ ค๋ ์๊ตฌ๊ฐ ๋ถ์กฑํจ์ ๋ณด์ฌ์ค๋๋ค.
๋ฌผ๋ก ์์ ๋ด์ฉ์ ๋ชจ๋ "๋ด ์๊ฐ์ผ ๋ฟ"์ ๋๋ค.
๊ทธ ์์์ ํํฌ์ ์ ์ฉ์ฑ์ ๋ณด์์ง๋ง ๋ด ๊ฒฝ์ฐ์๋ ๋ง์ ๊ฐ์ฒด๋ฅผ ํ ๋ฒ์ ์ด๊ธฐํํ๋ ค๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ ๊ฒฝ์ฐ(์ด ๊ฒฝ์ฐ AnimationController
s) ์๋ ๋ฐฉ์์ ์ดํดํ์ง ๋ชปํ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ค์ ๋ก๋ ๋ฌด์์ด๋ ๋ ์ ์์ต๋๋ค. ํํฌ๋ ์ด ๊ฒฝ์ฐ๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํฉ๋๊น?
๊ธฐ๋ณธ์ ์ผ๋ก ์ด๊ฒ์ ๋๋ฆฌ๋ ํํฌ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค
var x1 = useState(1);
var x2 = useState(2);
var x3 = useState(3);
์์ผ๋ก
var xs = []
for (int i = 0; i < 3; i++)
xs[i] = useState(i);
ํํฌ ๊ท์น์ ์๋ฐํ์ง ์๊ณ ? ์ผ๋ฐ Flutter์ ๋๋ฑํ ํญ๋ชฉ์ ๋์ดํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ ๋ Flutter์ ํํฌ์ ๋ํด ๊ฒฝํ์ด ๋ง์ง ์์ผ๋ ์ฐธ๊ณ ํ์ธ์.
๋ชจ๋ initState๋ฅผ ์ฌ์ฉํ์ฌ ์์ฒญ ์ ํํฌ ๊ฐ์ฒด(์: AnimationController)์ ๋ฐฐ์ด์ ๋ง๋ค๊ณ ์ด๋ฏธ ์ธ์คํด์คํ๋ ํ๊ธฐ๋ฅผ ์ํฉ๋๋ค. ํํฌ์์ ์ด๋ป๊ฒ ์๋ํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
@satvikpendem ์ ํด๋์ค์ ์์ฑ๊ณผ ๊ฐ์ ํํฌ์ ๋ํด ์๊ฐํฉ๋๋ค. ๋ฃจํ์์ ์ ์ํ๊ฑฐ๋ ์๋์ผ๋ก ํ๋์ฉ ์ด๋ฆ์ ์ง์ ํฉ๋๊น?
๋ค์๊ณผ ๊ฐ์ด ์ ์ํ๋ ๊ทํ์ ์์์
var x1 = useState(1);
var x2 = useState(2);
var x3 = useState(3);
์ด ์ฌ์ฉ ์ฌ๋ก์ ์ ์ฉํฉ๋๋ค.
var isLoading = useState(1);
var selectedTab = useState(2);
var username = useState(3); // text field
๊ฐ useState
๊ฐ ์ํ ๋
ผ๋ฆฌ์ ๋ช
๋ช
๋ ๋ถ๋ถ๊ณผ ์ด๋ป๊ฒ ๊ด๋ จ๋์ด ์๋์ง ์ ์ ์์ต๋๊น? (์: isLoading์ useState๋ ์ฑ์ด ๋ก๋ ์ํ์ผ ๋ ์ฐ๊ฒฐ๋จ)
๋ ๋ฒ์งธ ์ค๋ํซ์์๋ ๋ฃจํ์์ useState
๋ฅผ ํธ์ถํฉ๋๋ค. useState
๋ฅผ ์ํ ๋
ผ๋ฆฌ์ ์ผ๋ถ๊ฐ ์๋ ๊ฐ์น ๋ณด์ ์๋ก ์๊ฐํ๊ณ ์์ต๋๋ค. ์ด ๋ชฉ๋ก์ ListView
์ ํญ๋ชฉ์ ๋ฌด๋ฆฌ๋ฅผ ํ์ํ๋ ๋ฐ ํ์ํฉ๋๊น? ๊ทธ๋ ๋ค๋ฉด ๋ชฉ๋ก์ ๋ชจ๋ ํญ๋ชฉ์ ๊ฐ๋ณ์ ์ผ๋ก๊ฐ ์๋ ์ํ๋ก ์๊ฐํด์ผ ํฉ๋๋ค.
final listData = useState([]);
์ด๊ฒ์ useState
์ ๋ํ ๊ฒ์ด๋ฉฐ ์กฐ๊ฑด์ด๋ ๋ฃจํ์์ ์ผ๋ถ ํํฌ๋ฅผ ํธ์ถํ๋ ๋ช ๊ฐ์ง ์ฌ์ฉ ์ฌ๋ก(๋งค์ฐ ๋๋ฌผ๋ค๊ณ ์๊ฐํฉ๋๋ค)๋ฅผ ๋ณผ ์ ์์ต๋๋ค. ์ด๋ฌํ ์ข
๋ฅ์ ํํฌ์๋ ๋ฐ์ดํฐ ๋ชฉ๋ก์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ํํฌ๊ฐ ์์ด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด:
var single = useTest("data");
var list = useTests(["data1", "data2"]);
// which is equivalent to
var single1 = useTest("data1");
var single2 = useTest("data2");
์ฌ๋ฌ AnimationController์ ๊ฐ์ ํญ๋ชฉ ๋ฐฐ์ด์ด ์๋ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ํํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ณ๋์ ํํฌ๋ฅผ ๋ง๋ค์ด์ผ ํ๋ ๊ฒ์ฒ๋ผ ๋ณด์ ๋๋ค.
์ด๊ฒ์ ๋ด๊ฐ ์ฒ์์ ์๋ํ์ง ์๋ ๊ฒ์ ๋๋ค.
final animationControllers = useState<List<AnimationController>>([]);
animationControllers.value = List<AnimationController>.generate(
50,
(_) => useAnimationController(),
);
ํ์ง๋ง ์ฌ๋ฌ ํญ๋ชฉ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ๋ด ์์ ์ ํํฌ๋ฅผ ์์ฑํ๋ฉด ์ด๊ฒ์ด ์๋ํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
class _MultipleAnimationControllerHook extends Hook<MultipleAnimationController> {
const _MultipleAnimationControllerHook({
this.numControllers,
this.duration,
this.debugLabel,
this.initialValue,
this.lowerBound,
this.upperBound,
this.vsync,
this.animationBehavior,
List<Object> keys,
}) : super(keys: keys);
/// Take in number of controllers wanted
/// This hook assumes all `AnimationController`s will have the same parameters
final int numControllers;
final Duration duration;
final String debugLabel;
final double initialValue;
final double lowerBound;
final double upperBound;
final TickerProvider vsync;
final AnimationBehavior animationBehavior;
<strong i="10">@override</strong>
_AnimationControllerHookState createState() =>
_AnimationControllerHookState();
}
class _AnimationControllerHookState
extends HookState<AnimationController, _AnimationControllerHook> {
List<AnimationController> _multipleAnimationController; // return a list instead of a singular item
<strong i="11">@override</strong>
void initHook() {
super.initHook();
for (int i = 0; i < hook.numControllers) // just added loops
_multipleAnimationController[i] = AnimationController(
vsync: hook.vsync,
duration: hook.duration,
debugLabel: hook.debugLabel,
lowerBound: hook.lowerBound,
upperBound: hook.upperBound,
animationBehavior: hook.animationBehavior,
value: hook.initialValue,
);
}
<strong i="12">@override</strong>
void didUpdateHook(_AnimationControllerHook oldHook) {
for (int i = 0; i < numControllers; i++) {
if (hook.vsync != oldHook[i].vsync) {
_multipleAnimationController[i].resync(hook.vsync);
}
if (hook.duration != oldHook[i].duration) {
_multipleAnimationController[i].duration = hook.duration;
}
}
}
<strong i="13">@override</strong>
MultipleAnimationController build(BuildContext context) {
return _multipleAnimationController;
}
<strong i="14">@override</strong>
void dispose() {
_multipleAnimationController.map((e) => e.dispose());
}
}
์ด๊ฒ์ ๋จ์ผ ๋ฒ์ ์ ํํฌ๊ฐ ์๋ ๊ฒฝ์ฐ ๋จ์ํ ์ฌ๋ฌ ํญ๋ชฉ์ด ์๋ ๋ฒ์ ์ ์ฌ์ฉํ ์ ์๊ณ ๋์ ๋ ผ๋ฆฌ๋ฅผ ๋ค์ ์์ฑํด์ผ ํจ์ ์๋ฏธํฉ๋๊น? ์๋๋ฉด ์ด ์์ ์ ์ํํ๋ ๋ ์ข์ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
๋๊ตฐ๊ฐ๊ฐ non-hooks ์์ ๋ฅผ ์ ๊ณตํ๊ณ ์ถ์ด๋ ์ ๋ ์๊ณ ์ถ์ต๋๋ค. ์ฌ์ฌ์ฉ ๊ฐ๋ฅ์ฑ ํผ์ฆ์ ์ด ๋ถ๋ถ์ ๋ํด ๊ถ๊ธํฉ๋๋ค. ๊ณ ์ ํ AnimationController ํ๋๊ฐ ์๋ ํด๋์ค์ ์ด ๋์์ ์บก์ํํ๋ ๋ฐฉ๋ฒ์ด ์์ ์ ์์ง๋ง ๋ฃจํ ๋ด๋ถ์์ ์์ฑ๋ ๊ฒฝ์ฐ ํํฌ๋ ๊ท์น์ ์๋ฐํ๊ฒ ๋ฉ๋๋ค. ์๋ง๋ Vue๊ฐ ํํฌ ๊ตฌํ์ ์ํ ์กฐ๊ฑด๊ณผ ๋ฃจํ์ ์ํฅ์ ๋ฐ์ง ์๋ ๋ฐฉ์์ ๊ณ ๋ คํ ์ ์์ต๋๋ค.
@satvikpendem
๋ด ์ง์ ์ด AnimationController
๋๋ useAnimationController
์ ํจํ์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํ๋ ์ด์์ AnimationController
๊ฐ์ง ์ ์์ง๋ง ํด๋์ค ๋ฉ์๋์์ ์ฌ์ฉํ๊ธฐ ์ํด ๋ฐ๋์ ๋ฐฐ์ด์ ์ ์ฅํ ํ์๋ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์๋ฅผ ๋ค์ด:
useSingleTickProvider();
final animation1 = useAnimationController();
final animation2 = useAnimationController();
final animation3 = useAnimationController();
// ...
useEffect(() async {
await animation1.forward();
await Future.sleep(100);
await animation1.reverse();
await animation2.forward();
await animation3.forward();
}, []);
(๋ชฉ๋ก์ ๋ง๋ค๊ณ animation[0]
์ ๊ฐ์ด ์ฐธ์กฐํ์ง ์์)
์์งํ ํํฌ์ ๋ฐ์ํ๊ณ ํ๋ฌํฐ์ ๋ํ ๋ด ๊ฒฝํ์ ๋ฐ๋ฅด๋ฉด ๋ฃจํ์์ ์ผ์ข ์ ํํฌ๋ฅผ ํธ์ถํ ํ์๊ฐ ๊ฑฐ์ ์์์ต๋๋ค. ๊ทธ๋๋ ์๋ฃจ์ ์ ๊ฐ๋จํ๊ณ ๊ตฌํํ๊ธฐ ์ฌ์ ์ต๋๋ค. ์ด์ ๋๋ ๊ทธ๊ฒ์ ๋ํด ์๊ฐํฉ๋๋ค. IMO๊ฐ "๋ ๊นจ๋ํ"์๋ฃจ์ ์ธ ๊ฐ ๊ตฌ์ฑ ์์(์์ ฏ)๋ฅผ ๋ง๋๋ ๊ฒ๊ณผ ๊ฐ์ ๋ ๋์ ๋ฐฉ๋ฒ์ผ๋ก ํ์คํ ํด๊ฒฐํ ์ ์์ต๋๋ค.
์ฌ๋ฌ AnimationController
๋ฅผ ์ฒ๋ฆฌํ๋ ๋ ์ฌ์ด ๋ฐฉ๋ฒ์ด ์์ผ๋ฉด ๊ทํ์ ์ง๋ฌธ์ ๋๋ตํ๊ธฐ ์ํด ๋ค์์ด ์์ต๋๋ค.
final ticker = useTickerProvider();
final controllers = useMemo(() => [AnimationController(ticker), AnimationController(ticker)], []);
useEffect(() {
controllers.forEach(x => x.resync(ticker));
return () => controllers.forEach(x => x.dispose());
}, [ticker, controllers]);
AnimationController
๊ฐ ๋์ ์ด๋ฉด useState
๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.(ํฐ์ปค๊ฐ ๋ณ๊ฒฝ๋๋ฉด ๋ค์ ๋๊ธฐํ๋ฉ๋๋ค)
@rrousselGit ์ฌ๋ฌ ๊ฐ์ ํํฌ๊ฐ ์๋ ์๋ฅผ ๋ง๋ค ์ ์์ต๋๊น? ์๋ฅผ ๋ค์ด, ์์ญ ๊ฐ์ AnimationController๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋๋ฉ์ด์ ์ ๋ง๋ค๊ณ ์์ต๋๋ค. ์ผ๋ฐ Flutter๋ก ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
List<AnimationController> controllers = []; int numAnimationControllers = 50; <strong i="8">@override</strong> void initState() { for (int i = 0; i < numAnimationControllers; i++) controllers.add(AnimationController(...)); } <strong i="9">@override</strong> void dispose() { for (int i = 0; i < numAnimationControllers; i++) controllers[i].dispose(); }
๊ทธ๋ฌ๋ ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฃจํ์์
useAnimationController
๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค. ๋๋ ์ด๊ฒ์ด ์ฌ์ํ ์๋ผ๊ณ ์๊ฐํ์ง๋ง ์ค์ ๋ก ์ด๋ฌํ ์ ํ์ ์ฌ์ฉ ์ฌ๋ก์ ๋ํ ์๋ฃจ์ ์ ์ฐพ์ ์ ์์์ต๋๋ค.
ํํฌ๋ ๋ค๋ฅด๊ฒ ์๋ํฉ๋๋ค.
๋ ์ด์ ์ปจํธ๋กค๋ฌ ๋ชฉ๋ก์ ์์ฑํ์ง ์๊ณ ์ปจํธ๋กค๋ฌ ๋ก์ง์ ํญ๋ชฉ์ผ๋ก ์ด๋ํฉ๋๋ค.
Widget build(context) {
return ListView(
children: [
for (var i = 0; i < 50; i++)
HookBuilder(
builder: (context) {
final controller = useAnimationController();
},
),
],
);
}
์ฐ๋ฆฌ๋ ์ฌ์ ํ 50๊ฐ์ ์ ๋๋ฉ์ด์ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค์์ง๋ง ๋ค๋ฅธ ์์ ฏ์ด ์์ ํ๊ณ ์์ต๋๋ค.
์ ๊ทธ๊ฒ์ด ํ์ํ์ง์ ๋ํ ์๋ฅผ ๊ณต์ ํ๊ณ ํํฌ๋ก ๋ณํํ์ฌ Tim์ ์ ์ฅ์์ ์ถ๊ฐํ ์ ์์ต๋๊น?
Hixie๋ Google์์ ์ผํ๊ธฐ ๋๋ฌธ์ ์ธ๋ด์ฌ์ ๊ฐ๊ณ ์์ ๋ฐ๋ฅด๊ฒ ๋ํด์ผ ํ๋ฉฐ ์ฐธ์ฌ๊ฐ ๋ถ์กฑํ๋ค๊ณ ๋ถ๋ฅผ ์ ์์ต๋๋ค. ๊ทธ๊ฐ ํ ์ ์๋ ์ต์ ์ ๋ ๋ง์ ์๋ฅผ ์ ์ํ๋ ๊ฒ์ ๋๋ค.
@Hixie , ๊ทธ๋ ๊ฒ ๋๋ผ์๋ฉด ๊ทธ๋ ๊ฒ ๋ง์ํด ์ฃผ์ธ์(์ฌ๊ธฐ์์ ๋๋ ๊ฐ์ธ์ ์ผ๋ก ์ ์๊ฒ ์ฐ๋ฝํ์ญ์์ค).
๋๋ ๋ง ๊ทธ๋๋ก Remi๊ฐ ์ ๊ณตํ ์์ ๋ฅผ ์ฌ์ฉํ์ฌ ์ฅํฉํจ์ ์ค์ด๊ณ ๋น๋์ ์ค์ฒฉ์ ํผํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ํ ์์ ๋ฅผ ์ ๊ณตํ์ต๋๋ค.
๊ฐ์ฌํฉ๋๋ค. ํ์ง๋ง ์ด ๋ ผ๋ฆฌ๋ฅผ ๋ค๋ฅธ ์ฌ์ฉ ์ฌ๋ก์ ์ ์ฉํ ๋ ์ด ์ฝ๋์์ ๊ณตํต ํจํด์ ์ถ์ถํ๋ ๋ฐฉ๋ฒ์ด ๋ช ํํ์ง ์์ต๋๋ค.
OP์์ ๋๋ ํ์ฌ 3๊ฐ์ง ์ ํ์ด ์๋ค๊ณ ์ธ๊ธํ์ต๋๋ค.
StreamBuilder
๋ฐ AsyncSnapshot
๋ ๋ณต์กํ ์ํ ๋
ผ๋ฆฌ๋ผ๊ณ ์ฃผ์ฅํฉ๋๋ค).์ธ ๋ฒ์งธ ์ ํ( Property
๋๋ addDispose
์ ์์ ์ด๊ธฐ ๋ฐ๋ณต๊ณผ ๋์ผํ ๋ฒ์ฃผ์ ์์)์ ์ฌ์ฉํ ๊ฒ ๊ฐ์ต๋๋ค.
์ด์ ์ ํจํด์ ํ๋จํ๊ธฐ ์ํด ํ๊ฐ ๊ทธ๋ฆฌ๋๋ฅผ ๋ง๋ค์์ต๋๋ค.
์ด๊ฒ์ ๋ํ ๋ณํ์ ์คํํ ์ ์์ต๋๊น? ํนํ StreamBuilder
์ ๋ชจ๋ ๊ธฐ๋ฅ์ ์ฌ๋ฌ ๋ฒ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ฝ๋ ์ค๋ณต ์์ด ๊ตฌํ
์ด ๋ฒ๊ทธ์ ๋ํ ํ์ฌ ๊ณํ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋๊ตฐ๊ฐ ์ด ์ค ํ๋๋ฅผ ๋์์ฃผ๊ณ ์ถ๋ค๋ฉด ๊ธฐ๊บผ์ด ๋์์ ๋๋ฆฌ๊ฒ ์ต๋๋ค. NNBD ์ ํ์ ๋จผ์ ์์ ํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๊ณง ์ด ๋ฌธ์ ์ ๋๋ฌํ ๊ฒ ๊ฐ์ง ์์ต๋๋ค.
@rrousselGit ๋ฌผ๋ก , ์ ๋ ๋ง์ ์์ ฏ์ด ํ๋ฉด ์ฃผ์๋ฅผ ์ด๋ํ ์ ์๋ ์ฑ์ ๋ง๋ค๊ณ ์์ผ๋ฉฐ( Box
es๋ผ๊ณ ๋ถ๋ฅด๊ฒ ์ต๋๋ค), ์๋ก ๋
๋ฆฝ์ ์ผ๋ก ์์ง์ผ ์ ์์ด์ผ ํฉ๋๋ค(๋ฐ๋ผ์ ์ต์ํ ๊ฐ Box
์ ๋ํด ํ๋์ AnimationController ). ๋ค์์ ์ฌ๋ฌ ์์ ฏ ๊ฐ์ ๊ณต์ ๋๋ ๋จ ํ๋์ AnimationController๋ก ๋ง๋ ๋ฒ์ ์
๋๋ค. ๊ทธ๋ฌ๋ ๋ฏธ๋์๋ ๊ฐ ์์ ฏ์ ๋
๋ฆฝ์ ์ผ๋ก ์ ๋๋ฉ์ด์
ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋ง์ถค ์คํฌ๋กค ํ ํจ๊ณผ๋ฅผ ์ฌ์ฉํ์ฌ CupertinoPicker
๊ตฌํ๊ณผ ๊ฐ์ ๋ณต์กํ ๋ณํ์ ์ํํ ์ ์์ต๋๋ค. .
Stack์๋ FloatingActionButton์ ํด๋ฆญํ ๋ ์์๋๋ก ์์ง์ด๋ ์ธ ๊ฐ์ ์์๊ฐ ์์ต๋๋ค.
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
void main(List<String> args) => runApp(const App());
class App extends HookWidget {
const App({Key key});
static const Duration duration = Duration(milliseconds: 500);
static const Curve curve = Curves.easeOutBack;
<strong i="11">@override</strong>
Widget build(BuildContext context) {
final AnimationController controller =
useAnimationController(duration: duration);
final Animation<double> animation = Tween<double>(
begin: 0,
end: 300,
)
.chain(
CurveTween(
curve: curve,
),
)
.animate(controller);
final ValueNotifier<bool> isDown = useState<bool>(false);
final ValueNotifier<int> numBoxes = useState<int>(3);
return MaterialApp(
home: SafeArea(
child: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
if (!isDown.value) {
controller.forward();
isDown.value = true;
} else {
controller.reverse();
isDown.value = false;
}
},
),
body: AnimatedBuilder(
animation: animation,
builder: (_, __) => Boxes(
numBoxes: numBoxes.value,
animation: animation,
),
),
),
),
);
}
}
class Boxes extends StatelessWidget {
Boxes({
<strong i="12">@required</strong> this.numBoxes,
<strong i="13">@required</strong> this.animation,
});
final int numBoxes;
final Animation<double> animation;
<strong i="14">@override</strong>
Widget build(BuildContext context) {
return Stack(
children: List<Widget>.generate(
numBoxes,
(int index) => Positioned(
top: (animation.value) + (index * (100 + 10)),
left: (MediaQuery.of(context).size.width - 100) / 2,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
),
// ],
);
}
}
์ด ๊ฒฝ์ฐ ๊ฐ ์์๋ ์ผ์ ํ ์์ง์ด์ง๋ง ์๋ฅผ ๋ค์ด ์ ๋ ฌ ๊ธฐ๋ฅ์ ๋ํ ์๊ฐํ๋ฅผ ์์ฑํ๊ฑฐ๋ ์ ๋๋ฉ์ด์
๋ชฉ๋ก์์ ์์๋ฅผ ์ด๋ํ๋ ๊ฒ๊ณผ ๊ฐ์ ๋ ๋ณต์กํ ์๋๋ฆฌ์ค๋ฅผ ์์ํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์ ์์ ์์ ฏ์ ๊ฐ Box
์์น์ ๋ํ ๋ฐ์ดํฐ๋ฅผ ์๊ณ ์์ต๋๋ค.
๋ฌธ์ ๋ AnimationControllers์ ์์ง์์ ๊ตฌ๋ํ๋ ๋ฐ ์ฌ์ฉํ๋ Box
๊ฐ ๊ฐ์ ํด๋์ค์ ์์ง ์๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํ ๋ฐฐ์ด์ ์ ์งํ์ฌ AnimationController๋ฅผ ํต๊ณผํด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค. Builder ๋๋ ๊ฐ Box
๊ฐ ์์ฒด AnimationController๋ฅผ ์ ์งํ๋๋ก ํฉ๋๋ค.
ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด Box
es์ ์์ ์์ ฏ์ด ๊ฐ์ ํด๋์ค์ ์์ง ์์ ๊ฒฝ์ฐ ๊ฐ Box
๊ฐ AnimationController์์ ์ ๋ฌ๋๋ ์ฒซ ๋ฒ์งธ ๊ฒฝ์ฐ์ ๋ํด AnimationController ๋ชฉ๋ก์ ์ด๋ป๊ฒ ๋ง๋ค๊น์? ์ด๊ฒ์ HookBuilder๋ฅผ ์ฌ์ฉํ ์์ ๋ต๋ณ์ ๊ธฐ๋ฐ์ผ๋ก ํ ๋ ํ์ํ์ง ์์ ๊ฒ ๊ฐ์ง๋ง, ๋ง์ํ์ ๋๋ก ์ํ๋ฅผ ํ์ ์์ ฏ์ผ๋ก ์ด๋ํ๊ณ ๊ฐ Box
useAnimationController
๋ฅผ ํตํด ์์ฒด AnimationController๋ฅผ ๊ฐ๋๋ก ์ ํํ๋ฉด , ๋ ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค. ์์ฑ๋ AnimationController๋ฅผ ๋ถ๋ชจ ํด๋์ค์ ๋
ธ์ถํ์ฌ ๊ฐ ์์์ ๋ํ ๋
๋ฆฝ ์ ๋๋ฉ์ด์
์ ์กฐ์ ํ๊ณ ์คํํ ์ ์๋๋ก ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํฉ๋๊น?
Vue์์๋ emit
ํจํด์ ํตํด ์ด๋ฒคํธ๋ฅผ ๋ถ๋ชจ์๊ฒ ๋ค์ ๋ด๋ณด๋ผ ์ ์์ผ๋ฏ๋ก Flutter์์๋ ๋ถ๋ชจ๊ฐ ์ ์ญ ์ํ๋ฅผ ์
๋ฐ์ดํธํ๊ณ ์์์ด ์ ์ญ ์ํ๋ฅผ ์์ ํ๋ Riverpod ๋๋ Rx์ ๊ฐ์ ๊ณ ๊ธ ์ํ ๊ด๋ฆฌ ์๋ฃจ์
์ด ํ์ํฉ๋๊น? ์ํ? ์ ์ด๋ ์ด์ ๊ฐ์ ๊ฐ๋จํ ์์์๋ ๊ทธ๋ ์ง ์์ ๊ฒ ๊ฐ์ต๋๋ค. ๋ด ํผ๋์ ํด๊ฒฐํด ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค.
@satvikpendem ์ฃ์กํฉ๋๋ค. ๋ช ํํ์ง ์์์ต๋๋ค. ํํฌ๋ก ์ฐจ๋จํ๋ ๋ฌธ์ ๊ฐ ์๋๋ผ ํํฌ ์์ด ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค ์ ์์ต๋๊น?
์ด๋์์ ๋งํ๊ธฐ ๋ณด๋ค๋ ๋ฌด์์ ํ๋ ค๋์ง ๋ช ํํ ์ดํดํ๊ณ ์ถ์ต๋๋ค.
๊ทธ๋ฌ๋ ๋น ๋ฅธ ์ถ์ธก์ผ๋ก, ๋์ Interval ๊ณก์ ์ ์ฐพ๊ณ ์๊ณ ๋จ์ผ ์ ๋๋ฉ์ด์ ์ปจํธ๋กค๋ฌ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
@rrousselGit ๋ฌผ๋ก ์ ๋๋ค.
import 'package:flutter/material.dart';
void main(List<String> args) => runApp(const App());
class Animator {
Animator({this.controller, this.animation});
AnimationController controller;
Animation<double> animation;
}
class App extends StatefulWidget {
const App({Key key});
static const Duration duration = Duration(milliseconds: 500);
static const Curve curve = Curves.easeOutBack;
<strong i="7">@override</strong>
_AppState createState() => _AppState();
}
class _AppState extends State<App> with TickerProviderStateMixin {
List<Animator> animators = [];
bool isDown = false;
int numBoxes = 3;
<strong i="8">@override</strong>
void initState() {
for (int i = 0; i < numBoxes; i++) {
final AnimationController c = AnimationController(
duration: App.duration,
vsync: this,
);
animators.add(
Animator(
controller: c,
animation: Tween<double>(
begin: 0,
end: 300,
)
.chain(
CurveTween(
curve: App.curve,
),
)
.animate(c),
),
);
}
super.initState();
}
<strong i="9">@override</strong>
void dispose() {
for (int i = 0; i < numBoxes; i++) {
animators[i].controller.dispose();
}
super.dispose();
}
<strong i="10">@override</strong>
Widget build(BuildContext context) {
return MaterialApp(
home: SafeArea(
child: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
if (!isDown) {
for (final Animator animator in animators) {
animator.controller.forward();
}
setState(() {
isDown = true;
});
} else {
for (final Animator animator in animators) {
animator.controller.reverse();
}
setState(() {
isDown = false;
});
}
},
),
body: Stack(
children: List<Box>.generate(
numBoxes,
(int index) => Box(
index: index,
animation: animators[index].animation,
),
),
),
),
),
);
}
}
class Box extends StatelessWidget {
Box({
<strong i="11">@required</strong> this.animation,
<strong i="12">@required</strong> this.index,
});
final int index;
final Animation<double> animation;
<strong i="13">@override</strong>
Widget build(BuildContext context) {
return Positioned(
top: (animation.value) + (index * (100 + 10)),
left: (MediaQuery.of(context).size.width - 100) / 2,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
);
}
}
๋๋ ์ค์ ๋ก ๊ฐ ์์ ฏ์ ๋ํด ํ๋์ฉ ์ฌ๋ฌ ์ ๋๋ฉ์ด์ ์ปจํธ๋กค๋ฌ๋ฅผ ์ํฉ๋๋ค. ์๋ก ๋ ๋ฆฝ์ ์ผ๋ก ์ด๋ํ ์ ์๊ณ ์์ฒด ์ง์ ์๊ฐ, ๊ณก์ ๋ฑ์ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์์ ์ฝ๋์๋ ๋ด๊ฐ ํ์ ํ ์ ์๋ ๋ฒ๊ทธ๊ฐ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊น๋ํ๊ฒ ์ ๋๋ฉ์ด์ ๋์ด์ผ ํ์ง๋ง ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฒํผ ํด๋ฆญ ์ 3๊ฐ์ ์์๋ฅผ ์์๋๋ก ์ ๋๋ฉ์ด์ ํด์ผ ํฉ๋๋ค. ์ฐ๋ฆฌ๋ ๊ฐ๊ฐ์ด ๋์ผํ ๊ณก์ ์ ๊ฐ๋ ๋์ ์ ๊ฐ๊ฐ ๋ค๋ฅธ ๊ณก์ ์ ์ ๊ณตํ๊ฑฐ๋ ์ด์ ๊ฒ๋ณด๋ค ์ง์ ์๊ฐ์ด ๋ ๊ธธ๊ฑฐ๋ ์งง์ 100๊ฐ์ ์์๋ฅผ ๋ง๋ค๊ฑฐ๋ ์ง์๋ฅผ ์๋ก ์ฌ๋ฆฌ๋ ์๋๋ฆฌ์ค๋ฅผ ์์ํ ์ ์์ต๋๋ค. ์ด์ํ ๊ฒ๋ค์ ๋ด๋ ค๊ฐ๋๋ค.
์ผ๋ฐ Flutter๋ฅผ ์ฌ์ฉํ๋ฉด initState
๋ฐ dispose
๋ ๋ค ๋ฃจํ๋ฅผ ๊ฐ์ง ์ ์์ง๋ง ํํฌ๊ฐ ์๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง ์์ผ๋ฏ๋ก ์ด๋ป๊ฒ ๋์ฒํ ์ ์๋์ง ๊ถ๊ธํฉ๋๋ค. ๋ํ Box
ํด๋์ค๋ฅผ ๋ถ๋ชจ ์์ ฏ ์์ ๋ฃ๊ณ ์ถ์ง ์์ต๋๋ค. ๋ ๋ค ๋จ๋จํ ์บก์ํํ๊ณ ์ถ์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์์ ๋
ผ๋ฆฌ๋ฅผ ๋์ผํ๊ฒ ์ ์งํ ์ ์์ด์ผ ํ์ง๋ง ์๋ฅผ ๋ค์ด Box
๋ฅผ Box2
๋ก ๋ฐ๊ฟ ์ ์์ด์ผ ํฉ๋๋ค.
๊ฐ์ฌ ํด์!
ํํฌ์ ํด๋นํ๋ @TimWhiting ์ repo์ ๊ทํ์ ์๋ฅผ ํธ์ํ์ต๋๋ค.
TL;DR, ํํฌ(๋๋ ๋น๋)๋ฅผ ์ฌ์ฉํ๋ฉด ๋ช ๋ นํ์ด ์๋๋ผ ์ ์ธํ์ผ๋ก ์๊ฐํฉ๋๋ค. ๋ฐ๋ผ์ ํ๋์ ์์ ฏ์ ์ปจํธ๋กค๋ฌ ๋ชฉ๋ก์ด ์๋ ๋์ ์ปจํธ๋กค๋ฌ๋ฅผ ํญ๋ชฉ์ผ๋ก ์ด๋ํ๊ณ ์์์ ์ ๋๋ฉ์ด์ ์ ๊ตฌํํ๋ ๋ช ๋ น์ ์ผ๋ก ๊ตฌ๋ํฉ๋๋ค.
@rrousselGit ๊ฐ์ฌํฉ๋๋ค! ํํฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์์ํ ํ ์ ์ ๋์ ์ด๋ฌํ ์ ํ์ ๊ตฌํ์ ์ด๋ ค์์ ๊ฒช์์ง๋ง ์ด์ ์ด๋ป๊ฒ ์๋ํ๋์ง ์ดํดํฉ๋๋ค. ์์์ ๋งํ๋ฏ์ด ํํฌ๊ฐ ์ ์ฉํ ์ด์ ๋ฅผ ์ดํดํ๋ ๋ฐ ๋ ๋งค๋ ฅ์ ์ผ ์ ์์ผ๋ฏ๋ก ๊ฐ ์ ๋๋ฉ์ด์ ์ปจํธ๋กค๋ฌ์ ๋ํด ๋ค๋ฅธ ๋์์ด ์๋ ๋ฒ์ ์ ๋ํ PR์ ์ด์์ต๋๋ค.
์ฐ๋ฆฌ๋ ๊ฐ๊ฐ์ด ๋์ผํ ๊ณก์ ์ ๊ฐ๋ ๋์ ์ ๊ฐ๊ฐ ๋ค๋ฅธ ๊ณก์ ์ ์ ๊ณตํ๊ฑฐ๋ ์ด์ ๊ฒ๋ณด๋ค ์ง์ ์๊ฐ์ด ๋ ๊ธธ๊ฑฐ๋ ์งง์ 100๊ฐ์ ์์๋ฅผ ๋ง๋ค๊ฑฐ๋ ์ง์๋ฅผ ์๋ก ์ฌ๋ฆฌ๋ ์๋๋ฆฌ์ค๋ฅผ ์์ํ ์ ์์ต๋๋ค. ์ด์ํ ๊ฒ๋ค์ ๋ด๋ ค๊ฐ๋๋ค.
์ ์ธ์ ๋ฒ์ ์ ๋ง๋ค๋ ค๊ณ ํ์ผ๋ didUpdateWidget/Hook
์๋ช
์ฃผ๊ธฐ ๋ฐฉ์์ด ์ดํด๊ฐ ์ ๋ ๊ฒ ๊ฐ์์ ์์ prop์ด ๋ถ๋ชจ์์ ๋ณ๊ฒฝ๋์์ ๋ ์ ๋๋ฉ์ด์
์ ๊ตฌ๋ํ๋ ๋ฐฉ๋ฒ์ ๋ชฐ๋์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทํ์ ์ฝ๋๋ก ํด๊ฒฐ๋์์ต๋๋ค.
์ค๋ ๋ด ์ฝ๋ ๊ธฐ๋ฐ์์ ์ค์ ์์ ๋ฅผ ๋ฐ๊ฒฌํ์ผ๋ฏ๋ก ๊ณต์ ํ๋ ๊ฒ์ด ์ข๊ฒ ๋ค๊ณ ์๊ฐํ์ต๋๋ค.
๋ฐ๋ผ์ ์ด ์๋๋ฆฌ์ค์์ ์ ๋ Firestore๋ก ์์
ํ๊ณ ์์ผ๋ฉฐ ๊ฐ StreamBuilder๋ก ์ํํ ๋ช ๊ฐ์ง ์์ฉ๊ตฌ๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฏ๋ก ๋๋ง์ ์ฌ์ฉ์ ์ ์ ๋น๋๋ฅผ ๋ง๋ค์์ต๋๋ค. ๋ํ ValueListenable๋ก ์์
ํด์ผ ํฉ๋๋ค.
return ClipRRect(
borderRadius: BorderRadius.circular(CornerStyles.dialog),
child: Scaffold(
backgroundColor: state.theme.scaffoldBackgroundColor,
body: FamilyStreamBuilder<DocumentSnapshot>(
stream: state.listRef.snapshots(),
builder: (context, AsyncSnapshot<DocumentSnapshot> documentSnapshot) {
//When a list is updated, we need to update the listOrder
state.updateListOrderFromSnapshot(documentSnapshot);
return FamilyStreamBuilder<QuerySnapshot>(
stream: state.itemsCollection.snapshots(),
builder: (_, AsyncSnapshot<QuerySnapshot> itemsSnapshot) {
//Sort the list items by the idField on the list-doc
List<DocumentSnapshot> items = itemsSnapshot.data.documents;
state.handleDocsSync(items);
return ValueListenableBuilder(
valueListenable: state.listOrderNotifier,
builder: (_, List<String> listOrder, __) {
List<DocumentSnapshot> ordered = state.sortItems(items, listOrder);
//Set the firstCompleted item if we have one
state.firstCompletedItem = ordered
?.firstWhere((element) => element.data[FireParams.kIsComplete] == true, orElse: () => null)
?.documentID;
return _buildItemList(items, ordered);
},
);
});
},
),
),
);
๋ค์๊ณผ ๊ฐ์ด ์ธ ์ ์๋ค๋ฉด ํจ์ฌ ๋ ์ฝ๊ฒ ์ถ๋ก ํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
DocumentSnapshot list = useFamilyStream(state.listRef.snapshots());
List<DocumentSnapshot> items = useFamilyStream(state.itemsCollection.snapshots()).data.documents;
List<String> listOrder = useValueListenable(state.listOrderNotifier);
//When a list is updated, we need to update the listOrder
state.updateListOrderFromSnapshot(list);
//Sort the list items by the idField on the list-doc
state.handleDocsSync(items);
List<DocumentSnapshot> ordered = state.sortItems(items, listOrder);
//Set the firstCompleted item if we have one
state.firstCompletedItem = ordered
?.firstWhere((element) => element.data[FireParams.kIsComplete] == true, orElse: () => null)
?.documentID;
return ClipRRect(
borderRadius: BorderRadius.circular(CornerStyles.dialog),
child: Scaffold(
backgroundColor: state.theme.scaffoldBackgroundColor,
body: _buildItemList(items, ordered)
));
์ด๋ ๊ฒ ํ๋ฉด ์ธ๋ถํ๋ ์ฌ๊ตฌ์ฑ๊ณผ ๊ด๋ จ๋ ์ต์ ํ๊ฐ ์์ค๋์ง๋ง ๋ชจ๋ ์๊ฐ์ ์์๊ฐ ๋งจ ์๋ ๋ฆฌํ ๋ ธ๋์ ์๊ณ ๋ชจ๋ ๋ํผ๊ฐ ์์ ์ํ์ด๋ฏ๋ก ๋ค๋ฅธ IRL์ ๋ง๋ค์ง ์์ต๋๋ค.
๋ง์ ์ค์ ์๋๋ฆฌ์ค์ ๋ง์ฐฌ๊ฐ์ง๋ก "X๋ฅผ ์ฌ์ฉํ์ง ๋ง์ญ์์ค"๋ผ๋ ์กฐ์ธ์ ํ์ค์ ์ด์ง ์์ต๋๋ค. Firebase์๋ Streams๋ผ๋ ์ฐ๊ฒฐ ๋ฐฉ๋ฒ์ด ํ๋๋ง ์๊ณ ์ด ์์ผ๊ณผ ๊ฐ์ ๋์์ ์ํ ๋๋ง๋ค ์ ํ์ ์ฌ์ง๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์คํธ๋ฆผ์ ์ฌ์ฉํฉ๋๋ค. ์ธ๋ผ๋น.
์ด๋ ๊ฒ ํ๋ฉด ์ธ๋ถํ๋ ์ฌ๊ตฌ์ฑ๊ณผ ๊ด๋ จ๋ ์ต์ ํ๊ฐ ์์ค๋์ง๋ง ๋ชจ๋ ์๊ฐ์ ์์๊ฐ ๋งจ ์๋ ๋ฆฌํ ๋ ธ๋์ ์๊ณ ๋ชจ๋ ๋ํผ๊ฐ ์์ ์ํ์ด๋ฏ๋ก ๋ค๋ฅธ IRL์ ๋ง๋ค์ง ์์ต๋๋ค.
์ฌ์ ํ ์ฐจ์ด๊ฐ ์์ต๋๋ค. ๋ ธ๋๊ฐ ์๊ฐ์ ์ธ์ง ์ฌ๋ถ๋ ์ฌ๊ตฌ์ถ ๋น์ฉ์ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค.
๋๋ ์๋ง๋ ๊ทธ ์๋ฅผ ๋ค๋ฅธ ์์ ฏ์ ํฌํจ์ํฌ ๊ฒ์
๋๋ค. _buildItemList
๋ FamilyStreamBuilder
๋ฟ๋ฆฌ๋ฅผ ๋ ๋ถ๋ถ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์์ ฏ์ด์ด์ผ ํฉ๋๋ค.
์ฐ๋ฆฌ๋ ์ธ๋ถํ๋ ์ฌ๊ตฌ์ถ์ ์์ง ์์ต๋๋ค.
์ค์ ๋ก ํํฌ๋ useMemoized
์ฌ์ฉํ์ฌ ์์ ฏ ์ธ์คํด์ค๋ฅผ ์ฝ๊ฒ ์บ์ํ ์ ์๋๋ก ํ์ฌ ์ด๋ฌํ ์ธก๋ฉด์ ๊ฐ์ ํฉ๋๋ค.
Tim์ repo์๋ ๊ทธ๋ ๊ฒ ํ๋ ๋ช ๊ฐ์ง ์๊ฐ ์์ต๋๋ค.
๋๋ ์๋ง๋ ๊ทธ ์๋ฅผ ๋ค๋ฅธ ์์ ฏ์ ํฌํจ์ํฌ ๊ฒ์ ๋๋ค.
_buildItemList
๋FamilyStreamBuilder
๋ฟ๋ฆฌ๋ฅผ ๋ ๋ถ๋ถ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์์ ฏ์ด์ด์ผ ํฉ๋๋ค.
๋ฌธ์ ๋ ์ด ๋ณด๊ธฐ์์ ์ฑ๋ฅ์ ๋ํ ์ฐ๋ ค๊ฐ ์ ํ ์๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ์ด ์์ ์ ์ํํ๊ณ ์ถ์ง ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ฐ๋ผ์ 100% ์ ๋ ์ด์ ๊ฐ์ ๋ฏธ์ธ ์ต์ ํ๋ณด๋ค ์ฝ๋ ์ง์ญ์ฑ๊ณผ ์ผ๊ด์ฑ์ ์ ํธํฉ๋๋ค. ์ด ๋ณด๊ธฐ๋ ์ฌ์ฉ์๊ฐ ์์ ์ ์์ํ๊ฑฐ๋(~avg 10์ด๋น ํ ๋ฒ) ๋ฐฑ์๋ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๊ณ ์ด๋ฆฐ ๋ชฉ๋ก์ ์์ํ ๋(๊ฑฐ์ ๋ฐ์ํ์ง ์์)์๋ง ๋ค์ ์์ฑ๋ฉ๋๋ค. ๋ํ ์ฃผ๋ก ๋ชฉ๋ก์ธ ๋จ์ํ ๋ณด๊ธฐ์ผ ๋ฟ์ด๋ฉฐ ๋ชฉ๋ก์๋ ๋ด๋ถ์ ์ผ๋ก ์์ฒด ์ต์ ํ๊ฐ ๋ง์ด ์์ต๋๋ค. ๋๋ build()๊ฐ ๊ธฐ์ ์ ์ผ๋ก ์ธ์ ๋ ์ง ์คํํ ์ ์๋ค๋ ๊ฒ์ ์๊ณ ์์ง๋ง ์ค์ ๋ก ์์์ ์ฌ๊ตฌ์ถ์ ๋งค์ฐ ๋๋ญ ๋๋ค.
์ด ๋ชจ๋ ๋ ผ๋ฆฌ๊ฐ ํ๋์ ์์ ฏ์ ๊ทธ๋ฃนํ๋์ด ์์ผ๋ฉด ์ด ๋ณด๊ธฐ์์ ์์ ํ๊ณ ๋๋ฒ๊ทธํ๋ ๊ฒ์ด ํจ์ฌ ๋ ์ฝ์ต๋๋ค. ์ฃผ๋ก ๋์ค์ ๋ค์ ๋์์ฌ ๋ ๋ด ์ถ์ ๋ ์ฝ๊ฒ ๋ง๋ค๊ธฐ ์ํ ๋ ธ๋ ฅ์ ๋๋ค. :)
์ฃผ์ํด์ผ ํ ๋ ๋ค๋ฅธ ์ฌํญ์ ๊ตฌ๋ฉ์ ์๋ 3๊ฐ์ ํด๋ก์ ์ 16๊ฐ์ ๊ณต๊ฐ ๋ด๋ถ์ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์๊ธฐ ๋๋ฌธ์ ์ค์ฒฉ์ด ๊ธฐ๋ณธ์ ์ผ๋ก ๋น๋ ๋ฐฉ๋ฒ์์ "๊ฐ์ "๋์๋ค๋ ๊ฒ์ ๋๋ค.
์, ๊ทธ๋ฐ ๋ค์ ๋ณ๋์ ์์ ฏ์ผ๋ก ์ด๋ํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ด๋ผ๊ณ ๋งํ ์ ์์ต๋๋ค. ํ์ง๋ง ๋น๋ ๋ฐฉ๋ฒ์ ๋จธ๋ฌด๋ฅด์ง ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? ์์ฉ๊ตฌ๋ฅผ ์ค์ ๋ก _ํ์๋ก ํ๋ ์์ค์ผ๋ก ์ค์ผ ์ ์๋ค๋ฉด 2๊ฐ์ ํ์ผ๋ก ํญ๋ชฉ์ ๋ถํ ํ๋ ๊ฐ๋ ์ฑ ๋ฐ ์ ์ง ๊ด๋ฆฌ ๋ฒ๊ฑฐ๋ก์์ด ํ์ํ์ง ์์ต๋๋ค. (์ฑ๋ฅ์ด ๋ฌธ์ ๊ฐ ์๋๋ผ๊ณ ๊ฐ์ ํ๊ณ ์ข ์ข ๊ทธ๋ ์ง ์์ต๋๋ค)
์ด ์๋๋ฆฌ์ค์์ ์ด๋ฏธ Stream Builder๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉ์ ์ง์ ์์ ฏ์ ๋ง๋ค์์ต๋๋ค. ์ด์ ์ด ๋น๋์ ๊ตฌ์ฑ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ๋ค๋ฅธ ํ๋๋ฅผ ๋ง๋ค์ด์ผ ํฉ๋๊น?? ์ฝ๊ฐ ์ค๋ฒ์ธ ๊ฒ ๊ฐ์ต๋๋ค.
์ด ๋ณด๊ธฐ์์ ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ์ ํ ์๊ธฐ ๋๋ฌธ์
์ค ์ฑ๋ฅ์ ์ํด ์์ ฏ์ผ๋ก ๋ฆฌํฉํ ๋งํ์ง ์๊ฒ ์ต๋๋ค. ๋น๋๊ฐ ์ด๋ฏธ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค. ๊ฐ๋ ์ฑ๊ณผ ์ฌ์ฌ์ฉ์ฑ์ ์ํด ๋ฆฌํฉํ ๋งํ๊ฒ ์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ด "์ฌ๋ฐ๋ฅธ" ๋ฐฉ๋ฒ์ด๋ผ๊ณ ๋งํ๋ ๊ฒ์ด ์๋๋ผ ์ฝ๋๋ฅผ ๊ตฌ์กฐํํ๋ ๋ฐฉ๋ฒ์ ๋งํ๋ ๊ฒ์ ๋๋ค. ์ด์จ๋ ๊ทธ๊ฒ์ ์ฌ๊ธฐ๋ ์ ๊ธฐ๋ ์๋๋ค.
๊ตฌ๋ฉ์ 3๊ฐ์ ํด๋ก์ ์ 16๊ฐ์ ๊ณต๊ฐ์ด ์๋ ๋ด๋ถ์ ํธ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
๋๋ ๋น์ ๋ณด๋ค ๋ ๋์ ๋ชจ๋ํฐ๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค ... :-/
๊ทธ๋ฐ ๋ค์ 2๊ฐ์ ํ์ผ๋ก ํญ๋ชฉ์ ๋ถํ ํ๋ ๊ฐ๋ ์ฑ ๋ฐ ์ ์ง ๊ด๋ฆฌ ๋ฒ๊ฑฐ๋ก์์ด ํ์ํ์ง ์์ต๋๋ค.
์์ ฏ์ ๊ฐ์ ํ์ผ์ธ FWIW์ ๋ฃ๊ฒ ์ต๋๋ค.
์ด์จ๋ , ์ด๊ฒ์ ์ข์ ์์ด๋ฉฐ ๋ ๋ง์ ์์ ฏ์ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ๊ตฌ๋ฌธ์ด ๋ค๋ฅธ ํ๋์ ์์ ฏ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ซ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋๋ ๋น์ ๋ณด๋ค ๋ ๋์ ๋ชจ๋ํฐ๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค ... :-/
๋๋ ultrawide :D๋ฅผ ๊ฐ์ง๊ณ ์์ง๋ง dartfmt๋ ๋ถ๋ช
ํ ์ฐ๋ฆฌ ๋ชจ๋๋ฅผ 80์ผ๋ก ์ ํํฉ๋๋ค. ๋ฐ๋ผ์ 16์ ์๋ ๊ฒ์ ์ค์ํฉ๋๋ค. ์ฃผ์ ๋ฌธ์ ๋ ๋ด ์ง์ ์ ๋์ด },);});},),),);
๋ญ๊ฐ ์๋ง์ด ๋์์ ๋ ์ ๋ง ์ฌ๋ฏธ๊ฐ ์๋ค๋ ๊ฒ์
๋๋ค. ์ด ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ํธ์งํ ๋๋ง๋ค ๋งค์ฐ ์กฐ์ฌํด์ผ ํ๋ฉฐ swap with parent
์ ๊ฐ์ ์ผ๋ฐ์ ์ธ IDE ๋์ฐ๋ฏธ๊ฐ ์๋์ ๋ฉ์ถฅ๋๋ค.
์์ ฏ์ ๊ฐ์ ํ์ผ์ธ FWIW์ ๋ฃ๊ฒ ์ต๋๋ค.
100%์ง๋ง ์ฌ์ ํ ๋จ์ผ ํ์ผ์์ ์์ง์ผ๋ก ์ ํํ๋ ๊ฒ์ด ์ ์ง ๊ด๋ฆฌํ๊ธฐ๊ฐ ๋ ์ด๋ ต๋ค๋ ๊ฒ์ ์์์ต๋๋ค. ๋ฌผ๋ก ๋ถ๊ฐํผํ์ง๋ง ๊ฐ๋ฅํ๋ฉด ์ค์ด๊ณ 'ํจ๊ป ํ๋ ๊ฒ'์ ํ๋ ค๊ณ ํฉ๋๋ค.
๊ฒฐ์ ์ ์ผ๋ก, ๊ธฐ๋ณธ ๋ชฉ๋ก์ ์์ฒด ์์ ฏ์ผ๋ก ๋ฆฌํฉํ ๋งํ๋๋ผ๋(๋ด ์๊ฐ์๋ ์ค์ฒฉ๋ ๋น๋ ๋ฉ์๋๋ณด๋ค ์ฝ๊ธฐ ์ฝ์ต๋๋ค) ์์ ์์ ฏ์ ์ค์ฒฉ๋์ง ์์ ์ํ์์ ํจ์ฌ ๋ ์ฝ๊ธฐ ์ฝ์ต๋๋ค. ๋ด๊ฐ ๋ค์ด์์ ๋ชจ๋ ๋ ผ๋ฆฌ๋ฅผ ํ ๋์ ์ดํดํ๊ณ _MyListView() ์์ ฏ์ ๋ช ํํ๊ฒ ๋ณด๊ณ ๋ฐ๋ก ์์ํ ์ ์์ผ๋ฉฐ ์ฃผ๋ณ ์ปจํ ์คํธ๋ฅผ ์ดํดํ๋ค๊ณ ํ์ ํฉ๋๋ค. ๋ํ ์๋์ ์ผ๋ก ์ฝ๊ฒ ์ถ๊ฐ ์ข ์์ฑ์ ์ถ๊ฐ/์ ๊ฑฐํ ์ ์์ผ๋ฏ๋ก ํ์ฅ์ด ๋งค์ฐ ์ ๋ฉ๋๋ค.
dartfmt๋ ๋ถ๋ช ํ ์ฐ๋ฆฌ ๋ชจ๋๋ฅผ 80์ผ๋ก ์ ํํฉ๋๋ค.
๋ด ๋ง์, ๊ทธ๊ฒ์ด ๋ด๊ฐ ์ผ๋ฐ์ ์ผ๋ก dartfmt๋ฅผ ์ฌ์ฉํ์ง ์๋ ์ด์ ์ค ํ๋์ด๋ฉฐ ์ฌ์ฉํ ๋ 120 ๋๋ 180์๋ก ์ค์ ํฉ๋๋ค...
์ฌ๊ธฐ์์์ ๊ฒฝํ์ ์์ ํ ์ ํจํฉ๋๋ค.
์ฌ์ค ์ ๋ ํ๋ฃจ ์ข ์ผ 120์ ๋๋ค. :) ํ์ง๋ง pub.dev๋ 80์ผ๋ก ํฌ๋งท๋์ง ์์ ํ๋ฌ๊ทธ์ธ์ ์ ๊ทน์ ์ผ๋ก ๋ค์ด๋ ์ดํธํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ๋ ์ด ๊ฐ์ ๋ณ๊ฒฝํ ๋ ์ (์ฐ๋ฆฌ)๊ฐ ์์๋ผ๋ ์ธ์์ ๋ฐ์ต๋๋ค.
๊ทธ๊ฑด ๋ง๋ ์ ๋ฉ๋๋ค. ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ๊ณ ์ณ์ผ ํฉ๋๋ค.
pub.dev๋ dartfmt๋ฅผ ์กด์คํ์ง ์๋ ํ๋ฌ๊ทธ์ธ์ ํ๊ฐํ์ง ์์ต๋๋ค. ์ ์ ํ์ด์ง์๋ ๋๊ธ๋ง ํ์๋์ง๋ง ์ ์์๋ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค.
๊ทธ๋ฌ๋ ํ๋ฆผ์์ด dartfmt์๋ ๋ผ์ธ ๊ธธ์ด๋ณด๋ค ๋ ๋ง์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
์ค ๊ธธ์ด๊ฐ ๋๋ฌด ํฌ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ฌ๋ฌ ์ค์์ ๋ ์ฝ๊ธฐ ์ฌ์ด ๊ฒ์ด ํ ์ค๋ก ํ์๋ฉ๋๋ค.
object
..method()
..method2();
๋ค์์ด ๋ ์ ์์ต๋๋ค.
object..method()..method2();
๋๋ ์ด๊ฒ์๋ณด๊ณ ์๋ค?
๋ฌธ์ ์ ํจํค์ง: https://pub.dev/packages/sized_context/score
ํฅ๋ฏธ๋กญ์ต๋๋ค. ๊ณต๊ธ์๊ฐ ํ๋์ dartfmt๋ฅผ ์ฌ์ฉํ์ง ์์๊ธฐ ๋๋ฌธ์ ์ด์ ์๋ ํ์คํ ๊ทธ๋ ์ง ์์์ต๋๋ค.
์ ์ ํฉ๋๋ค.
๋ค, ํ์คํ ์๋ก์ด ๋์์ ๋๋ค. ์ ๊ฐ ์๋ ๋ด์ ์ฒ์ ๊ฒ์ํ์ ๋ ๋ชจ๋ ์์์ ์ฒดํฌ ํ์๋ฅผ ํ๋์ง ํ์ธํ๊ณ dartfmt๊ฐ ํ์ํ์ง ์์์ต๋๋ค.
์ด๋ฌํ ๋ชจ๋ ๋
ผ์๊ฐ ๋๋๋ฉด Flutter์์ ํํฌ์ ๊ฐ์ ์๋ฃจ์
์ ๋ํ ๊ธฐ๋ณธ ์ง์์ ๋ณผ ์ ์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. useHook
๋๋ use Hook
๋๋ flutter ํ์ด ์์ ์ ๊ธฐ๋ฅ์ด React์ ๊ฐ์ง ์๋ค๊ณ ๋๋ ์ ์๋ ๋ชจ๋ ๊ฒ ๐๐คทโโ๏ธ
final controller = useAnimationController(duration: Duration(milliseconds: 800));
์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ํํฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
kotlin/swift์์ ๋ณต์ฌํ Darts์ ์ ํ๋ก๊ทธ๋จ ๊ธฐ๋ฅ _Extension_์ ์ฌ์ฉํ์ฌ ๊ทธ ๊ตฌ๋ฌธ์ ์๋ฆ๋ต๊ฒ ๋ง๋๋ ๊ฒ์ด ๋ ์ข์ง ์์ต๋๊น?
final controller = AnimationController.use(duration: Duration(milliseconds: 800));
์ ๊ฐ์ ๊ฒ
์ด ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด flutter/dart ํ์ด ํ์ฌ ์ฌ์ฉ ๊ฐ๋ฅํ ๊ตฌ๋ฌธ useHook
๋์ use Hook
๋ฅผ ์ถ๊ฐํ๊ธฐ๋ก ๊ฒฐ์ ํ์ ๋ ํด๋น ํ์ฅ ํจ์์ Annotation
๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ๋๋ก ์ฝํ์ต๋๋ค.
final controller = use AnimationController(duration: Duration(milliseconds: 800));
๋ํ const
๋ฐ new
์ ๊ฐ์ด const
use
ํค์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๋ ์ดํด ๊ฐ๋ฅ/์๋ฏธ ์์ต๋๋ค.
new Something
const Something
use Something
๊ทธ ๊ถ์ฅ ์ฌํญ์ ๋ํ ๋ณด๋์ค๋ก, ๋ง์นจ๋ด ์์ฑ์/์์ฑ๊ธฐ ํจ์๋ ์ ์๋ Annotation
์์ ์ฌ์ฉ/์ด์ ์ ์ป์ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ผ๋ถ ์ฌ์ฉ์ ์ ์๊ฐ ํฌํจ๋ dart ์ปดํ์ผ๋ฌ๋ use
ํค์๋๋ฅผ ์ง์ํ๋๋ก ๋ณํํฉ๋๋ค.
๋๋ฌด ์๋ฆ๋ต๊ณ ํ๋ฌํฐ/๋คํธ ์ ์ฉ ๊ธฐ๋ฅ ๐
https://github.com/TimWhiting/local_widget_state_approaches/tree/master/lib/stateful ์ ์๊ฐ ์ด์ ์ฌ๋๋ค์ด ํด๊ฒฐํ๊ณ ์ ํ๋ ๋ฌธ์ ๋ฅผ ๋ํํ๋ค๊ณ ๊ฐ์ ํ๋ ๊ฒ์ด ๋ง์ต๋๊น?
๋๋ ๋ค๋ฅธ ์ฌ๋๋ค์ด ์ด๋ป๊ฒ ๋๋ผ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ง๋ง ๋ฌธ์ ๊ฐ ๊ฑฐ๊ธฐ์ ์ด๋ ์ ๋ ํํ๋์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํด๋น ์ ์ฅ์์์ ์ค๊ฐ ์๋ฃจ์ ์ ์๋ํ์ต๋๋ค. ํํฌ์ฒ๋ผ ๊ตฌ์ฑ ๊ฐ๋ฅํ์ง๋ง ํจ์ ํธ์ถ์ ์์์ ์์กดํ์ง ์๊ฑฐ๋ ๋ฃจํ๋ฅผ ํ์ฉํ์ง ์์ต๋๋ค. StatefulWidget์ ์ง์ ์ฌ์ฉํฉ๋๋ค. ์ฌ๊ธฐ์๋ ๋ฏน์ค์ธ๊ณผ ํค๋ก ๊ณ ์ ํ๊ฒ ์๋ณ๋๋ ์ํ ์ ์ฅ ์์ฑ์ด ํฌํจ๋ฉ๋๋ค. ๋๋ ์ด๊ฒ์ ๊ถ๊ทน์ ์ธ ํด๊ฒฐ์ฑ ์ผ๋ก ํ๋ณดํ๋ ค๋ ๊ฒ์ด ์๋๋ผ ๋ ์ ๊ทผ ๋ฐฉ์ ์ฌ์ด์ ์ค๊ฐ ์ง์ ์ผ๋ก ํ๋ณดํ๋ ค๊ณ ํฉ๋๋ค.
์ ๋ ์ด๊ฒ์ lifecycleMixin ์ ๊ทผ ๋ฐฉ์์ด๋ผ๊ณ ๋ถ๋ ์ต๋๋ค. ์ฌ๊ธฐ์์ ๋ ผ์ํ LateProperty ์ ๊ทผ ๋ฐฉ์๊ณผ ๋งค์ฐ ์ ์ฌํ์ง๋ง ์ฃผ์ ์ฐจ์ด์ ์ ๊ตฌํ๋ ์๋ช ์ฃผ๊ธฐ๊ฐ ๋ ๋ง๊ณ ์ฝ๊ฒ ๊ตฌ์ฑํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. (์๋ช ์ฃผ๊ธฐ ๋ถ๋ถ์์ ๋๋ initState ์ด์ธ์ ์์ ฏ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ฌ์ฉํ์ง ์์๊ณ ๋ง์ด ํ๊ธฐํ๊ธฐ ๋๋ฌธ์ ๊ฑฐ๊ธฐ์ ์์ ํ ์๋ง์ด ๋์์ ์ ์์ต๋๋ค).
๋๋ ๋ค์๊ณผ ๊ฐ์ ์ด์ ๋ก ์ด ์ ๊ทผ ๋ฐฉ์์ ์ข์ํฉ๋๋ค.
๋ค์๊ณผ ๊ฐ์ ์ด์ ๋ก ํํฌ์ ๋น๊ตํ์ฌ ์ด ์ ๊ทผ ๋ฐฉ์์ด ๋ง์์ ๋ค์ง ์์ต๋๋ค.
๊ฐ๋จํ ์นด์ดํฐ ์.
์ ๋๋ฉ์ด์
์นด์ดํฐ ์
๋ผ๋
์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ํ ๊ตฌ์ฑ ๋
ผ๋ฆฌ์ ๊ณตํต ๋นํธ
์๊ฐ์ด ์ผ๋ง๋ ๋จ์๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๋ํ์ ๊ณต๋ถ๋ ํญ์ ์ ๋ฅผ ๋ฐ์๊ฒ ๋ง๋ค๊ณ ์์ง๋ง ํผ๋๋ฐฑ์ ๋ฐ๊ณ ์ถ์ต๋๋ค. @rrousselGit ์ด๊ฒ์ด ํํฌ์ ์ผ๋ง๋ ๊ฐ๊น์ต๋๊น? ์ฌ์ฌ์ฉ์ฑ ๋๋ ๊ตฌ์ฑ ๊ฐ๋ฅ์ฑ์ ๋ช ๋ฐฑํ ๊ตฌ๋ฉ์ด ์์ต๋๊น?
๋ด ์๋ฃจ์ ์ ํ๋ณดํ๋ ค๋ ๊ฒ์ด ์๋๋ผ ์ค๊ฐ ์ง์ ์์ ๊ธ์ ์ ์ธ ํ ๋ก ์ ์ฅ๋ คํ๋ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋๋ฝ๋ ์ฌํญ์ด๋ ์ด ์๋ฃจ์ ์ด ์ ๊ณตํ๋ ์ฌํญ์ ๋ํด ๋์ํ ์ ์๋ค๋ฉด ์์ผ๋ก ์ข์ ์ง์ ์ ์ด๋ฃฐ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
@TimWhiting ์ด ์ ๊ทผ ๋ฐฉ์์ ์ฃผ์ ๋ฌธ์ ๋ ๊ฒฌ๊ณ ์ฑ ๋ถ์กฑ์ ๋๋ค. ์ฌ๊ธฐ์ ํฐ ๋์ธ์ ๊ฐ๊ฒฐํ ํํ๋ก ๊ฑด์ถ์ ์์ ์ ๋ขฐ์ฑ์ ๋ํ ํ์์ฑ์ ๋๋ค. ๋งค์ง id์ ์๋ช ์ฃผ๊ธฐ์์ ์ถฉ๋ํ๋ ๊ธฐ๋ฅ์ ๋ชจ๋ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ๊ธฐ ์ํ ์๋ก์ด ๋ฒกํฐ๋ฅผ ์์ฑํ๋ฉฐ, ์ฝ๊ธฐ์๋ ๊ฝค ๋ถ์พํ์ง๋ง ์ ์ด๋ ์ฐ๋ฆฌ๋ ๊ทธ๋ค์ด 100๊ฐ๋ผ๋ ๊ฒ์ ์๊ณ ์๊ธฐ ๋๋ฌธ์ ๋น๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ ๊ณ์ ๊ถ์ฅํ ๊ฒ์ ๋๋ค. % ๋ฒ๊ทธ๊ฐ ์์ต๋๋ค.
์์ ์ ๊ด๋ จํ์ฌ ์ฌ์ ํ ์๋ฒฝํ ์์ ๋ ์์ ฏ์ ์ฐ๊ฒฐ๋ ๊ธฐ๊ฐ ๊ฐ๊ณผ ํจ๊ป AnimationController๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ฐ๋จํ๊ณ ์น์ํ๊ฒ ์ ์งํฉ๋๋ค. ์ด๋ณด๋ค ๋ ๋ํดํ ํ์๋ ์์ต๋๋ค. ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์์ฉ๊ตฌ์ ๋ํ ์๋ฒฝํ ์์ ์ฌ์ฉ ์ฌ๋ก์ด๋ฉฐ, ์๋ช ์ฃผ๊ธฐ ํํฌ๊ฐ ํ์ํ๋ฉฐ, ๋ชจ๋ ์๋ฃจ์ ์ ์ฌ๋ฌ ์ ๋๋ฉ์ด์ ์ ๊ฐ๊ฒฐํ๊ฒ ์ฌ์ฉํ ์ ์๋ ๋ฅ๋ ฅ์ผ๋ก ์ฝ๊ฒ ํ๋จํ ์ ์์ต๋๋ค.
๋ค๋ฅธ ๋ชจ๋ ๊ฒ์ ์ด์ ๋์ผํ ์ฌ์ฉ '์ํ ์ ์ฅ ์ปจํธ๋กค๋ฌ' ์ฌ์ฉ ์ฌ๋ก์ ๋ณํ์ผ ๋ฟ์ ๋๋ค. initState์์ X๋ฅผ ์ํํ๊ณ dispose ์ํ์์ Y๋ฅผ ์ํํ๊ณ ์ข ์์ฑ์ด ๋ณ๊ฒฝ๋๋ฉด Z๋ฅผ ์ ๋ฐ์ดํธํ๊ณ ์ถ์ต๋๋ค. X, Y, Z๊ฐ ๋ฌด์์ธ์ง๋ ์ค์ํ์ง ์์ต๋๋ค.
@rrousselGit ์ด ์ฌ๊ธฐ์ ์ฝ๊ฐ์ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํ ์ ์๋์ง ๋๋ ํ์ฌ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ํํฌ์ ๋ํ ๋ฐ์ดํฐ๊ฐ ์๋์ง ๊ถ๊ธํฉ๋๋ค. 80%๋ ์คํธ๋ฆผ๊ณผ ์ ๋๋ฉ์ด์ ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง ์ค์ ๋ก ์ฌ๋๋ค์ด ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๊ฒ์ด ๋ฌด์์ธ์ง ์๋ ๊ฒ์ด ์ข์ ๊ฒ์ ๋๋ค.
ํธ๋ฆฌ์ ์ผ๋ถ๋ฅผ ์ฌ๊ตฌ์ถํ๋ ๊ฒ๊ณผ ๊ด๋ จํ์ฌ ๋น๋๋ ์ด์จ๋ ์์ฐ์ค๋ฝ๊ฒ ์ด ์์ ์ ์ ํฉํฉ๋๋ค. ์ํ ์ ์ฅ ์ปจํธ๋กค๋ฌ๋ ์ํ๋ ๊ฒฝ์ฐ ์ํ ๋น์ ์ฅ ๋ ๋๋ฌ์ ์ฝ๊ฒ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค(๋ชจ๋ Transition ํด๋์ค ์๋ ํ์ธ์).
์ฐ๋ฆฌ๊ฐ ํ ์ ์๋ ๊ฒ์ฒ๋ผ:
var anim = get AnimationController();
return Column(
_someExpensiveBuildMethod(),
FadeTransition(opacity: anim, child: ...)
)
์ฐ๋ฆฌ๋ ํญ์ ํ ์ ์์ต๋๋ค:
var foo = get ComplicatedThingController();
return Column(
_someExpensiveBuildMethod(),
ComplicatedThing(controller: foo, child: ...)
)
@esDotDev ํค์ ๋น๋ ๊ตฌ๋ฌธ์ด lifecycleMixin ์ ๊ทผ ๋ฐฉ์์ ์ฃผ์ ๋จ์ ์ด๋ผ๋ ๋ฐ ๋์ํฉ๋๋ค. ๊ด๋ จ ์ ํ ์ฌํญ์ด ์๋ ํํฌ ์คํ์ผ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๊ฑฐ๋ ๋ณ์ ์ ์ธ์ ์ํ ๋นํธ์ ์๋ช ์ฃผ๊ธฐ์ ์ฐ๊ฒฐํ ์ ์๋ ์ธ์ด ๋ณ๊ฒฝ์ ์ ์ธํ๊ณ ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ด๊ฒ์ด ๋ด๊ฐ ๊ณ์ ํํฌ๋ฅผ ์ฌ์ฉํ๊ณ ๋ ๋์ ์๋ฃจ์ ์ด ๋์ค์ง ์๋ ํ ๋ค๋ฅธ ์ฌ๋๋ค์ด ์ํ ์ ์ฅ ์์ ฏ์ ์ฌ์ฉํ๋๋ก ํ๋ ์ด์ ์ ๋๋ค. ๊ทธ๋ฌ๋ ์์ฒด ์ ํ์ด ์์ง๋ง ํํฌ์ ์ ํ์ ์ข์ํ์ง ์๋ ์ฌ๋๋ค์๊ฒ๋ ํฅ๋ฏธ๋ก์ด ๋์์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
https://github.com/TimWhiting/local_widget_state_approaches/tree/master/lib/stateful ์ ์๊ฐ ์ด์ ์ฌ๋๋ค์ด ํด๊ฒฐํ๊ณ ์ ํ๋ ๋ฌธ์ ๋ฅผ ๋ํํ๋ค๊ณ ๊ฐ์ ํ๋ ๊ฒ์ด ๋ง์ต๋๊น?
์์งํ ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๋๋ _์_๋ผ๊ณ ๋งํ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ์ด๋ฌํ ์๋ฅผ ์ด๋ป๊ฒ ํด์ํ ๊ฒ์ธ๊ฐ์ ๋ฌ๋ ค ์์ต๋๋ค.
์ด ์ค๋ ๋์์ ์ฐ๋ฆฌ๋ ์๋ก๋ฅผ ์ดํดํ์ง ๋ชปํ ์ญ์ฌ๊ฐ ์์ด์ ๋ค์๋ ์ด๋ฐ ์ผ์ด ์ผ์ด๋์ง ์์ ๊ฒ์ด๋ผ๊ณ ์ฅ๋ดํ ์ ์์ต๋๋ค.
์ด๊ฒ์ด ๋ถ๋ถ์ ์ผ๋ก ๋ด๊ฐ ์ฝ๋ ์์ ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ซ์ดํ๊ณ ๋์ ๊ท์น ์งํฉ์ ์ถ์ถํ๋๋ก ์ ์ํ ์ด์ ์
๋๋ค.
์๋ ์ฃผ๊ด์ ์ด๊ณ ์ฌ๋ฌ ์๋ฃจ์
์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ ๊ทธ ์ค ์ผ๋ถ๋ ๋ ๊ด๋ฒ์ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ๋ชปํ ์ ์์ต๋๋ค.
@rrousselGit ์ด ์ฌ๊ธฐ์ ์ฝ๊ฐ์ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํ ์ ์๋์ง ๋๋ ํ์ฌ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ํํฌ์ ๋ํ ๋ฐ์ดํฐ๊ฐ ์๋์ง ๊ถ๊ธํฉ๋๋ค. 80%๋ ์คํธ๋ฆผ๊ณผ ์ ๋๋ฉ์ด์ ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง ์ค์ ๋ก ์ฌ๋๋ค์ด ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๊ฒ์ด ๋ฌด์์ธ์ง ์๋ ๊ฒ์ด ์ข์ ๊ฒ์ ๋๋ค.
๋งค์ฐ ๋์ง์ ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
useStream
๋ฐ ์ ๋๋ฉ์ด์
์ด ๊ฐ์ฅ ์ ๊ฒ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
context.watch
, useBloc
, useProvider
, ...TweenAnimationBuilder
๋ค๋ฅธ ์์์ ์ผ๋ก ์ ๋๋ฉ์ด์
๋ ์์ ฏ์ด ํ์์ ํฐ ๋ถ๋ถ์ ์ฐจ์งํฉ๋๋ค.useImplicitlyAnimatedInt
ํํฌ๋ฅผ ์ถ๊ฐํ๋ฉด ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค.@esDotDev lifecycleMixin ์ ๊ทผ ๋ฐฉ์์์ ํค/ID์ ํ์์ฑ์ ์ ๊ฑฐํ์ต๋๋ค. ๋น๋ ๊ตฌ๋ฌธ์์๋ ์ฌ์ ํ ์ฝ๊ฐ ์ด์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ฒฐ๊ตญ์๋ ๊ทธ๊ฒ์ด ๋์์ด ๋ ์๋ ์์ต๋๋ค. ๋ด๊ฐ ๊ฒช๊ณ ์๋ ํ ๊ฐ์ง ๋ฌธ์ ๋ ์ ํ ์์คํ ์ ๋๋ค. ์๋ํ์ง ์๋ ํน์ ๋ฐฉ์์ผ๋ก ์ผ์ ๋์ง๋ ค๊ณ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์๋ง๋ ์ฃผ์ ๊น์ ์บ์คํ ์ด๋ ์ ํ ์์คํ ์๋ฌ์ด ํ์ํ ๊ฒ์ ๋๋ค. ๋ผ์ดํ์ฌ์ดํด์ ํผํฉํ๋ ํ, ์ก์ธ์คํ๋ ค๋ ํน์ ์ํ๊ฐ ํด๋น ์์ ฏ์ ๋ผ์ดํ์ฌ์ดํด์์ ์ก์ธ์คํ ์ ์๋ ๊ฒฝ์ฐ ๋ช ๊ฐ์ง ํฉ๋ฆฌ์ ์ธ ์์ธ๋ฅผ ๋ฐ์์์ผ ๊ฐ์ ํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋๋ lifecyclebuilder ๋ด์์ ๋น๋์ ์๋ช ์ฃผ๊ธฐ์๋ง ์ก์ธ์คํด์ผ ํ๋ ๋ฆฐํธ์ ๋๋ค.
Remi ๋๋ถ์ ๋๋์ต๋๋ค. ์ฌ๋๋ค์ด Animation์ ๋งค์ฐ ์์ฃผ ์ฌ์ฉํ์ฌ ์ฝ์ด์ ์๋ ๋๊ท๋ชจ ์ ํ ์์ ฏ ๋ชจ์์ ๊ตฌ๋ํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. .
์ฌ์ ํ AnimatorController๊ฐ ์์์ ๋ฐ ๋ช ์์ ์์ ฏ ์ ํ๊ตฐ๊ณผ ํจ๊ป ๋งค์ฐ ์ ์ ๊ณต๋๊ณ ์์์๋ ๋ถ๊ตฌํ๊ณ ์ฌ์ ํ '์ํ๋ฅผ ์ ์งํ๊ณ ์์ ฏ ๋งค๊ฐ๋ณ์ ๋ฐ ์๋ช ์ฃผ๊ธฐ์ ์ฐ๊ฒฐํด์ผ ํ๋ ๊ฒ'์ ํ๋ฅญํ ์๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํด๊ฒฐํด์ผ ํ ๋ฌธ์ ์ ์๋ฒฝํ ์์ ์๋ก์ ์ญํ ์ ํฉ๋๋ค(์ฌ์ค์ Flutter์์ 12๊ฐ์ ์์ ฏ์ด ์์์๋ ๋ถ๊ตฌํ๊ณ ์์ ํ ํด๊ฒฐ๋์์ต๋๋ค). ์ฐ๋ฆฌ ๋ชจ๋๋ ์ฝํ ์ธ ๊ฐ ์๋ ์ํคํ ์ฒ์ ๋ํด ๋ ผ์ํ๊ณ ์ง์คํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด var anim = AnimationController.use(context, duration: widget.duration ?? _duration);
๊ฐ ์ผ๋ฑ ์๋ฏผ์ด๋ผ๋ฉด ์ด๋ฌํ ์์์ ๋๋ ๋ช
์์ ์ ๋๋ฉ์ด์
์ด ์ค์ ๋ก ์กด์ฌํ ํ์๊ฐ ์๋ ๋ฐฉ๋ฒ์ ์๊ฐํด ๋ณด์ญ์์ค. ์์ ฏ์ ์ปจํ
์คํธ ๋ด์์ ์ํ ์ ์ฅ ์ฌ๋ฌผ(AnimationController)์ ์ฝ๊ฒ ํฉ์ฑํ๋ ํต์ฌ ๋ฌธ์ ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ๋ชจ๋ ์์ฑ๋์๊ธฐ ๋๋ฌธ์ ์ค๋ณต์ผ๋ก ๋ ๋๋ง๋ฉ๋๋ค. AnimatedBuilder + AnimatorController.use()
๋์ผํ ์์
์ ์ํํ ์ ์์ผ๋ฏ๋ก TAB ์ ๊ฑฐ์ ๋ฌด์๋ฏธํด์ง๋๋ค.
์ ๋๋ฉ์ด์ ์ฃผ์์ ์๊ฒจ๋ ์์ฒญ๋ ์์ ์์ ฏ์ ๋ณด๋ฉด ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ์ฌ๋ก์ ํ์์ฑ์ ์ ๋ณด์ฌ์ค๋๋ค. ํต์ฌ ์ค์ /ํด์ ๋ก์ง์ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ ๋งค์ฐ ๋ฒ๊ฑฐ๋กญ๊ณ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ๊ธฐ ์ฌ์ฐ๋ฏ๋ก 15๊ฐ ์ด์์ ์์ ฏ์ด ๋ชจ๋ ๋งค์ฐ ๊ตฌ์ฒด์ ์ธ ์์ ์ ์ฒ๋ฆฌํ์ง๋ง ๋๋ถ๋ถ์ ๋ช ๊ฐ์ง๋ง ์ฌ์ฉํ์ฌ ๋์ผํ ์ ๋๋ฉ์ด์ ์์ฉ๊ตฌ๋ฅผ ๋ฐ๋ณตํ๊ณ ์์ต๋๋ค. ๋ง์ ๊ฒฝ์ฐ์ ๊ณ ์ ํ ์ฝ๋ ๋ผ์ธ.
์, ์ฐ๋ฆฌ ์์ ์ ์ํ ์ ์ฅ ๋ ผ๋ฆฌ๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ ์ํด ์ด ์์ ์ ์ํํ ์๋ ์์์ ๋ณด์ฌ์ค๋๋ค. ์ฌ์ฉ์ ๋ชจ๋ ๋จ์ผ ์์ด์ ๋ํ ์์ ฏ์ ๋ง๋ญ๋๋ค. ๊ทธ๋ฌ๋ ์ผ๋ง๋ ๋ฒ๊ฑฐ๋กญ๊ณ ์ ์ง ๊ด๋ฆฌ๊ฐ ๊ณจ์น ์ํ์ง! ์๋ช ์ฃผ๊ธฐ ํํฌ๋ฅผ ์ฌ์ฉํ์ฌ ์์ ์ํ ์ ์ฅ ๊ฐ์ฒด๋ฅผ ์ฝ๊ฒ ๊ตฌ์ฑํ ์ ์๋ ๋ฐฉ๋ฒ์ด ํจ์ฌ ๋ ์ข์ผ๋ฉฐ, ๋ ๋๋ง์ ์ํ ์ ์ฉ ์์ ฏ์ด๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋น๋๋ฅผ ๋ง๋ค๋ ค๋ ๊ฒฝ์ฐ ๋งจ ์์ ๋ ์ด์ด๋ฅผ ์ฝ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
๊ทธ๋งํ ๊ฐ์น๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ ์ ๋๋ฉ์ด์
์์ ฏ๋ณด๋ค ๋ด ์ฑ์์ useAnimation
์ ๊ฐ์ ๊ฒ์ ๋ง์ด ์ฌ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด AnimatedContainer์ ๊ฐ์ ์์ ฏ์์ ์ ์ง์๋์ง ์๋ SpringAnimation์ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ๊ทธ๋ค์ ๋ชจ๋ Simulation
์ธ์๋ฅผ ํ์ฉํ๋ ์๋ฎฌ๋ ์ด์
๊ธฐ๋ฐ ์ ๋๋ฉ์ด์
์ด ์๋ curve
๋ฐ duration
ํ์ฌ ์๊ฐ ๊ธฐ๋ฐ ์ ๋๋ฉ์ด์
์ ๊ฐ์ ํฉ๋๋ค.
useAnimation
์ด์์ผ๋ก ์ถ์ํ๋ฅผ ๋ง๋ค์์ง๋ง ์คํ๋ง์ ์ฌ์ฉํ์ฌ useSpringAnimation
๋ผ๊ณ ํ์ต๋๋ค. ์ด ํํฌ์ ์ฌ์ฉํ ๋ํผ ์์ ฏ์ AnimatedContainer
์ ๋น์ทํ์ง๋ง @esDotDev ๋ผ๊ณ ํ๋ ๊ฒ์ฒ๋ผ ๋ชจ๋ ์ ๋๋ฉ์ด์
์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ํจ์ฌ ๋ ์ฝ๊ฒ ๋ง๋ค ์ ์์์ต๋๋ค. ๋
ผ๋ฆฌ๊ฐ ๋ง์ด ๋์ผํ๊ธฐ ๋๋ฌธ์
๋๋ค. useSpringAnimation
๋ฅผ ๋ค์ ์ฌ์ฉํ์ฌ ๋ชจ๋ ์ ๋๋ฉ์ด์
์์ ฏ์ ๋ด ์์ ์ ๋ฒ์ ์ ๋ง๋ค ์๋ ์์ง๋ง ๋ด ํ๋ก์ ํธ์ ๊ผญ ํ์ํ ๊ฒ์ ์๋๋๋ค. ์ด๊ฒ์ ํํฌ๊ฐ ์ ๊ณตํ๋ ๋ผ์ดํ ์ฌ์ดํด ๋ก์ง ์ฌ์ฌ์ฉ์ ํ์ ๋ค์ ํ ๋ฒ ๋ณด์ฌ์ค๋๋ค.
์๋ฅผ ๋ค์ด, if var anim = AnimationController.use(context, duration: widget.duration ?? _duration); ๊ทธ๋ค์ ์ผ๋ฅ ์๋ฏผ์ด์๊ณ ์ด๋ฌํ ์์์ ๋๋ ๋ช ์์ ์ ๋๋ฉ์ด์ ์ ์ค์ ๋ก ์กด์ฌํ ํ์๊ฐ ์์์ต๋๋ค. ์์ ฏ์ ์ปจํ ์คํธ ๋ด์์ ์ํ ์ ์ฅ ์ฌ๋ฌผ(AnimationController)์ ์ฝ๊ฒ ํฉ์ฑํ๋ ํต์ฌ ๋ฌธ์ ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ๋ชจ๋ ์์ฑ๋์๊ธฐ ๋๋ฌธ์ ์ค๋ณต์ผ๋ก ๋ ๋๋ง๋ฉ๋๋ค. AnimatedBuilder + AnimatorController.use()๋ก ๋์ผํ ์์ ์ ์ํํ ์ ์๊ธฐ ๋๋ฌธ์ TAB์ ๊ฑฐ์ ๋ฌด์๋ฏธํด์ง๋๋ค.
์์ ๋ด ์๊ฒฌ์ ์ฝ์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์คํ๋ง ์ ๋๋ฉ์ด์
ํ
์ผ๋ก ์ํํ ์์
๊ณผ ์ ํํ ์ผ์นํ๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋ก์ง์ ์บก์ํํ ๋ค์ ๋จ์ํ AnimatedBuilder๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ์์์ ์ผ๋ก ๋ง๋ค๊ธฐ ์ํด AnimatedContainer์์ ํ๋ ๊ฒ์ฒ๋ผ ์ํ์ ๋ณ๊ฒฝํ๋ฉด ์ ๋๋ฉ์ด์
์ด ์ ์ฉ๋๋๋ก didUpdateWidget
( didUpdateHook
์์ flutter_hooks
) ๋ฉ์๋๋ฅผ ์ถ๊ฐํ์ต๋๋ค. ์ด์ ๊ฐ์์ ์ ๊ฐ์ผ๋ก ์ ๋๋ฉ์ด์
์ ์คํํฉ๋๋ค.
https://github.com/TimWhiting/local_widget_state_approaches/tree/master/lib/stateful ์ ์๊ฐ ์ด์ ์ฌ๋๋ค์ด ํด๊ฒฐํ๊ณ ์ ํ๋ ๋ฌธ์ ๋ฅผ ๋ํํ๋ค๊ณ ๊ฐ์ ํ๋ ๊ฒ์ด ๋ง์ต๋๊น?
์์งํ ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๋๋ _์_๋ผ๊ณ ๋งํ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ์ด๋ฌํ ์๋ฅผ ์ด๋ป๊ฒ ํด์ํ ๊ฒ์ธ๊ฐ์ ๋ฌ๋ ค ์์ต๋๋ค.์ด ์ค๋ ๋์์ ์ฐ๋ฆฌ๋ ์๋ก๋ฅผ ์ดํดํ์ง ๋ชปํ ์ญ์ฌ๊ฐ ์์ด์ ๋ค์๋ ์ด๋ฐ ์ผ์ด ์ผ์ด๋์ง ์์ ๊ฒ์ด๋ผ๊ณ ์ฅ๋ดํ ์ ์์ต๋๋ค.
์ด๊ฒ์ด ๋ถ๋ถ์ ์ผ๋ก ๋ด๊ฐ ์ฝ๋ ์์ ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ซ์ดํ๊ณ ๋์ ๊ท์น ์งํฉ์ ์ถ์ถํ๋๋ก ์ ์ํ ์ด์ ์ ๋๋ค.
์๋ ์ฃผ๊ด์ ์ด๊ณ ์ฌ๋ฌ ์๋ฃจ์ ์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ ๊ทธ ์ค ์ผ๋ถ๋ ๋ ๊ด๋ฒ์ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง ๋ชปํ ์ ์์ต๋๋ค.
๋ํ ์ด ๋ฌธ์ ์ ๋ ผ์๋ ๋ชจ๋ ์ฝ๋ ์ํ์ ํฌํจํด์ผ ํ๋ค๊ณ ๋งํ๊ณ ์ถ์ต๋๋ค .
local_state ์ ์ฅ์์ ์ถ๊ฐํ๋ PR์ ๋ง๋ค ์ ์์ต๋๋ค.
๋งค์ฐ ์ ์ฉํ ๊ฒ์ ๋๋ค.
๋๋ ์ด ์ค๋ ๋๊ฐ ์ฌ์ฌ์ฉ์ ์ ์ํ์ง ์์๊ฑฐ๋ ์ฌ์ฌ์ฉ์ด ์ด๋ป๊ฒ ์๊ฒผ๋์ง ์ง์ ํ๊ณ ์ถ์ต๋๋ค. ๋ํ๊ฐ ์ด์ ์ ์์ง ์๋๋ก ์ ์ํ ๋ ๊ณ ํต์ค๋ฝ๊ฒ ๊ตฌ์ฒด์ ์ด์ด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
Flutter์ ๊ด๋ จํ์ฌ ์ฌ์ฌ์ฉ์ด _์๋_๋ง ํ์ํ์ต๋๋ค.
๊ฝค ๋ง์ ์ฌ์ฉ ์๊ฐ ์์๊ณ ํํฌ๋ ์์ ฏ ์ํ ์ฌ์ฌ์ฉ์ ์ ์ฒด ์๋ฅผ ๋ช ํํ๊ฒ ์ ๊ณตํฉ๋๋ค. ๊ฒ๋ณด๊ธฐ์ ์ง์ค์ ์ผ๋ก ๋ณด์ด๊ธฐ ๋๋ฌธ์ ํผ๋์ด ์ด๋์์ ๋น๋กฏ๋ ๊ฒ์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
์ฌ์ฌ์ฉ์ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋จํ ์ ์ํ ์ ์์ต๋๋ค. _๋น๋ ์์ ฏ์ด ํ ์ ์๋ ๋ชจ๋ ๊ฒ._
๋ชจ๋ ์์ ฏ ๋ด๋ถ์ ์กด์ฌํ ์ ์๋ ๋ค์๊ณผ ๊ฐ์ ์ํ ์ ์ฅ ๊ฐ์ฒด์ ๋ํ ์์ฒญ์ ๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ์์ฉ๊ตฌ ์์ด ์ค๋นํ๊ธฐ ์ฝ๊ณ ๊ฐ๊ฒฐํ ๋ฐฉ์์ผ๋ก ์ํํฉ๋๋ค.
AnimationController anim = AnimationController.stateful(duration: widget.duration);
์ด๊ฒ์ด Stateless ๋ฐ Stateful ์์ ฏ์์ ์๋ํ๋ ๊ฒฝ์ฐ. widget.something์ด ๋ณ๊ฒฝ๋ ๋ ๋ค์ ๋น๋๋๊ณ ์์ฒด init() ๋ฐ dispose()๋ฅผ ์คํํ ์ ์๋ค๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก ์น์๊ฐ ์๊ณ ๋ชจ๋๊ฐ ๊ฐ์ฌํ ๊ฒ์ด๋ผ๊ณ ํ์ ํฉ๋๋ค.
๋ด๊ฐ ๊ณ ๊ตฐ๋ถํฌํ๋ ์ฃผ์ ๋ฌธ์ ๋ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ์ด ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ValueListenableBuilder๋ ์ฑ๋ฅ์ ์ธก์ ๊ฐ๋ฅํ๊ฒ ๊ฐ์ ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ์์ ์ธ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. Property ์ ๊ทผ ๋ฐฉ์์ผ๋ก ๊ทธ๋ ๊ฒ ํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
๋๋ ์ด๊ฒ์ด ๋ฌธ์ ๊ฐ ์๋๋ผ๊ณ ํ์ ํฉ๋๋ค. XTransition
์์ ฏ์ด ์ง๊ธ ์๋ํ๋ ๊ฒ๊ณผ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ด ์์
์ ์ํํฉ๋๋ค. ๋ณต์กํ ์ํ๊ฐ ์๊ณ ๊ฐ๋น์ผ ์์์ ๊ฐ๊ณ ์ถ๋ค๋ฉด ์์ ๋ํผ ์์ ฏ์ ๋ง๋ค๋ฉด ๋ฉ๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ง๋ค ์ ์๋ ๊ฒ์ฒ๋ผ:
FadeTransition(opacity: anim, child: someChild)
'์ฌ๋ฌผ'์ ์์ ฏ์ ์ ๋ฌํ์ฌ ๋ค์ ๋ ๋๋งํจ์ผ๋ก์จ ๋ ๋๋งํ๋ ค๋ ๋ชจ๋ ๊ฒ์ผ๋ก ์ฝ๊ฒ ๊ทธ๋ ๊ฒ ํ ์ ์์ต๋๋ค.
MyThingRenderer(value: thing, child: someChild)
@esDotDev์ ๋์ํ์ต๋๋ค. ์์ ์ธ๊ธํ๋ฏ์ด ์ด์ ๋ํ ๋์ฒด ์ ๋ชฉ์ "๋น๋๋ฅผ ์ํ ๊ตฌ๋ฌธ ์คํ"์ ๋๋ค.
๋ด๊ฐ ๊ณ ๊ตฐ๋ถํฌํ๋ ์ฃผ์ ๋ฌธ์ ๋ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ์ด ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ValueListenableBuilder๋ ์ฑ๋ฅ์ ์ธก์ ๊ฐ๋ฅํ๊ฒ ๊ฐ์ ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ์์ ์ธ์๋ฅผ ์ฌ์ฉํฉ๋๋ค. Property ์ ๊ทผ ๋ฐฉ์์ผ๋ก ๊ทธ๋ ๊ฒ ํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
๋๋ ์ด๊ฒ์ด ๋ฌธ์ ๊ฐ ์๋๋ผ๊ณ ํ์ ํฉ๋๋ค.
XTransition
์์ ฏ์ด ์ง๊ธ ์๋ํ๋ ๊ฒ๊ณผ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ด ์์ ์ ์ํํฉ๋๋ค. ๋ณต์กํ ์ํ๊ฐ ์๊ณ ๊ฐ๋น์ผ ์์์ ๊ฐ๊ณ ์ถ๋ค๋ฉด ์์ ๋ํผ ์์ ฏ์ ๋ง๋ค๋ฉด ๋ฉ๋๋ค. ์ฐ๋ฆฌ๊ฐ ๋ง๋ค ์ ์๋ ๊ฒ์ฒ๋ผ:
๊ทธ๋ด ํ์๊ฐ ์์ต๋๋ค.
์ด ๊ธฐ๋ฅ์ ์ด์ ์ค ํ๋๋ "๋งค๊ฐ๋ณ์๊ฐ ๋ณ๊ฒฝ๋์ง ์์ ๊ฒฝ์ฐ ์์ ฏ ์ธ์คํด์ค๋ฅผ ์บ์"ํ๋ ์ํ ๋
ผ๋ฆฌ๋ฅผ ๊ฐ์ง ์ ์๋ค๋ ๊ฒ์
๋๋ค.
ํํฌ๋ฅผ ์ฌ์ฉํ๋ฉด React์์ useMemo
๋ฉ๋๋ค.
<insert whatever>
final myWidget = useMemo(() => MyWidget(pameter: value), [value]);
์ด ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด value
๋ณ๊ฒฝ๋ ๋ myWidget
๊ฐ _only_ ๋ค์ ๋น๋๋ฉ๋๋ค. useMemo
๋ฅผ ํธ์ถํ๋ ์์ ฏ์ด ๋ค๋ฅธ ์ด์ ๋ก ๋ค์ ๋น๋๋๋๋ผ๋.
์ด๋ ์์ ฏ์ const ์์ฑ์์ ์ ์ฌํ์ง๋ง ๋์ ๋งค๊ฐ๋ณ์๋ฅผ ํ์ฉํฉ๋๋ค.
Tim์ ์ ์ฅ์์ ๊ทธ๋ ๊ฒ ํ๋ ์๊ฐ ์์ต๋๋ค.
๋ชจ๋ ์์ ฏ ๋ด๋ถ์ ์กด์ฌํ ์ ์๋ ๋ค์๊ณผ ๊ฐ์ ์ํ ์ ์ฅ ๊ฐ์ฒด์ ๋ํ ์์ฒญ์ ๋๋ค.
- ์์ ์ ์ํ๋ฅผ ์บก์ํ
- initState/dispose ํธ์ถ์ ๋ฐ๋ผ ์์ฒด์ ์ผ๋ก ์ค์ /ํด์ ๊ฐ๋ฅ
- ์์ ฏ์์ ์ข ์์ฑ์ด ๋ณ๊ฒฝ๋ ๋ ๋ฐ์ํ ์ ์์ต๋๋ค.
๋๋ ๊ทธ ๋งค๊ฐ๋ณ์๋ก StatefulWidget
์ด ์์
์ ๋ ์ ์ํํ์ง ์๋ ์ด์ ๋ฅผ ์๊ธฐ๊ฐ ์ด๋ ต๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด๊ฒ์ด ๋ด๊ฐ ์๋ฃจ์
์์ ์ฐ๋ฆฌ๊ฐ ์ค์ ๋ก ์ถ๊ตฌํ๋ ๊ฒ์ด ๋ฌด์์ธ์ง์ ๋ํ ์ง๋ฌธ์ ํ ์ด์ ์
๋๋ค. flutter_hooks
๋ฅผ ์ฌ์ฉํ๋ ์ฌ๋์ผ๋ก์ ๋๋ ๊ทธ๊ฒ๋ค์ด StatefulWidget
๋ณด๋ค ์์
ํ๋ ๊ฒ์ด ๋ ์ฌ๋ฏธ์๋ค๋ ๊ฒ์ ์์ง๋ง ์ด๋ ๋จ์ง ์ฅํฉํจ์ ํผํ๊ธฐ ์ํ ๊ฒ์
๋๋ค. ํํฌ์ ๊ด์ ์์ ์๊ฐํ๊ธฐ ๋๋ฌธ์ด ์๋๋๋ค. ์ค์ ๋ก Widget
๋นํด ํํฌ์์ UI ์
๋ฐ์ดํธ์ ๋ํ ์ถ๋ก ์ด ์ด๋ ต๋ค๋ ๊ฒ์ ์์์ต๋๋ค.
- ์์ ฏ์์ ์ข ์์ฑ์ด ๋ณ๊ฒฝ๋ ๋ ๋ฐ์ํ ์ ์์ต๋๋ค.
์์ ฏ ๋ด์์ ์์ฑ/ํ๋๋ ์ข ์์ฑ์ ์๋ฏธํฉ๋๊น? ์๋๋ฉด ํธ๋ฆฌ์ ์์ ฏ ์๋์ ์๋ ์ข ์์ฑ์ ๋๊น?
Flutter์ ์ฅํฉํจ/ํผ๋์ ์ผ์ผํค๋ ๋ฌธ์ ๊ฐ ์๋ค๋ ๊ฒ์ ๋ถ์ ํ๋ ๊ฒ์ด ์๋๋ผ "์ฌ์ฌ์ฉ"์ด ๋ฌด์์ธ์ง์ ๋ํ ๋์ผํ ์ ์ ๋ชจ๋ธ์ ์ค์ ๋ก ๊ฐ์ง๊ณ ์๋ ๋ชจ๋ ์ฌ๋์๊ฒ ์์กดํ๋ ๊ฒ์ ์ฃผ์ ํฉ๋๋ค. ์ค๋ช ํด์ฃผ์ ์ ์ ๋ง ๊ฐ์ฌํฉ๋๋ค. ์ฌ๋๋ค์ด ๋ค๋ฅธ ๋ชจ๋ธ์ ๊ฐ์ง๊ณ ์์ ๋ ๊ทธ๋ค์ ๋ค๋ฅธ ์๋ฃจ์ ์ ๋ง๋ญ๋๋ค.
SW๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ์ํํ๋ ๊ฒ์ ํน์ ์ฌ์ฉ ์ฌ๋ก์์๋ ๊ด์ฐฎ์ง๋ง ๋ง์ SW์์ ์ฌ์ฉ ์ฌ๋ก์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ ผ๋ฆฌ๋ฅผ ์ถ์ํํ๋ ๋ฐ๋ ์ข์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ ๋๋ฉ์ด์ ์ ์ค์ /ํด์ฒด๋ฅผ ์๋ก ๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. ์ด๊ฒ์ SW ์์ฒด๊ฐ ์๋๋ผ ์ ์ฒด์์ ์ฌ์ฉํ๊ณ ์ ํ๋ ๊ฒ์ ๋๋ค. ์บก์ํ๋ ์ํ ๊ณต์ ์ ๋ํ ์ผ๊ธ ์ง์์ด ์์ผ๋ฉด ๊ฒฐ๊ตญ ๋น๋(์: TweenAnimationBuilder)๋ฅผ ๋ง๋ค๊ฑฐ๋ ํน์ ์์ ฏ(์: AnimatedContainer ๋ฑ)์ ๋ง์ด ๋ง๋ค์ด์ผ ํฉ๋๋ค. ํด๋น ๋ ผ๋ฆฌ๋ฅผ ๋ฒ๋ค๋ก ๋ฌถ์ด ์ฌ์ฌ์ฉํ ์ ์๋ค๋ฉด ํจ์ฌ ๋ ์ฐ์ํด์ง๋๋ค. ๊ทธ๊ฒ์ ๋น์ ์ด ์ํ๋ ์ด๋ค ๋ฐฉ์์ผ๋ก๋ ๋๋ฌด ์์ ์์ต๋๋ค.
์์ ฏ ์ข
์์ฑ ์ธก๋ฉด์์ ๋งํ์๋ฉด, widget.foo
๋ณ๊ฒฝ๋๋ฉด stateful-thing์ ํ์ํ ์
๋ฐ์ดํธ๋ฅผ ์ํํ ๊ธฐํ๋ฅผ ์ป์ต๋๋ค. stateful
AnimationController์ ๊ฒฝ์ฐ ์ง์ ์๊ฐ์ด ๋ณ๊ฒฝ๋์๋์ง ํ์ธํ๊ณ ๋ณ๊ฒฝ๋๋ฉด ๋ด๋ถ AnimatorController ์ธ์คํด์ค๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ ๋๋ฉ์ด์
์ ๋ชจ๋ ๊ตฌํ์๊ฐ ์์ฑ ๋ณ๊ฒฝ์ ์ฒ๋ฆฌํ ํ์๊ฐ ์์ต๋๋ค.
<insert whatever> final myWidget = useMemo(() => MyWidget(pameter: value), [value]);
์ด ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด
value
๋ณ๊ฒฝ๋ ๋myWidget
๊ฐ _only_ ๋ค์ ๋น๋๋ฉ๋๋ค.useMemo
๋ฅผ ํธ์ถํ๋ ์์ ฏ์ด ๋ค๋ฅธ ์ด์ ๋ก ๋ค์ ๋น๋๋๋๋ผ๋.
์, Memoized๋ ์์ ฏ ์์ฒด๋ฅผ ๋ฐํํ๊ณ [value]๋ฅผ ๋ค์ ๋น๋ ํธ๋ฆฌ๊ฑฐ๋ก ์ ๋ฌํฉ๋๋ค. ๊น๋ํฉ๋๋ค!
AnimatedOpacity์ ํต์ฌ์ ๋ถ๋ชจ๋ ์์๋ ๋ค์ ๋น๋ํ์ง ์๋๋ค๋ ๊ฒ์ ๋๋ค. ์ค์ ๋ก AnimatedOpacity๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋๋ฉ์ด์ ์ ํธ๋ฆฌ๊ฑฐํ๋ฉด ์ ๋๋ฉ์ด์ ์ ํธ๋ฆฌ๊ฑฐํ ์ฒซ ๋ฒ์งธ ํ๋ ์ ์ดํ์๋ ๋ฌธ์ ๊ทธ๋๋ก ์๋ฌด ๊ฒ๋ ๋ค์ ๋น๋๋์ง ์์ต๋๋ค. ๋น๋ ๋จ๊ณ๋ฅผ ์์ ํ ๊ฑด๋๋ฐ๊ณ ๋ ๋ ๊ฐ์ฒด์์ ๋ชจ๋ ์์ ์ ์ํํฉ๋๋ค(๋ ๋ ํธ๋ฆฌ์์๋ ๋ค์ ๊ทธ๋ฆฌ๊ธฐ๋ง ํ๊ณ ๋ฆด๋ ์ด์์์ ํ์ง ์์ผ๋ฉฐ ์ค์ ๋ก ๋ ์ด์ด๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ํ์ธํธ๋ ๋งค์ฐ ์ต์ํ๋จ). ์ฑ๋ฅ๊ณผ ๋ฐฐํฐ๋ฆฌ ์ฌ์ฉ๋์ ์๋นํ ์ฐจ์ด๋ฅผ ๋ง๋ญ๋๋ค. ์ฌ๊ธฐ์ ์ฐ๋ฆฌ๊ฐ ์ ์ํ๋ ์๋ฃจ์ ์ด ๋ฌด์์ด๋ ํต์ฌ ํ๋ ์์ํฌ์ ๊ตฌ์ถํ๋ ค๋ฉด ๊ทธ๋ฌํ ์ฑ๋ฅ์ ์ ์งํ ์ ์์ด์ผ ํฉ๋๋ค.
๋ถํํ๋ ๋๋ ์ด ๋ฌธ์ ์ ์๋ฅผ ์ง์ญ ์ฃผ ๋ฆฌํฌ์งํ ๋ฆฌ์ ๋์กฐํ ์๊ฐ์ด ์์์ต๋๋ค. ๋๋ ๊ฐ๊น์ด ์์ผ ๋ด์ ๊ทธ๊ฒ์ ์ป์ง ๋ชปํ ์๋ ์์ผ๋ฏ๋ก ๋ค๋ฅธ ์ฌ๋์ด ๊ทธ๊ฒ์ ๋ฐ๋ฆฌ๋ฌ ๊ฐ๊ณ ์ถ๋ค๋ฉด ๋๋ ๊ด์ฐฎ์ ๊ฒ์ ๋๋ค.
๋น๋/๋ ๋๋ง ๋ฉ์๋ ๋ด๋ถ์ ์ ์๋ ํํฌ์ ์ฑ๋ฅ๊ณผ ๊ด๋ จํ์ฌ(์ด ๋ฌธ์ ์ ์๋ถ๋ถ์์ ๋๊ตฐ๊ฐ ์ธ๊ธํ ๊ฒ ๊ฐ์ต๋๋ค), ์ ๋ React ๋ฌธ์๋ฅผ ์ฝ๊ณ ์ด FAQ๊ฐ ์ ์ฉํ ์ ์์์ ๋ณด์์ต๋๋ค. ํํฌ ๋ชจ๋ ๋ ๋๋ง์์ ํจ์๋ฅผ ๋ง๋๋ ๋๋ฌธ์ ์๋๊ฐ ๋๋ฆฐ ๊ฒฝ์ฐ ๊ธฐ๋ณธ์ ์ผ๋ก๋ ์๊ตฌํ์ง ์์ผ๋ฉฐ, ๊ทธ๋ค์ ์ธํด ๊ฐ์ ํํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ๋ฅ์ memoize ์์๊ฒ๋๊ณ ๊ทธ ์ค ํ๋๋ ๋ช ๊ฐ์ง ์ด์ ์ ๋ ๋งํ useMemo
๋๋ useCallback
.
https://reactjs.org/docs/hooks-faq.html#are -hooks-slow-because-of-creating-functions-in-render
ํํฌ ๋ชจ๋ ๋ ๋๋ง์์ ํจ์๋ฅผ ๋ง๋๋ ๋๋ฌธ์ ์๋๊ฐ ๋๋ฆฐ ๊ฒฝ์ฐ ๊ธฐ๋ณธ์ ์ผ๋ก๋ ์๊ตฌํ์ง ์์ผ๋ฉฐ, ๊ทธ๋ค์ ์ธํด ๊ฐ์ ํํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ๋ฅ์ memoize ์์๊ฒ๋๊ณ ๊ทธ ์ค ํ๋๋ ๋ช ๊ฐ์ง ์ด์ ์ ๋ ๋งํ
useMemo
๋๋useCallback
.
๊ฑฑ์ ์ ํ์๋ฅผ ๋ง๋๋ ๋น์ฉ์ ๊ดํ ๊ฒ์ด ์๋๋ผ ์ค์ ๋ก ์๋์ ์ผ๋ก ์ ๋ ดํฉ๋๋ค. ์ค๋๋ ์ต์ ์ ๊ฒฝ์ฐ Flutter๊ฐ ๋ณด์ฌ์ฃผ๋ ์ฑ๋ฅ์ ํต์ฌ์ ์ฝ๋๋ฅผ ์ ํ ์คํํ๋ ๊ฒ๊ณผ ์ ํ ์คํํ์ง ์๋ ๊ฒ์ ์ฐจ์ด์ ๋๋ค. ์ฐ๋ฆฌ๋ ๋ฌธ์ ๊ทธ๋๋ก ํน์ ์ฝ๋ ๊ฒฝ๋ก๋ฅผ ์ ํ ์คํํ์ง ์๋ ์๊ณ ๋ฆฌ์ฆ์ ๋ง๋๋ ๋ฐ ๋ง์ ๋ ธ๋ ฅ์ ๊ธฐ์ธ์์ต๋๋ค(์: AnimatedOpacity์ ๋ํด ๋น๋ ๋จ๊ณ๋ฅผ ์์ ํ ๊ฑด๋๋ฐ๊ฑฐ๋ ์ ๋ฐ์ดํธ๋ฅผ ์ํํ๊ธฐ ์ํด ํธ๋ฆฌ๋ฅผ ๊ฑท๋ ๊ฒ์ ํผํ๊ณ ๋์ ์ํฅ์ ๋ฐ๋ ๋ ธ๋๋ฅผ ๋์์ผ๋ก ํ๋ ๋ฐฉ์).
๋๋ ๋์ํ๋ค. ์ ๋ Flutter ๋ด๋ถ๋ ํํฌ ๋ด๋ถ์ ๋ํด ์ ์์ง ๋ชปํ์ง๋ง ํํฌ๊ฐ ์คํ๋์ด์ผ ํ๋ ์์ ๊ณผ ์คํ๋์ง ์์์ผ ํ ์์ ์ ํ์ ํด์ผ ํ๊ณ (์์ง ์คํํ์ง ์๋ ๊ฒฝ์ฐ) ์ฑ๋ฅ์ด ํํดํ์ง ์์์ผ ํ๋ค๋ ๊ฒ์ ๋ง์ต๋๋ค.
์ค๋๋ Flutter๊ฐ ์ต์ ์ ๊ฒฝ์ฐ์ ๋ํ๋ด๋ ์ฑ๋ฅ์ ํต์ฌ์ ์ฝ๋๋ฅผ ์ ํ ์คํํ๋ ๊ฒ๊ณผ ์ ํ ์คํํ์ง ์๋ ๊ฒ์ ์ฐจ์ด์ ๋๋ค.
์์ ๋ช ๋ฒ ์ธ๊ธํ๋ฏ์ด ํํฌ๋ ์ด๋ฅผ ๊ฐ์ ํฉ๋๋ค.
Tim์ ๋ฆฌํฌ์งํ ๋ฆฌ์ ์๋ ์ ๋๋ฉ์ด์
์์ ๊ฐ ๊ทธ ์ฆ๊ฑฐ์
๋๋ค. ํํฌ ๋ณํ์ useMemo
๋๋ถ์ StatefulWidget ๋ณํ๋ณด๋ค ๋ ์์ฃผ ๋ค์ ๋น๋๋ฉ๋๋ค.
์ด ์ค๋ ๋์ ์ด๋๊ฐ์์ ์ด ๋ฌธ์ ์ ๋ํ ์๋ฃจ์ ์ ๋ํด ๋ ผ์ ์ค์ด๋ฏ๋ก ์ ์์ผ๋ก๋ ๋ ์ด๋ธ์ ์ง์ ํฉ๋๋ค.
๋ฐ์๊ณผ ํจ๊ป ํ๋ฌํฐ์ ํตํฉ๋ ํํฌ๋ฅผ ๋ณด๊ณ ์ถ์ต๋๋ค. ๋๋ ์ฒ์ react๋ฅผ ์ฌ์ฉํ ๋์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ํ๋ฅผ ํ๋ฌํฐ๋ก ๋ด ๋๋ค. ํํฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋๋ ๊ฐ์ธ์ ์ผ๋ก ๊ฒฐ์ฝ ๋๋์ ๊ฐ์ง ์์ ๊ฒ์ ๋๋ค.
ํจ์ฌ ๋ ์ฝ๊ธฐ ์ฌ์ด IMO์ ๋๋ค. ํ์ฌ๋ stateful ์์ ฏ๊ณผ usestate์ ๋๋กญํ ํํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๊ฐ์ ํด๋์ค๋ฅผ ์ ์ธํด์ผ ํฉ๋๋ค.
๋ํ ๊ฐ๋ฐ์๋ค์ด ํ๋ฌํฐ ์ฝ๋๋ฅผ ๋ณผ ๋ ์ข ์ข ๊ฐ์ง ๋ชปํ๋ ๋ฐ์์ ํ๋ฌํฐ์ ์ด๋ ์ ๋ ์ต์ํ๊ฒ ๋ง๋ค ๊ฒ์ ๋๋ค. ๋ถ๋ช ํ flutter์ react๋ฅผ ๋น๊ตํ๋ ๊ฒ์ ์ํํ ๊ธธ์ ๋๋ค. ํ์ง๋ง ํํฌ๋ฅผ ์ฌ์ฉํ ๊ฐ๋ฐ์ ๊ฒฝํ์ด ํํฌ๊ฐ ์๋ ๊ฒฝํ๋ณด๋ค ๋ซ๋ค๊ณ ์๊ฐํฉ๋๋ค.
์ ๋ flutter btw๋ฅผ ์ซ์ดํ์ง ์์ต๋๋ค. ์ค์ ๋ก ์ ๊ฐ ๊ฐ์ฅ ์ข์ํ๋ ํ๋ ์์ํฌ์ด์ง๋ง ๊ฐ๋ ์ฑ๊ณผ ๊ฐ๋ฐ ๊ฒฝํ์ ๋์ผ ์ ์๋ ์ ๋ง ์ข์ ๊ธฐํ๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๋ช ๋ช ๊ท์น์ ๊ฐ์ ํ๊ณ ๋ ํ๋ คํ๊ฒ ๋ง๋ค ๊ธฐํ๊ฐ ๋ถ๋ช ํ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
UseMemoized ๋ฐ UseEffect ๊ฐ์ ๊ฒ์ ์๋นํ ์์ํ๊ฒ ๋ค๋ฆฌ๋ฉฐ ๋น๋ fxn์์ init() ์ฝ๋๋ฅผ ์คํํ ํ์๊ฐ ์๋ ๋ฐฉ๋ฒ์ ์ํ๋ ๊ฒ์ฒ๋ผ ๋ค๋ฆฝ๋๋ค.
ํ์ฌ ํํฌ๋ก ์ด๊ธฐํํ๋ ๊ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค(์ ์๊ฐ์๋?).
Widget build(){
useEffect(
(){
// Do init stuff
return (){ //Do dispose stuff };
}, [ ] ) //<-- pass an empty list of rebuild triggers, so this can only fire once. Passing null here would let it fire every time.
);
}
๋๋ ์ด ์ฝ๋์ ๊ฐ๊ฒฐํจ์ ๊ฐ์ฌํ์ง๋ง ๊ฐ๋ ์ฑ๊ณผ "์์ฒด ๋ฌธ์ํ ์ฝ๋" ๊ด์ ์์ ๋ณด๋ฉด ํ์คํ ์ด์์ ์ด์ง ์์ต๋๋ค. ์ฌ๊ธฐ์๋ ๋ง์ ์์์ ๋ง์ ์ด ์ผ์ด๋๊ณ ์์ต๋๋ค. ์ด์์ ์ผ๋ก๋ init/dispose ํํฌ์ ๋ํด ๋ช ์์ ์ด๋ฉฐ Stateless ์์ ฏ๊ณผ ํจ๊ป ์ฌ์ฉํ ๋ ๊ฐ์ ๋ก ๋น๋๋์ง ์๋ ๊ฒ์ด ์์ต๋๋ค.
useMemoized ๋ฐ useEffect์ ๊ฐ์ ํญ๋ชฉ์ ๋ ๋ช
์์ ์ผ๋ก hook ComputedValue()
๋ฐ hook SideEffect()
์ด๋ฆ์ ์ง์ ํ๋ ๊ฒ์ด ๋ ๋์ ์ ์์ต๋๋ค.
Widget build(BuildContext context){
List<int> volumes = hook ComputedValue(
execute: ()=>_getVolumeFromAudioSamples(widget.bytes),
dependencies: [ widget.bytes ]);
hook SideEffect(
execute: ()=>_recordSongChangedAnalytics()
dependencies: [ widget.songUrl ]);
)
return SongVisualizer(volumes: volumes);
}
๋๋ ๊ทธ๊ฒ์ ์ข์ํ์ง๋ง hook
ํค์๋์ ์ฌ์ฉ์ ๋ํด ์ด๋ป๊ฒ ๋๋ผ๋์ง ์ ๋ชจ๋ฅด๊ฒ ๊ณ ๊ทธ๊ฒ์ด ์ธ๊ตญ ๊ฐ๋
์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ์ ํค์๋๋ฅผ ์๊ฐํ๋ ๊ฒ์ ์ ์๊ฐ์๋ withSideEffect
๋๋ withComputedValue
์ ๊ฐ์ ์ต์์ ์ ๊ทผ ๋ฐฉ์์ด ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋๋ ์ธ์ด ๋์์ด๋๊ฐ ์๋๋ฏ๋ก ๋ด ๋ง์ ๊ฐ์น๊ฐ ์์ต๋๋ค.
๋๋ Flutter์ ํํฌ์ ๊ฐ์ ๊ธฐ๋ฅ์ด ํ์ฌ๊ฐ ReactNative์ Flutter ์ฌ์ด์์ ๊ฒฐ์ ์ ๋ด๋ฆด ๋ ์ค์ ๋ก ๋์์ด ๋๋ React ๊ฐ๋ฐ์์ ํ์ต ๊ณก์ ์ ์ํํ๊ฒ ํ๋ ๋ฐ ํฐ ๋์์ด ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
@lemusthelroy๋ฅผ ๋์๊ธฐ๋ฉฐ Flutter๋ ๋จ์ฐ์ฝ ์ ๊ฐ ๊ฐ์ฅ ์ข์ํ๋ ํ๋ ์์ํฌ์ด๋ฉฐ ๊ทธ ๋ฐฉํฅ์ ๋ณด๊ฒ ๋์ด ๋งค์ฐ ๊ธฐ์ฉ๋๋ค. ๊ทธ๋ฌ๋ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ๊ฐ๋ ์ ์์ง ์๋์ ์ผ๋ก ํ์๋์ง ์์ ๋ฐฉํฅ์ผ๋ก ํ๋ ์์ํฌ๋ฅผ ์ฑ์ฅ์ํค๋ ๋ฐ ํฐ ๋์์ด ๋ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ผ๋ถ ์ฌ๋๋ค์ React์ ๊ฑฐ๋ฆฌ๋ฅผ ๋๋ ค๋ ๋ชฉ์ ์ผ๋ก ์ด ์์ด๋์ด๋ฅผ ๋ฌด์ํ๊ณ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ ๋ถํํ์ง๋ง ์ดํดํ ์ ์์ต๋๋ค.
๋ค ๊ทธ ๋์ ์๋ ์๋ฉด์ด ์๋ ๊ฒ ๊ฐ์์. ์๋ก์ด ํค์๋๋ ์ฃผ์ ์ด๋ฒคํธ์ด๋ฏ๋ก ์ง์ ์ ํ๋ ๋งค์ฐ ์ ์ํ์ง๋ง ๋ค๋ฅธ ์ธก๋ฉด์ ํ์คํ _๋ชจ๋์๊ฒ ์๋ก์ด ๊ฒ์ ๋๋ค. ๊ทธ๊ฒ ์์ด๋ ๊ฐ๋ฅํ๋ค๋ฉด ๋ฉ์ง๋ค! ํ์คํ์ง ์์ต๋๋ค ... ์ ์ด๋ ์ฐ์ํ์ง๋ ์์ต๋๋ค.
์๊ฒฌ: ์ด ๋ฌธ์ ์ ๋ํ ์ฌ์ค์์ ํด๊ฒฐ์ฑ
์ผ๋ก ํํฌ๋ฅผ ๋ช
๋ช
ํ๋ ค๋ ์ปค๋ฎค๋ํฐ ๊ฒฝํฅ์ ํจ์์ ๋ํ ํธ๊ฒฌ์์ ๋น๋กฏ๋ฉ๋๋ค. ํจ์๋ ํนํ ์ ์ ์ผ๋ก ์ ํ์ด ์ง์ ๋ ์ธ์ด์์ ๊ฐ์ฒด๋ณด๋ค ๊ตฌ์ฑํ๊ธฐ๊ฐ ๋ ๊ฐ๋จํฉ๋๋ค. ๋ง์ ๊ฐ๋ฐ์๋ฅผ ์ํ Widget์ ๋ฉํ ๋ชจ๋ธ์ ์ฌ์ค์ build
๋ฐฉ์์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๊ธฐ๋ณธ ์ธก๋ฉด์์ ๋ฌธ์ ๋ฅผ ๊ตฌ์ฑํ๋ฉด ๋๋จธ์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ์๋ํ๋ ์๋ฃจ์ ์ ์ค๊ณํ ๊ฐ๋ฅ์ฑ์ด ๋ ๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ธฐ๋ณธ ์ธก๋ฉด์์ hook
ํค์๋์ ๊ฒฝ์ฐ; ์ผ์ข
์ ํ
ํ๋ฆฟ(๋งคํฌ๋ก)์์ ํจ์๋ฅผ ์ ์ธํ๊ณ ์ ์ํ๋ ๊ฒ์ผ๋ก ๋ณผ ์ ์์ผ๋ฉฐ hook
์ ๋์ฌ๋ ์ค์ ๋ก ๋ด์ฅ ํจ์์ ๋ด๋ถ ์ํ(c-style static.xml)๊ฐ ์์์ ํธ์ถํ๋ ๊ฒ์
๋๋ค. )
Swift FunctionBuilders์ ์ด๋ค ์ข ๋ฅ์ ์ ํ ๊ธฐ์ ์ด ์๋์ง ๊ถ๊ธํฉ๋๋ค.
์ฐ๋ฆฌ๊ฐ ๊ฟ๊พธ๋ ๋์ ํ์ํ ์ฝ๋๊ฐ ๋ฌด์์ธ์ง ์ถ์ธกํด ๋ณด๊ฒ ์ต๋๋ค.
Hook SideEffect(void Function() execute, List<Object> dependencies) {
// Whatever happens each build.
}
Widget build(BuildContext context){
List<int> volumes = hook ComputedValue(
execute: ()=>_getVolumeFromAudioSamples(widget.bytes),
dependencies: [ widget.bytes ]);
SideEffect(
execute: ()=>_recordSongChangedAnalytics()
dependencies: [ widget.songUrl ]);
)
return SongVisualizer(volumes: volumes);
}
์ฌ๊ธฐ์ Hook
๋ ํํฌ์ ์ต์ํ ๊ฐ๋ฐ์๊ฐ ํํฌ ๋ฒ์น์ผ๋ก ์๊ณ ์๋ ๊ฒ์ ๋ฐ๋ผ ๊ฒฐ๊ณผ ํํฌ๊ฐ ํธ์ถ๋์์์ ์ ์ ์ผ๋ก ๋ถ์ํ๋ ๋ฐ ๋์์ด ๋๋ ์ ํ ์์คํ
์์ค ํดํน์
๋๋ค. ๊ทธ๋ฐ ์ข
๋ฅ์ ๊ฒ์ผ๋ก Hook-type์ ํจ์์ ๋งค์ฐ ์ ์ฌํ์ง๋ง ์ ์ ๋ด๋ถ ๋ณ๊ฒฝ ๊ฐ๋ฅ ์ํ๋ฅผ ๊ฐ์ง ๊ฒ์ผ๋ก ๋ฌธ์ํํ ์ ์์ต๋๋ค.
์ธ์ด์ ๊ด์ ์์ ๋ณด๋ฉด ๋๋ฌด ์ด์ํ๊ธฐ ๋๋ฌธ์ ์ด ๊ธ์ ์ฐ๋ฉด์ ์ฝ๊ฐ ์์ธ ๋ฌ๋ญ๋๋ค. ๋ค์ ๋งํ์ง๋ง, Dart๋ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ์์ฑํ๊ธฐ ์ํด ํ์ด๋ ์ธ์ด์ ๋๋ค. ์ด๋ฐ ๊ธฐ์ดํจ์ด ์ด๋์๋ ์กด์ฌํด์ผ ํ๋ค๋ฉด ๋ฐ๋ก ์ด๊ณณ์ด ์๋๊น. ํนํ ์ด ์ด์ํจ๋ง ์๋ ๊ฒ์ ์๋๋๋ค.
์๊ฒฌ: ์ด ๋ฌธ์ ์ ๋ํ ์ฌ์ค์์ ํด๊ฒฐ์ฑ ์ผ๋ก ํํฌ๋ฅผ ๋ช ๋ช ํ๋ ค๋ ์ปค๋ฎค๋ํฐ ๊ฒฝํฅ์ ํจ์์ ๋ํ ํธ๊ฒฌ์์ ๋น๋กฏ๋ฉ๋๋ค. ํจ์๋ ํนํ ์ ์ ์ผ๋ก ์ ํ์ด ์ง์ ๋ ์ธ์ด์์ ๊ฐ์ฒด๋ณด๋ค ๊ตฌ์ฑํ๊ธฐ๊ฐ ๋ ๊ฐ๋จํฉ๋๋ค. ๋ง์ ๊ฐ๋ฐ์๋ฅผ ์ํ ์์ ฏ์ ๋ฉํ ๋ชจ๋ธ์ ์ฌ์ค์ ๋น๋ ๋ฐฉ๋ฒ์ผ ๋ฟ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๊ทธ๊ฑธ๋ก ๋ฌด์จ ๋ง์ ํ๊ณ ์ถ์์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. get_it_mixin๊ณผ ํจ๊ป ์ฌ์ฉํ๋ ํํฌ ์ ๊ทผ ๋ฐฉ์์ ๋น๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ์์ ฏ ํธ๋ฆฌ๋ฅผ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
React hooks ์ ๋ํ ํฅ๋ฏธ๋ก์ด ๊ธฐ์ฌ
@nt4f04uNd ์ฑ๋ฅ, ํต์ฌ ๊ธฐ๋ฅ์ด ํ์ํ ์ด์ , ๊ธฐ๋ฅ ๋ ํด๋์ค ์คํ์ผ ์์ ฏ, ํํฌ ์ด์ธ์ ๊ฒ์ด ์๋ํ์ง ์๋ ์ด์ ๋ฑ ๋ชจ๋ ์์ ์ ์ด์ ์ ํด๊ฒฐ๋์์ต๋๋ค. ๋ค์ํ ์์ ์ ์ดํดํ๊ธฐ ์ํด ์ ์ฒด ๋ํ๋ฅผ ์ฝ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๋ค์ํ ์์ ์ ์ดํดํ๊ธฐ ์ํด ์ ์ฒด ๋ํ๋ฅผ ์ฝ๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ด๊ฒ์ ๊ทธ๋ค์ด ์ ์ฒด ์ค๋ ๋๋ฅผ ์ฝ์ง ์์๋ค๋ ์ ์ ๊ณ ๋ คํ๋ฉด ๊ณตํํ์ง๋ง ์ค๋ ๋์ ๋๋จธ์ง ๋ถ๋ถ์ ์ฝ๋ ๊ฒ์ด ์ํฉ์ ๋ ๋ช ํํ๊ฒ ๋ง๋๋์ง ํ์ ํ ์ ์์ต๋๋ค. ์์ ฏ์ ์๋ ๊ทธ๋๋ก ์ ์งํ๋ ๊ฒ์ด ์ฐ์ ์ธ ์ฌ๋๋ค๊ณผ ์์ ํ ๋ค๋ฅธ ์ผ์ ํ๊ฑฐ๋ ์์ ฏ์ ๋ชจ๋ํํ๋ ค๋ ๋ ๋ค๋ฅธ ๊ทธ๋ฃน์ด ์์ต๋๋ค.
์ฌ์ค์ผ ์๋ ์์ง๋ง ์ด ๋ฌธ์ ๋ ํ์ฌ ์์ ฏ์ผ๋ก ํด๊ฒฐํ ์ ์๋ ๋ฌธ์ ๊ฐ ์์์ ๋ณด์ฌ์ฃผ๋ฏ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ์๋ก์ด ๊ฒ์ ๋ง๋ค ์ ๋ฐ์ ์์ต๋๋ค. ์ด๊ฒ์ Future
๊ฐ ์๊ณ ๋์ค์ async/await
๊ตฌ๋ฌธ์ ๋์
ํ๋ ๊ฒ๊ณผ ๋์ผํ ๊ฐ๋
์
๋๋ค. ํ์๋ ์๋ก์ด ๊ตฌ๋ฌธ ์์ด๋ ๋ถ๊ฐ๋ฅํ๋ ์ผ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ฌ๋๋ค์ ์ฐ๋ฆฌ๊ฐ ๊ทธ๊ฒ์ ํ๋ ์์ํฌ์ ์ผ๋ถ๋ก ๋ง๋ค ๊ฒ์ ์ ์ํฉ๋๋ค. React๋ ์ฌ์ฉ ๊ฐ๋ฅํ ์ ์ผํ ํ๋ ์์ํฌ๊ฐ ์๋๊ธฐ ๋๋ฌธ์ Javascript์ ์ ๊ตฌ๋ฌธ์ ์ถ๊ฐํ ์ ์์ต๋๋ค(๋ฐ๋ฒจ ๋ณํ์ ํตํด ๊ฐ๋ฅ). ํ์ง๋ง Dart๋ Flutter(์ต์ํ ์๋ณธ ๋ฒ์ ์ด ์๋ Dart 2)์ ํจ๊ป ์๋ํ๋๋ก ํน๋ณํ ์ค๊ณ๋์์ต๋๋ค. ํํฌ๊ฐ ๊ธฐ๋ณธ ์ธ์ด์ ํจ๊ป ์๋ํ๋๋ก ํ๋ ํจ์ฌ ๋ ๋ง์ ๊ธฐ๋ฅ. ์๋ฅผ ๋ค์ด React๋ JSX์ฉ Babel์ด ํ์ํ๊ณ useEffect
์ค๋ฅ์ ๋ํด ๋ฆฐํฐ๋ฅผ ์ฌ์ฉํด์ผ ํ์ง๋ง ์ปดํ์ผ ์๊ฐ ์ค๋ฅ๋ก ๋ง๋ค ์ ์์ต๋๋ค. ํจํค์ง๊ฐ ์์ผ๋ฉด ์ฑํ์ด ํจ์ฌ ๋ ์ด๋ ค์์ง๋๋ค. React hooks๊ฐ ํ์ฌ ํจํค์ง์๋ค๋ฉด ์ป์ ์ ์์๋ ๊ฒฌ์ธ๋ ฅ์ ์์ํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
ํ์ฌ Stateless ๋ฐ Stateful ์์ ฏ ์ธ์ HookWidget๊ณผ ๊ฐ์ ์ธ ๋ฒ์งธ ์ ํ์ ์์ ฏ์ด ์์ผ๋ฉด ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์ด๋ ๊ฒ์ ์ฌ์ฉํ ์ง ์ปค๋ฎค๋ํฐ๊ฐ ๊ฒฐ์ ํ๊ฒ ํ์ญ์์ค. ์ด๋ฏธ ๋ ๋ฏธ์์ ํจํค์ง๊ฐ ์๊ธด ํ์ง๋ง ์ด์ฉ ์ ์์ด ํ๊ณ๊ฐ ์์ต๋๋ค. ๋๋ ๊ทธ๊ฒ์ ์๋ํ๊ณ ๊ทธ๊ฒ์ ์์ฉ๊ตฌ๋ฅผ ํฌ๊ฒ ์ค์์ง๋ง ์ ํ ๋๋ฌธ์ ๋ถํํ๋ ๊ทธ๊ฒ์ ๋จ์ด ๋จ๋ ค์ผํ์ต๋๋ค. init ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ง ์ํ ์ ์ฅ ์์ ฏ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค. ์ธ์ด ์ง์์ด ํฌํจ๋ ํต์ฌ ํ๋ ์์ํฌ์ ์ผ๋ถ์ธ ๊ฒฝ์ฐ ์ถ๊ฐ๋ก ํฐ ์ด์ ์ด ์์ ์ ์์ต๋๋ค. ๊ฒ๋ค๊ฐ HookWidget์ ์ฌ์ฉํ๋ฉด ์ปค๋ฎค๋ํฐ์์ ๋ ์ต์ ํ๋๊ณ ์ฑ๋ฅ์ด ๋ฐ์ด๋ ์ฑ์ ๋ง๋ค ์ ์์ต๋๋ค.
init ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ง ์ํ ์ ์ฅ ์์ ฏ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
์ค์ ๋ก ์ด๊ฒ์ ํ ํ์๋ ์์ต๋๋ค. useEffect()๋ ๋น๋ ๋ด๋ถ์์ initCall์ ์ํํ ์ ์์ต๋๋ค. ๋ฌธ์๋ ์ด๊ฒ์ ์ค๋ช ํ๊ธฐ ์ํด ์ ํ ๋ ธ๋ ฅํ์ง ์์ผ๋ฉฐ ๊ธฐ๋ณธ์ ์ผ๋ก ๋น์ ์ด ํํฌ์ ์๋ ๋ฐฉ์์ ์ด๋ฏธ ์๊ณ ์๋ React ๊ฐ๋ฐ์๋ผ๊ณ ๊ฐ์ ํฉ๋๋ค.
๊ทธ๋ฐ ์์ผ๋ก ์ฌ์ฉํ๊ณ ์์์ง๋ง ํจํค์ง์ ์ ํ์ผ๋ก ์ธํด ๋ช ๊ฐ์ง ๋ค๋ฅธ ๋ฌธ์ ๊ฐ ์์๊ณ ์ ํํ ๋ฌด์์ด์๋์ง ๊ธฐ์ต๋์ง ์์ต๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
React ๊ด์ ์์ ๋ช ๊ฐ์ง ์๊ฐ์ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
๊ทธ๊ฒ๋ค์ด ๊ด๋ จ์ด ์๋ค๋ฉด ์ฉ์ํ์ง๋ง Hooks์ ๋ํด ์ฐ๋ฆฌ๊ฐ ์ด๋ป๊ฒ ์๊ฐํ๋์ง ๊ฐ๋ตํ๊ฒ ์ค๋ช ํ๊ณ ์ถ์์ต๋๋ค.
ํํฌ๋ ํ์คํ "์จ๊ธฐ๊ธฐ"์ ๋๋ค. ๋๋ ์ด๋ป๊ฒ ๋ณด๋๋์ ๋ฐ๋ผ ์บก์ํํ์ญ์์ค. ํนํ, ๊ทธ๊ฒ๋ค์ ์ง์ญ ์ํ์ ํจ๊ณผ๋ฅผ ์บก์ํํฉ๋๋ค(์ ๋ ์ฐ๋ฆฌ์ "ํจ๊ณผ"๊ฐ "์ผํ์ฉ"๊ณผ ๊ฐ์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค). "์์์ฑ"์ ํธ์ถ๋๋ ๊ตฌ์ฑ ์์์ ์๋ช ์ ์๋์ผ๋ก ์ฒจ๋ถํ๋ค๋ ์ ์ ๋๋ค.
์ด๋ฌํ ๋ด์ฌ์ฑ์ ๋ชจ๋ธ์ ๋ด์ฌ๋์ด ์์ง ์์ต๋๋ค. ๋ชจ๋ ํธ์ถ์ ํตํด ์ธ์๊ฐ ๋ช ์์ ์ผ๋ก ์ค๋ ๋๋๋ ๊ฒ์ ์์ํ ์ ์์ต๋๋ค. ๊ตฌ์ฑ ์์ ์์ฒด์์ ์ฌ์ฉ์ ์ ์ Hook, ๊ฐ ๊ธฐ๋ณธ Hook์ ์ด๋ฅด๊ธฐ๊น์ง ๋ง์ ๋๋ค. ๊ทธ๋ฌ๋ ์ค์ ๋ก ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ด ์๋๋ฝ๊ณ ์ค์ ๋ก ์ ์ฉํ์ง ์๋ค๋ ๊ฒ์ ๋ฐ๊ฒฌํ์ต๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ํ์ฌ ์คํ ์ค์ธ Component๋ฅผ ์์์ ์ ์ญ ์ํ๋ก ๋ง๋ค์์ต๋๋ค. ์ด๊ฒ์ VM์
throw
errorHandlerFrame
๊ฐ ์ฝ๋์์catch
๋ธ๋ก์ ์์ชฝ์ผ๋ก ๊ฒ์ํ๋ ๊ฒ๊ณผ ์ ์ฌํฉ๋๋ค.์ข์ต๋๋ค. ๋ด๋ถ์ ์์์ ์๋ ์ํ๊ฐ ์๋ ํจ์์ ๋๋ค. ์ข์ง ์์ ๊ฒ ๊ฐ์ต๋๊น? ๊ทธ๋ฌ๋ React์์๋ ์ผ๋ฐ์ ์ผ๋ก ๊ตฌ์ฑ ์์๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค. ์ด๊ฒ์ด ์ปดํฌ๋ํธ์ ์์ ์ ๋๋ค. ๊ทธ๊ฒ๋ค์ (UI ํธ๋ฆฌ์ ์์น์ ํด๋นํ๋) ์๋ช ์ด ์ฐ๊ฒฐ๋ ํจ์์ ๋๋ค. ๊ตฌ์ฑ ์์ ์์ฒด๊ฐ ์ํ์ ๊ด๋ จํ์ฌ ๋ฐํ์ด ์๋ ์ด์ ๋ ์์์ ์ฝ๋์์ ๊ตฌ์ฑ ์์๋ฅผ ํธ์ถํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ค๋ฅธ ๊ตฌ์ฑ ์์์์ ํธ์ถํฉ๋๋ค. ๋ฐ๋ผ์ UI ์ฝ๋์ ์ปจํ ์คํธ์ ๋จ์ ์๊ธฐ ๋๋ฌธ์ ์๋ช ์ด ์๋ฏธ๊ฐ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๋ชจ๋ ๋ฌธ์ ๊ฐ ๊ตฌ์ฑ ์์ ํํ์ธ ๊ฒ์ ์๋๋๋ค. ๊ตฌ์ฑ ์์๋ ์ํ+ํจ๊ณผ์ ๋๋ฌด ์์น์ ์ฐ๊ฒฐ๋ ์๋ช ์ด๋ผ๋ ๋ ๊ฐ์ง ๋ฅ๋ ฅ์ ๊ฒฐํฉํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ์ฒซ ๋ฒ์งธ ๋ฅ๋ ฅ์ด ๊ทธ ์์ฒด๋ก ์ ์ฉํ๋ค๋ ๊ฒ์ ๋ฐ๊ฒฌํ์ต๋๋ค. ํจ์๊ฐ ์ฝ๋๋ฅผ ์บก์ํํ ์ ์๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ์ ์ผ๋ก ์ ์ฉํ๋ฏ์ด ํธ๋ฆฌ์ ์ ๋ ธ๋๋ฅผ ์์ฑํ์ง ์๊ณ ๋ ์ํ+ํจ๊ณผ ๋ฒ๋ค์ ์บก์ํ(๋ฐ ์ฌ์ฌ์ฉ)ํ ์ ์๋ ๊ธฐ๋ณธ ์์๊ฐ ๋ถ์กฑํ์ต๋๋ค. ๊ทธ๊ฒ์ด ๋ฐ๋ก Hooks์ ๋๋ค. ๊ตฌ์ฑ ์์ = ํํฌ + ๋ฐํ๋ UI.
๋ด๊ฐ ์ธ๊ธํ๋ฏ์ด ์ปจํ ์คํธ ์ํ๋ฅผ ์จ๊ธฐ๋ ์์์ ํจ์๋ ๋ฌด์ญ์ต๋๋ค. ์ด๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ๋ฆฐํฐ๋ฅผ ํตํด ๊ท์น์ ์ํํ๋ ์ด์ ์ ๋๋ค. Hook์๋ "์์" ์ด ์์ต๋๋ค. Hook์ ์ฌ์ฉํ๋ฉด ํจ์๋ Hook์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฆฐํฐ๋ ์ปดํฌ๋ํธ๋ ๋ค๋ฅธ Hooks๋ง์ด Hooks๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ๊ฐ์ ํฉ๋๋ค. ์ด๊ฒ์ ์ด์ ๊ตฌ์ฑ ์์ ์์ฒด๋ณด๋ค ๋ ์์์ ์ด์ง ์๊ธฐ ๋๋ฌธ์ ์ปจํ ์คํธ UI ์ํ๋ฅผ ์จ๊ธฐ๋ ์์ ํจ์์ ๋ฌธ์ ๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
๊ฐ๋ ์ ์ผ๋ก ์ฐ๋ฆฌ๋ Hook ํธ์ถ์ ์ผ๋ฐ ํจ์ ํธ์ถ๋ก ๋ณด์ง ์์ต๋๋ค.
useState()
๋ ๊ตฌ๋ฌธ์ด ์๋ ๊ฒฝ์ฐuse State()
์ ๋๋ค. ๊ทธ๊ฒ์ ์ธ์ด ๊ธฐ๋ฅ์ด ๋ ๊ฒ์ ๋๋ค. ํจ๊ณผ ์ถ์ ๊ธฐ๋ฅ์ด ์๋ ์ธ์ด์์ ๋์ ํจ๊ณผ๊ฐ ์๋ Hooks์ ๊ฐ์ ๊ฒ์ ๋ชจ๋ธ๋งํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ์๋ฏธ์์ ๊ทธ๊ฒ๋ค ์ ์ผ๋ฐ ํจ์์ด์ง๋ง State๋ฅผ "์ฌ์ฉ"ํ๋ค๋ ์ฌ์ค์ ํ์ ์๋ช ์ ์ผ๋ถ๊ฐ ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฐ ๋ค์ React ์์ฒด๋ฅผ ์ด ํจ๊ณผ์ ๋ํ "์ฒ๋ฆฌ์"๋ก ์๊ฐํ ์ ์์ต๋๋ค. ์ด์จ๋ ์ด๊ฒ์ ๋งค์ฐ ์ด๋ก ์ ์ด์ง๋ง ํ๋ก๊ทธ๋๋ฐ ๋ชจ๋ธ์ ๊ด์ ์์ ์ ํ ๊ธฐ์ ์ ์ง์ ํ๊ณ ์ถ์์ต๋๋ค.์ค์ฉ์ ์ธ ์ธก๋ฉด์์ ์ฌ๊ธฐ์๋ ๋ช ๊ฐ์ง๊ฐ ์์ต๋๋ค. ์ฒซ์งธ, Hooks๊ฐ React์ "์ถ๊ฐ" API๊ฐ ์๋๋ผ๋ ์ ์ ์ฃผ๋ชฉํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ๊ทธ๋ค์์ด ์์ ์์ ๊ตฌ์ฑ ์์๋ฅผ ์์ฑํ๊ธฐ์ํ API ๋ฐ์์ ๋๋ค. ๋๋ ๊ทธ๋ค์ด ์ถ๊ฐ ๊ธฐ๋ฅ์ผ๋ก์ ๊ทธ๋ค์ง ๋งค๋ ฅ์ ์ด์ง ์์ ๊ฒ์ด๋ผ๋ ๋ฐ ๋์ํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋ฐ๋ผ์ ํ๋ฆผ์์ด ๋ค๋ฅธ ์ ์ฒด ํจ๋ฌ๋ค์์ ๊ฐ์ง Flutter์ ๋ํด ๊ทธ๋ค์ด ์ ๋ง๋ก ์๋ฏธ๊ฐ ์๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๊ทธ๊ฒ๋ค์ด ํ์ฉํ๋ ๊ฒ์ ๊ดํด์๋, ํต์ฌ ๊ธฐ๋ฅ์ ์ํ+์ ํจ ๋ก์ง์ ์บก์ํํ ๋ค์ ์ผ๋ฐ ํจ์ ๊ตฌ์ฑ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ํจ๊ป ์ฐ๊ฒฐํ๋ ๊ธฐ๋ฅ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ํ๋ฆฌ๋ฏธํฐ๋ธ๋ ๊ตฌ์ฑํ๋๋ก ์ค๊ณ๋์๊ธฐ ๋๋ฌธ์
useState()
์ ๊ฐ์ ์ผ๋ถ ํํฌ ์ถ๋ ฅ์ ๊ฐ์ ธ์์ ์ฌ์ฉ์ ์ ์useGesture(state)
์ ๋ํ ์ ๋ ฅ์ผ๋ก ์ ๋ฌํ ๋ค์ ์ด๋ฅผ ์ฌ๋ฌ ์ฌ์ฉ์ ์ ์useSpring(gesture)
์ ๋ ฅ์ผ๋ก ์ ๋ฌํ ์ ์์ต๋๋ค. ์์ฐจ ๊ฐ์ ์ ๊ณตํ๋ ๋ฐ๋ชจ ์ Hooks๊ฐ ๋ฌด์์ธ์ง ๊ฐ๋ตํ๊ฒ ์์ฝํ ๊ธฐ์ฌ ์ ๋๋ค.๋๋ ์ด๊ฒ์ด ์์ฉ๊ตฌ๋ฅผ ์ค์ด๋ ๊ฒ์ด ์๋๋ผ ์ํ ์ ์ฅ ์บก์ํ๋ ๋ก์ง์ ํ์ดํ๋ผ์ธ์ ๋์ ์ผ๋ก ๊ตฌ์ฑํ๋ ๋ฅ๋ ฅ์ ๊ดํ
์ด๊ฒ์ด ์กฐ๊ธ์ด๋ผ๋ ๋์์ด ๋์๋์ง๋ ๋ชจ๋ฅด๊ฒ ์ง๋ง ํ๋ก๊ทธ๋๋ฐ ๋ชจ๋ธ์ ๋ํ ๊ด์ ์ ์กฐ๊ธ์ด๋ผ๋ ๋ฒ์ด๋๊ธธ ๋ฐ๋๋๋ค.
๋ค๋ฅธ ์ง๋ฌธ์ ๋๋ตํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค.