(Flutter-기초 강의) 5. 프로젝트 생성 및 기본구조

Flutter를 배우기에 앞서 두 포스팅(3. Dart 소개, 4. Dart 필수 문법 및 동작의 이해)을 통해 Dart 언어의 기본적인 로직과 문법에 대해 익혔고, 이제 본격적으로 Flutter에 대한 강의를 진행하고자 합니다.

먼저 Flutter CLI를 통해 프로젝트를 생성하고 기본으로 생성되는 프로젝트 구조 및 구성에 대해 알아보겠습니다.

프로젝트 생성

CMD창에서 Flutter CLI의 flutter create <project_name> 을 이용하여 새로운 프로젝트를 생성합니다.
본 예제에서는 <project_name>_1_create_project_로 대체합니다.

다음 명령어를 통해 생성한 프로젝트로 이동하고, 실행해 볼 수 있습니다.

  $ cd _1_create_project
  $ flutter run

허나 우리는 Visual Studio Code를 사용중이므로 VS Code하단 상태바의 우측에서 Emulator를 선택하여 실행한 후
F5를 눌러 Debug를 통해 실행합니다.

select-emulator-1
select-emulator-2

그럼 다음과 같이 기본 Count Application이 실행됩니다.

start-debug

프로젝트 구조

여러 폴더 및 파일들이 생성되지만 주요 구조를 확인하면 다음과 같습니다.

.
├── android
│   ├── app
│   │   ├── build
│   │   │   ├── app
│   │   │   ├── generated
│   │   │   └── res
│   │   ├── lib
│   │   │   └── main.dart
│   │   └── src
│   │       └── main.dart
│   └── build.gradle
├── ios
│   ├── Runner
│   │   ├── Assets.xcassets
│   │   ├── Info.plist
│   │   ├── Runner.xcodeproj
│   │   └── Runner.xcworkspace
│   └── Runner.podspec
├── lib
│   └── main.dart
├── test
├── pubspec.lock
└── pubspec.yaml

폴더 설명

  • android 폴더: Android용 빌드 파일 및 코드를 포함합니다.
  • ios 폴더: iOS용 빌드 파일 및 코드를 포함합니다.
  • lib 폴더: Flutter 애플리케이션의 Dart 코드를 포함합니다.
  • test 폴더: dart 코드로 테스트할 때 사용하는 파일들을 포함합니다.

파일 설명

  • main.dart 파일: Flutter 애플리케이션의 진입점입니다. 이 파일은 애플리케이션의 초기화 및 실행을 담당합니다.
  • pubspec.lock 파일: 프로젝트의 종속성 버전을 잠급니다. 이 파일은 프로젝트의 종속성을 재설치할 때 사용됩니다.
  • pubspec.yaml 파일: 프로젝트의 종속성을 정의합니다. 이 파일은 프로젝트에 필요한 라이브러리를 정의합니다.

main.dart

모든 dart app은 main()로부터 시작하는데, flutter의 기본 프로젝트의 경우 main.dart안에 main() 에서 시작합니다.

다음과 같이 import 키워드를 이용하여 구글에서 개발한 디자인인 Material 패키지를 import 합니다.

import 'package:flutter/material.dart';

다음 main()는 application의 진입점 역할을 하는 함수 입니다.

본 함수에서는 MyApp이라는 Widget을 전달하여 화면에 표시하였습니다.

void main() {
  runApp(const MyApp());
}

MyApp class 는 화면에 표시될 Widget으로 Stateless Widget을 상속하여 상태가 변경되지 않는 Widget입니다.

build() 함수를 override하여 항상 MaterialApp() 을 반환하여 표시해야 합니다.

따라서 main()에서 표시하기로 한 MyAppMaterialApp()을 반환하고,

MaterialApp()에서는 타이틀, 테마, 홈 widget을 설정했습니다.

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),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

그리고 MyHomePage는 앞서 상태가 변경되지 않는 MyApp과 달리 숫자를 카운팅하여 상태가 변경되는 Widget으로 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),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

StatefulWidget과 StatelessWidget에 대해서는 이후 설명하도록 하겠습니다.

참고 링크

Leave a Comment