본문 바로가기
Study/Flutter

[Flutter] 초기 프로젝트 Application 이해하기

 

초기 Flutter Project를 시작하면, 

위와 같이 작성된 앱을 만들어 제공해준다.

 

처음부터 이 App을 이해하기란 쉽지 않지만,

하나씩 살펴보며 배워보자.

 

1. 프로젝트 구조

 

프로젝트의 구조를 살펴보면,

  1. 개발이 이루어지는 lib 폴더 
  2. 테스트를 진행하는 test 폴더
  3. 플랫폼별 빌드와 배포가 이루어지는 build , andriod, ios 가 존재한다.

 

이중에서 초보인 우리는 lib폴더와 최상위에 존재하는 pubspec.yaml 을 가장많이 사용하고 수정하게 된다.

실질적인 라이브러리들은 Extenal Libraries에 존재한다.

 

2. pubspec.yaml

pubspec.yaml 은 gradle 이나 maven 처럼

패키지 모듈을 설치하고, 버전에 의존성 등을  관리해주는 설정파일입니다.

name: <APP_NAME>
description: A new Flutter project.

# 다음은 앱 버전 및 빌드 번호를 정의합니다.
# 버전은 점으로 구분된 세개의 숫자입니다. (예: 1.2.43) 
# 그 다음 빌드 번호가 `+` 뒤에 표시됩니다. (옵션입니다.)
# 버전과 빌드 번호는 각각 --build-name과 --build-number를 지정하여 오버라이딩할 수 있습니다.
# semver.org에서 버전관리에 대해 자세히 읽어보세요.
version: 1.0.0+1

environment:
  sdk: '>=2.0.0-dev.68.0 <3.0.0'

dependencies:
  flutter:
    sdk: flutter

  # 다음은 앱에 Cupertino 아이콘 폰트를 추가합니다.
  # iOS 스타일 아이콘으로 CupertinoIcons 클래스를 이용해서 사용하세요.
  cupertino_icons: ^0.1.2

dev_dependencies:
  flutter_test:
    sdk: flutter

# 이 파일의 일반적인 Dart에 관한 내용은 다음 페이지를 참고하세요.
# https://www.dartlang.org/tools/pub/pubspec

# 아래 내용은 플러터에만 해당합니다.
flutter:
  # 다음 라인은 머티리얼 아이콘 폰트가 앱에 포함됨을 의미하며 
  # 머티리얼 아이콘의 Icons 클래스를 사용할 수 있습니다.
  uses-material-design: true
  # 앱에 에셋을 추가하려면 다음과 같이 에셋 섹션을 추가하세요.
  # assets:
  #  - images/a_dot_burr.jpeg
  #  - images/a_dot_ham.jpeg
  # 이미지 에셋은 하나 이상의 해상도별 종류를 참조할 수 있습니다.
  # https://flutter.io/assets-and-images/#resolution-aware.
  # 패키지 의존성에 에셋을 추가하는 방법에 대한 자세한 내용은 아래 주소를 확인하세요.
  # https://flutter.io/assets-and-images/#from-packages
  # 앱에 사용자정의 폰트를 추가하려면 이 "flutter" 섹션에 폰트 섹션을 추가하세요.
  # 이 목록의 각 항목에는 폰트 패밀리 이름이 있는 "family" 키와 폰트의 에셋 및 
  # 기타 설명을 포함하는 "fonts" 키가 있어야합니다. 예를 들어,
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # 패키지 의존성의 폰트에 대한 자세한 내용은 아래 링크를 참조하세요.

 기본 제공된 파일의 설명을 번역한 내용이니

부분부분 무엇을 설정하는건지 궁금하신 경우 확인하시기 바랍니다.

 

우리가 배포하는 앱의 패키지 name, version, desc , author (이름, 버전정보, 설명, 만든이 ) 등등  정보들....

의존하는 외부 라이브러리, 개발용 라이브러리,

