
vscode에서 flutter project를 실행하게 되면 간단한 counter 프로그램이 실행된다.
위 프로그램이 정석적인 틀에 맞춰 코딩되었다고 생각해 분석해보기로 했다.
튜터님의 조언과 google AI, Gemini의 힘을 빌렸다.
void main() {
runApp(const MyApp());
}
main 함수는 프로그램이 어디서부터 시작해야 할 지에 대한 명확하고 유일한 지시를 내린다.
flutter 프레임워크는 main 함수에서 runApp() 함수를 호출한다.
여러개의 main 함수가 존재하면, 런타임이 어떤 함수를 앱의 시작점으로 해석하는데에 문제(충돌 발생)가 생긴다.
이번에는 컴파일러 관점에서 바라보았다.
Dart 컴파일러는 프로그램의 시작 주소를 main 함수로 지정한다.
또, flutter 앱이 빌드되어 android와 iOS 네이티브 앱으로 패키징 될 때 OS는 단 하나의 시작지점만 찾는다.
따라서 flutter는 main 함수를 시작지점으로 지정하기에 하나만 존재해야 한다.
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
시작지점에 있는 MyApp class를 찾아왔다.
compose를 공부할 때는 볼 수 없었던 StatelessWidget을 상속받는 부분이 보인다.
알아본 결과, StatelessWidget은 말 그대로 상태를 바꿀 수 없는 위젯을 의미하고, StatefulWidget은 상태 변경이 가능한 위젯을 의미한다.
여기서 상태는 compose와 동일하게 "변하는 데이터"를 의미하는 듯 하다.
Gemini는 build 메서드를 위젯의 설계도 정도로 설명한다.
build는 현재 위젯이 화면에 어떻게 표시되어야 하는지를 flutter 프레임워크에게 설명하는 위젯 트리(Widget Tree)를 반환하는 함수이다.
결국 flutter project는 Element, Widget Tree, Widget으로 구성되는데 이 부분은 나중에 공부해봐야겠다.
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
State<MyHomePage> createState() => _MyHomePageState();
}
final은 변수가 선언될 때나 런타임(컴파일 후 프로그램이 실행 중) 값이 정해지며, 이후 변경할 수 없는 상수를 의미한다.
const는 완전 상수를 의미하는 키워드다.
final 키워드와 다르게 const는 컴파일 시점에 값이 할당되며, 값이 고정된다.
또, 값이 같다면 같은 메모리를 사용한다.
final보다 더 깊은 의미의 상수를 의미한다.
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
데이터의 상태를 담고 있고, 값을 증가시키는 로직을 보고 viewmodel과 상당히 유사하다는 생각이 들었다.
또, setState() 함수를 통해 상태 변경을 flutter 프레임워크에 알린다.
build 메서드가 이부분을 인지하고, ui를 업데이트 한다는데 이부분은 공부가 조금 더 필요할 것 같다.