Flutter macOS Desktop App 만들기 #1번

나의 첫번째 macOS Desktop App 만들기 #1번 


Flutter macOS Desktop App 만들고자 합니다. 

[첨고] 모든 자료  구글 디벨로퍼스 Code labs에 Flutter 첫 앱 만들기의 내용을 재 구성 및 정리하였습니다. 원문은 아래 링크 입니다. 



1. 목표 

구글개발자 Code Lab에서 아래 사항을 배울수 있다고 되어 있었습니다. 

  • 플러터 작동의 기본기 익히기 
  • 플러터 레이아웃 생성하기 
  • 유저 인터페이스 컴포넌트 만들기 및 기능 연결하기 ( 버튼 및 버튼 누르기 등 ) 
  • 플러터 소스코드 Keeping your Flutter code organized
  • 화면 사이즈 변화에 따라 바뀌는 반응형 앱만들기
  • 앱의 정확한 룩앤필 만들기 

제가 이번 블로그 글에서 목표로 하는건 hello world 출력 할수 있는 macOS Desktop APP 인데 제시된 목표 UI는 아래 모습이므로 조금 더 완성된 형태의 모습의 앱을 간단히 만들어 내도록 할려고 합니다. 

언제나 새로운 랭귀지 새로운 개발 방식을 사용하게 되면 제일 힘든게 개발환경 구성하고 간단한 앱 정도를 한번만 만들어 가는게 제일 힘드니까. 간단하게만 구현 해보면 그 다음 부터는 전부 문제 해결을 통해서 그때 그때 마다 필요한 기능들만들어  살을 붙여나가면 되니 Toy 프로젝트 수준의 간단한 어플들은 이후는 그렇게 개발이 힘들진 않을꺼라 생각합니다.  