플러터 안에서 사용되는 assets (이미지, 폰트, 미디어 파일 등

사용하고 관리하는 파일입니다.

 

해당 파일에 dependencies에 외부모듈 사용을 작성하고나서

프로젝트 안에서 사용하기 위해서는 반드시 pub get 이 진행되야 합니다.

저기 위치에 pub get을 명령할 수 있다

해당 파일에 내용을 수정하고나면

위와같이 pub get 을 통해 수정사항에 대한 반영을 꼭 해주어야 합니다.

 

 

3. main.dart

초기 프로젝트에서 앱의 전체적인 동작내용이 코딩된 부분입니다.

 main.dart 전문 보기

더보기
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  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(
        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.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

 

main.dart 는 가장 먼저 실행되는 main메소드와, stful 위젯과  stless 위젯 ( 다음글에서 다룰 예정 )

이렇게 크게 세 가지 부분으로 나눌 수 있다.

 

1)  main 메소드

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

앱이 실행되면 가장 먼저  main 메소드가 실행됩니다. (약속된 규칙)

메인 메소드는 runApp 함수를 통해서 아래에 작성되있는 MyApp() 클래스를 기동합니다.

이제 main에 의해서 호출되는 MyApp을 살펴보겠습니다.

 

 

2) MyApp (메인 앱)

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

먼저 앱의 구조를 보면,

MyApp 클래스 안에, 특정 화면에 대한 키가 명시되어있고                     (Navigator 화면의 전환을 위해 약속된 Key 부분)

재정의된 build 메소드와                             (앱의 실행에서 생명주기상에 가장 중요한 메소드로 UI코드가 작성되는 부분)

그 안에서 호출되는 MaterialApp에 하위에 앱 테마와 home 화면에 연결되어있다.                           (여기가 중요한 부분)

 

 

초기 프로젝트의 UI에 최상단에는 일반적으로 MaterialApp Widget이 사용됩니다.

가장 최상단인 해당 위젯에 앱의 전제적인 테마도 지정하며, 화면의 구성과, 라우팅, 초기화면을 연결합니다.

 

여기서는 home 옵션에 MyHomePage가 연결되어 있습니다.

 

 

3) MyHomePage 

이제 아래 기본 프로젝트에서 해당 부분을 살펴보겠습니다.

여기 화면에서는 앱의 상태관리에 대한 중요한 부분이 등장하는데요, 

StateFulWidgetStateLessWidget의 차이점을 알아야합니다. (이 글에서는 다루지 않겠습니다)

 

간략히  설명하자면, 앱의 상태관리란,

인터렉티브하게 사용자의 행동에 따라 값, UI, 화면등의 변화를 관리하는 것을 상태관리하고 말합니다.

그 상태를 즉각적으로 반영시켜주한 기본적인 방법으로  StateFulWidget + setState() 라는 메소드가 있으며,

StateFulWidget 하위에서 setState 메소드에 의해 변화된 부분은 즉각적인 reBuild되어

앱의 상태변화를 반영해줍니다. 

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      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.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

여기서는 Floation버튼을 누르면 연결된 _incrementCounter 메소드가 호출되는데

작성된 메소드안을 보면, setState가 있음을 알 수 있다.

setState 메소드가 호출되면,

변화를 감지하여 앱의 화면이 순식간에 reBuild되므로 앱화면 사용자에 클릭에 바로 변경됨을 확인할 수 있다. 

 

초기 프로젝트에서는

프로젝트의 디렉토리구조와  pubSpec파일과,  초기 앱의 구성, 그리고 상태관리에 대한 개념을 잘 이해하면 된다. 

 

 

https://bangu4.tistory.com/312

 

[Flutter] 앱 생명주기와 Stateful , Stateless

앱을 구성하는 하나의 클래스를 만들때, 우리는 그 위젯의 속성의 따라  Stateful , Stateless 두가지 종류의 클래스를 만들 수 있다. Stateless 는 변경 불가능 하며, 모든 값이 final 상수지만, 반면, State

bangu4.tistory.com