이 글에서는 Flutter가 어떤 방식으로 앱을 실행하고, main.dart
가
어떤 역할을 하는지를 천천히, 실제 흐름에 맞춰 설명해보겠습니다.
특히 상태 관리(StatefulWidget), setState()
, build()
같은 핵심 개념을
코드 흐름과 함께 시각적으로 풀어갈 예정입니다.
이제 본격적으로 시작해볼까요?
프로젝트 생성
flutter create my_app
생성되는 구조는 다음과 같습니다:
my_app/
┣ android/ ▶ 안드로이드 프로젝트 파일
┣ ios/ ▶ iOS 프로젝트 파일
┣ lib/
┃ ┗ main.dart ▶ 프로젝트 시작점
┣ test/ ▶ 테스트 파일
┗ pubspec.yaml ▶ 의존성, 보안성, 이어서 레퍼런스 가져오기
Android Studio에서 Flutter 프로젝트 만들기
Flutter은 보통 Android Studio를 이용해 활용하는 경우가 많아요:
- Android Studio >
New Flutter Project
- Flutter SDK path 설정 (ex.
/Users/yourname/fvm/versions/3.13.9
) - Project name, org domain, platform target 설정
- Finish
이 과정을 거치면, Android Studio가 flutter create
명령과 같은 결과를 자동으로 처리하고
가장 기본적인 Flutter 가이드와 같은 형식의 프로젝트를 만들어줍니다.
이렇게 해서 프로젝트가 만들어졌습니다.
이제 우리가 가장 많이 마주치게 될 파일, main.dart
를 함께 살펴보겠습니다.
이 파일이 Flutter 앱의 시작점이며, 전체 구조를 이해하는 데 가장 중요한 부분이니까요.
main.dart
구조의 이해
기본 CounterApp 소스 예제
main.dart
는 Flutter 앱의 진입점(entry point)이며, 일반적으로 아래와 같은 기본 구조로 구성됩니다:
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
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'),
);
}
}
핵심 구성 요소 설명
main()
함수: 앱이 시작될 때 가장 먼저 실행되는 함수로,runApp()
함수를 통해 Flutter 앱을 실행합니다.runApp(MyApp())
: 전체 앱의 루트 위젯을 등록합니다.MyApp
클래스: StatelessWidget을 상속받은 클래스이며, 앱 전체에서 사용할MaterialApp
을 반환합니다.MaterialApp
: Flutter에서 제공하는 가장 기본적인 앱 뼈대이며, 테마, 라우팅, 지역화 등의 기능을 포함합니다.home
: 앱이 시작할 때 가장 처음 보여줄 위젯을 지정합니다. 여기서는MyHomePage
가 해당됩니다.
추가로, MyApp
이 StatelessWidget
을 상속받았다는 것은
이 위젯이 상태 변화 없이 동일한 UI를 유지한다는 의미입니다.
즉, 이 화면은 한 번 그려지면 다시 그려질 일이 없는 구조입니다.
위에서 home: const MyHomePage(title: 'Flutter Demo Home Page')
에 연결된 위젯이
실제 어떤 구조로 구성되어 있는지 확인해보면, 아래와 같은 StatefulWidget 기반의 카운터 앱이 기본으로 포함되어 있습니다:
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
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),
),
);
}
}
위 코드는 기본적으로 StatefulWidget을 활용하여 카운터 기능을 구현한 예제입니다.
MyHomePage
: MyHomePage는 StatefulWidget이라는 “껍데기”예요.
Stateful 이기때문에 이 화면은 내용이 변경될 수 있는 홤녀임을 알 수 있습니다.
이 클래스를 통해 이 위젯은 _MyHomePageState
라는 상태를 갖고 있다고 알려주고 있습니다.
이 state를 통해 UI에 어떤 변화가 있을 수 있는지, 그리고 그걸 누가 관리할 건지를 정의하는 설계도를 알 수 있는거죠.
createState() 메서드에서 반환한 _MyHomePageState()
가 실제로 앱의 상태와 UI를 관리하는 state입니다.
🧭 Flutter 앱이 처음 실행될 때, 화면이 그려지는 과정
- main() 함수 실행
→ 앱의 진입점. 여기서 runApp(MyApp())을 호출함 - MyApp 위젯 생성
→ StatelessWidget이라 build()가 한 번 실행되어 MaterialApp을 반환함 - MaterialApp이 home으로 지정한 MyHomePage 생성
→ MyHomePage는 StatefulWidget이므로… - createState() 실행 → _MyHomePageState 생성
→ State 객체가 만들어짐
이제 _MyHomePageState
라는 state를 살펴보겠습니다.
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
// ... 생략
body: Center(
// ... 생략
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment'
child: const Icon(Icons.add),
),
) // Center
); // Scaffold
}
)
이 state는 내부에 build()
가 호출될 때마다 UI가 갱신됩니다.
이 화면에는 상단부터 차례로 아래처럼 구성되어있습니다.
- AppBar
- Text : 'You have..'문구
- Text : 현재 카운트
- 버튼 : 버튼을 누르면
_incrementCounter
함수가 실행됩니다.
3. 카운트 표시 텍스트
는 내부변수 _counter 의 값을 바라보고 있습니다. 최초에 0이기 때문에 화면에 표시되는 숫자는 0입니다.
일단 최초에 먼저 initState()를 통해 state가 생성되고 최초 상태에 따라 build()를 자동호출합니다.
화면을 살펴보면 화면을 변화시킬수있는 요인이 있는데, 여기선 트리거가 버튼입니다.
- 사용자가 버튼을 누름 (예: FloatingActionButton)
- onPressed: _incrementCounter 실행됨
- _incrementCounter() 안에서 setState() 호출됨
- setState()는 Flutter에게 “상태가 바뀌었어요!”라고 알림
- Flutter는 해당 위젯의 build() 함수를 자동으로 다시 호출함
- 새 상태값에 따라 화면이 다시 그려짐
지금까지 Flutter 프로젝트의 구조와 실행 흐름을 따라가며,main.dart
와 StatefulWidget
, setState()
의 작동 원리에 대해 알아봤습니다.
다음 글부터는 본격적으로 Flutter UI의 기본 단위인 ‘위젯(Widget)’에 대해 다룰 예정입니다.
Flutter 앱의 모든 화면은 위젯들로 구성되며, 이 구조를 이해하는 것이 Flutter를 잘 다루는 첫걸음이기 때문이죠.
StatelessWidget과 StatefulWidget을 포함한 기초 위젯 개념과 예시 코드를 간단하게 살펴보며,
어떤 식으로 화면이 구성되고 동작하는지 자연스럽게 익혀갈 수 있도록 구성해보겠습니다.
👉 계속해서 이 시리즈를 따라오신다면, Flutter에 대한 감각이 빠르게 잡힐 거예요!
'모바일 앱개발 > Flutter' 카테고리의 다른 글
Flutter 설치하기 (mac, fvm, 안드로이드 스튜디오) (0) | 2025.06.16 |
---|---|
4년 차 iOS 개발자, 다시 Flutter를 배우는 이유 (2) | 2025.06.10 |
플러터 - 삼각형 모양 View 그리기 (0) | 2023.06.11 |
(Flutter) Mac OS 플러터 닥터 설정 및 프로젝트 생성하고 에뮬레이터에서 실행해 보기(4) (0) | 2021.09.17 |
(Flutter) 안드로이드 스튜디오, 비주얼 스튜디오 코드, 에뮬레이터 설치하기(3) (0) | 2021.09.15 |
(Flutter) SDK설치와 환경변수 설정하기 (2) (0) | 2021.09.15 |
(Flutter) 우리는 왜 플러터를 학습해야할까? (1) (0) | 2021.09.14 |