2. App UI 

     제시된 App의 UI는 아래의 모양이었습니다. 기초적인 모습인데 기본적으로 모두 셋으로 deploy가 될테니 프로젝트 생성학 몇가지 손만 보로 바로 배포하면 될테니 별로 할일은 없을꺼 같네요. 








    아래 부터 진행 사항은 Visual Stuido Code 설치 및 Flutter SDK 설치 그리고 개발 환경 구성을 완료한 이후 진행이 되는 내용입니다. 
     Visual Stuido Code 설치 및 Flutter SDK 설치 그리고 개발 환경 구성이 안되었다면  아래 링크를 클릭해서 먼저 개발 환경 구성을 완료 하고 오시기 바랍니다. 




    3. 프로젝트 생성하기 


    VSC를 실행합니다.     키를 눌러서 command  팔레트를 열고 flutter 타이핑 해서 아래와 같이 flutter new project를 선택하여 엽니다. 




    application 생성을 선택 하고 폴더 선택해주고 프로젝트명을 넣어서 새로운 프로젝트를 생성 합니다. 아래 질문 사항이 나오면 Yes 클릭하고 승인 해줍니다. 








    아래 그림과 같이 새로운 Flutter Application 프로젝트가 생성 됩니다. 




    그리고 저 같은 경우는 프로젝트 생성 폴더를 development 폴더로 선택 해주어서 아래와 같이 development 폴더 아래 프로젝트명 ( flutter_app_test1 )의 폴더가 생성되고 자동으로 필요한 모든 것들이 생성되었습니다. 아래 그림 참조하세요. 안드로이드 스튜디오로 Flutter SDK를 셋팅하고 테스트 앱을 최초로 만들었을때와 똑같았습니다. 모든게 자동으로 모두 셋팅 및 생성이 되네요. IDE와 SDK를 써서 개발해서 요즘은 정말 편하게 개발 하네요. 




    4. 설정파일 수정하기 

    1) pubspec.yaml 파일 수정하기 


    VS Code에서 아래 그림의 pubspec.yaml 을 아래 제시된 코드들로 변경하여주시기 바랍니다. 




    pubspec.yaml  아래 코드에서 붉은 색 부분을 비교 해보시고 다른게 있으면 아래 코드로 변경해주시기 바랍니다. 



    name: namer_app
    description
    : A new Flutter project.

    publish_to
    : 'none' # Remove this line if you wish to publish to pub.dev

    version
    : 0.0.1+1

    environment
    :
      sdk
    : ^3.1.1

    dependencies
    :
      flutter
    :
        sdk
    : flutter

      english_words
    : ^4.0.0
      provider
    : ^6.0.0

    dev_dependencies
    :
      flutter_test
    :
        sdk
    : flutter

      flutter_lints
    : ^2.0.0

    flutter
    :
      uses
    -material-design: true



    위 사항을 저 같은 경우는 파일 통채로 내용을 모두 변경하진 않고 기존 소스코드에 붉은색 색깔 부분의 글자만 변경 반영하니 pubspec.yaml 파일의 내용이 아래와 같이 되었습니다. 

    name: namer_app
    description: A new Flutter project.

    # The following line prevents the package from being accidentally published to
    # pub.dev using `flutter pub publish`. This is preferred for private packages.
    publish_to: 'none' # Remove this line if you wish to publish to pub.dev

    # The following defines the version and build number for your application.
    # A version number is three numbers separated by dots, like 1.2.43
    # followed by an optional build number separated by a +.
    # Both the version and the builder number may be overridden in flutter
    # build by specifying --build-name and --build-number, respectively.
    # In Android, build-name is used as versionName while build-number used as versionCode.
    # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
    # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
    # Read more about iOS versioning at
    # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
    version: 1.0.0+1

    environment:
      sdk: ^3.1.1

    # Dependencies specify other packages that your package needs in order to work.
    # To automatically upgrade your package dependencies to the latest versions
    # consider running `flutter pub upgrade --major-versions`. Alternatively,
    # dependencies can be manually updated by changing the version numbers below to
    # the latest version available on pub.dev. To see which dependencies have newer
    # versions available, run `flutter pub outdated`.
    dependencies:
      flutter:
        sdk: flutter

      english_words: ^4.0.0
      provider: ^6.0.0

      # The following adds the Cupertino Icons font to your application.
      # Use with the CupertinoIcons class for iOS style icons.
      cupertino_icons: ^1.0.2

    dev_dependencies:
      flutter_test:
        sdk: flutter

      # The "flutter_lints" package below contains a set of recommended lints to
      # encourage good coding practices. The lint set provided by the package is
      # activated in the `analysis_options.yaml` file located at the root of your
      # package. See that file for information about deactivating specific lint
      # rules and activating additional ones.
      flutter_lints: ^2.0.0

    # For information on the generic Dart part of this file, see the
    # following page: https://dart.dev/tools/pub/pubspec

    # The following section is specific to Flutter.
    flutter:

      # The following line ensures that the Material Icons font is
      # included with your application, so that you can use the icons in
      # the material Icons class.
      uses-material-design: true

      # To add assets to your application, add an assets section, like this:
      # assets:
      #   - images/a_dot_burr.jpeg
      #   - images/a_dot_ham.jpeg

      # An image asset can refer to one or more resolution-specific "variants", see
      # https://flutter.dev/assets-and-images/#resolution-aware.

      # For details regarding adding assets from package dependencies, see
      # https://flutter.dev/assets-and-images/#from-packages

      # To add custom fonts to your application, add a fonts section here,
      # in this "flutter" section. Each entry in this list should have a
      # "family" key with the font family name, and a "fonts" key with a
      # list giving the asset and other descriptors for the font. For
      # example:
      # 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
      #
      # For details regarding fonts from package dependencies,
      # see https://flutter.dev/custom-fonts/#from-packages



    2) analysis_options.yaml 파일 수정하기 


    해당 파일의 내용을 아래 소스코드와 동일하게 변경해주세요. 


    include: package:flutter_lints/flutter.yaml

    linter
    :
      rules
    :
        avoid_print
    : false
        prefer_const_constructors_in_immutables
    : false
        prefer_const_constructors
    : false
        prefer_const_literals_to_create_immutables
    : false
        prefer_final_fields
    : false
        unnecessary_breaks
    : true
        use_key_in_widget_constructors
    : false


    위 파일은 Fluttter 코드 분석기에게 얼마나 보수적으로 강하게 코드분석을 하게 할지 정하는 부분입니다. 간단한 앱을 바로만드는 상황이어서 코드 분석 수준을 최대한 약하게 하였습니다. 해당 부분은 해당 파일의 위 옵션들을 수정 하실수 있습니다. 현재 설정 수준 이상의 보수적으로 꼼꼼하게 코드 분석을 하도록 하는게 좋타고 합니다. 일단은 권고안 대로 코드분석 환경설정파일을 저는 아래와 같이 위 사항들을 라인추가하여 그대로 반영하였습니다. 아래 붉은색 글자 부분입니다. 

    # This file configures the analyzer, which statically analyzes Dart code to
    # check for errors, warnings, and lints.
    #
    # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
    # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
    # invoked from the command line by running `flutter analyze`.

    # The following line activates a set of recommended lints for Flutter apps,
    # packages, and plugins designed to encourage good coding practices.
    include: package:flutter_lints/flutter.yaml

    linter:
      # The lint rules applied to this project can be customized in the
      # section below to disable rules from the `package:flutter_lints/flutter.yaml`
      # included above or to enable additional rules. A list of all available lints
      # and their documentation is published at
      # https://dart-lang.github.io/linter/lints/index.html.
      #
      # Instead of disabling a lint rule for the entire project in the
      # section below, it can also be suppressed for a single line of code
      # or a specific dart file by using the `// ignore: name_of_lint` and
      # `// ignore_for_file: name_of_lint` syntax on the line or in the file
      # producing the lint.
      rules:
        # avoid_print: false  # Uncomment to disable the `avoid_print` rule
        # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
        avoid_print: false
        prefer_const_constructors_in_immutables: false
        prefer_const_constructors: false
        prefer_const_literals_to_create_immutables: false
        prefer_final_fields: false
        unnecessary_breaks: true
        use_key_in_widget_constructors: false

    # Additional information about this file can be found at
    # https://dart.dev/guides/language/analysis-options



    5. mian.dart 파일 수정하기 
    마지막 부분입니다. main.dart파일을 수정합니다. 아래 그림의 해당 파일을 더블클릭해서 오픈합니다. 





    저와 동일한 결과를 얻고자 하시는 분들은 아래 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);

      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            // This is the theme of your application.
            //
            // Try running your application with "flutter run". You'll see the
            // application has a blue toolbar. Then, without quitting the app, try
            // changing the primarySwatch below to Colors.green and then invoke
            // "hot reload" (press "r" in the console where you ran "flutter run",
            // or simply save your changes to "hot reload" in a Flutter IDE).
            // Notice that the counter didn't reset back to zero; the application
            // is not restarted.
            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);

      // This widget is the home page of your application. It is stateful, meaning
      // that it has a State object (defined below) that contains fields that affect
      // how it looks.

      // This class is the configuration for the state. It holds the values (in this
      // case the title) provided by the parent (in this case the App widget) and
      // used by the build method of the State. Fields in a Widget subclass are
      // always marked "final".

      final String title;

      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }

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

      void _incrementCounter() {
        setState(() {
          // This call to setState tells the Flutter framework that something has
          // changed in this State, which causes it to rerun the build method below
          // so that the display can reflect the updated values. If we changed
          // _counter without calling setState(), then the build method would not be
          // called again, and so nothing would appear to happen.
          _counter++;
        });
      }

      @override
      Widget build(BuildContext context) {
        // This method is rerun every time setState is called, for instance as done
        // by the _incrementCounter method above.
        //
        // The Flutter framework has been optimized to make rerunning build methods
        // fast, so that you can just rebuild anything that needs updating rather
        // than having to individually change instances of widgets.
        return Scaffold(
          appBar: AppBar(
            // Here we take the value from the MyHomePage object that was created by
            // the App.build method, and use it to set our appbar title.
            title: Text(widget.title),
          ),
          body: Center(
            // Center is a layout widget. It takes a single child and positions it
            // in the middle of the parent.
            child: Column(
              // Column is also a layout widget. It takes a list of children and
              // arranges them vertically. By default, it sizes itself to fit its
              // children horizontally, and tries to be as tall as its parent.
              //
              // Invoke "debug painting" (press "p" in the console, choose the
              // "Toggle Debug Paint" action from the Flutter Inspector in Android
              // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
              // to see the wireframe for each widget.
              //
              // Column has various properties to control how it sizes itself and
              // how it positions its children. Here we use mainAxisAlignment to
              // center the children vertically; the main axis here is the vertical
              // axis because Columns are vertical (the cross axis would be
              // horizontal).
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.headlineMedium,
                ),

                // ↓ Add this.
                ElevatedButton(
                  onPressed: () {
                    print('button pressed!');
                  },
                  child: Text('Next'),
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }






    코드를 모두 변경하니 아래와 같이 여러 오류들이 뜹니다. 



    다음 장에서는 프로그램을 디버그 모드로 실행도 해보고 개발도 시작하겠습니다. 
































     




    댓글 쓰기

    여러분의 소중한 의견과 응원을 주시면 저에게 많은 도움이 됩니다.