Menu
murmur blog
  • About me
  • Flutter
murmur blog

Write your first Flutter app, part 1

Posted on 2019년 9월 16일2019년 10월 10일 by JH Y
Table of Content

Write your first Flutter app, part 1

본 문서는 flutter 에서 제공하는 공식 tutorial 문서를 참고하여 작성 했습니다.

Contents

  1. 기본 Flutter app.
  2. 외부 package 사용.
  3. Stateful widget사용.
  4. 무제한 scrolling ListView생성.



본 가이드를 통해 첫번째 Flutter 앱을 만들어 보겠습니다.

본 과정은 Part1 과 Part2 로 나뉘어 있습니다.
Flutter app을 어떻게 만드는지 맛만 본다고 생각하시고 진행 하세요. 아직 Dart 언어를 이해하지 못하더라도 본 과정은
어렵지 않기 때문에 이해하실 수 있습니다.
다만 Programming language 를 한번도 공부해 본적 없으신 입문자 분이라면 Dart 언어부터 익히고 본 과정을 진행하시는게 필요 합니다.

Dart 언어는 객체지향 언어입니다. 객체지향 언어가 익숙하신 분들이라면 무리없이 본 과정을 이해하실 수 있습니다.


오른쪽 이미지의 앱은 Part1에서 우리가 만들 결과물 입니다.
상단에 App 이름 Startup Name Generator을 출력 하고 무작위의 영문 이름이 list 형태로 출력 됩니다.
해당 list는 무제한으로 출력 됩니다.

Tip!!:우리는 이런 방식을 lazily loaded list 라고 부릅니다.  
한번에 전체 list를 출력 하는게 아니라 scroll 에 따라 조금씩 출력을 추가해 나가는 방식 입니다. 




What you’ll build in part 1

지금부터 간단한 flutter 앱을 만들어 보겠습니다.

PART1.
랜덤하게 영어단어가 나오고 무제한 scroll 되는 리스트에 출력 합니다.

PART2.
Part 2에서는 새로운 스크린을 만들고, 두개의 스크린을 이동 하는 앱을 만들어 보겠습니다.
단어를 선택하면 선택된 단어만 따로 저장이 되고, 선택된 단어만 볼 수 있는 화면이 있는 기능을 추가 합니다.
마지막으로 App의 테마를 변경 해볼 것입니다.

Part1의 목표

  • iOS 와 Android 모두에서 동작되는 Flutter app 개발방법
  • Flutter app의 구조
  • packages 사용해보기.
  • hot reload 를 통해 개발 편리하게 하기.
  • stateful widget 구성해보기.
  • 무제한 list 만들기

Source code editor 선택

본 강의에서는 Visual Source Code를 editor로 사용하겠습니다. 본인이 원하는 editor를 사용하셔도 됩니다.
본 과정에서 개발하는 App은 아래 device에서 구동 가능 합니다.
(iOS 핸드폰에 프로그램을 올려서 테스트 하기 위해서는 개발자등록을 해야 합니다.
회피 방법이 있긴 하나, 정식 방법은 개발자 등록을 하는 것입니다. 개발 단계에서는 simulator를 사용해도 충분 합니다.)

  • 개발자 모드로 연결된 Android 또는 iOS 핸드폰
  • iOS simulator
  • Android emulator

Step 1: Create the starter Flutter app

startup_namer 이란 이름으로 Flutter app을 만듭니다.

아래 순서로 app을 생성 합니다.

  1. View > Command Palette 를 선택 합니다.
  2. “flutter” 라고 검색하여, Flutter: New Project를 선택합니다.
  3. project name을 startup_namer라고 입력 합니다.
  4. 새로 생성할 project folder를 지정합니다.
  5. project 가 생성되면 main.dart 파일이 생성 될 것입니다. 아래 이미지를 참고 하세요.
    (프로젝트가 구성되는데 시간이 조금 걸립니다.)
    Menubar_and_main_dart_—_startup_namer_and_Test_drive_-_Flutter
Tip!: 만약에 "New Flutter Project"가 보이지 않다면 IDE setting이 제대로 되지 않은 것입니다.  
flutter 와 dart plugin 이 제대로 설치 되었는지 확인 하세요.

본 과정에서는 주로 lib/main.dart 파일을 편집 할 것입니다.

  1. lib/main.dart 파일의 코드를 모두 삭제하고 아래 코드로 대체 합니다.

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Welcome to Flutter',
          home: Scaffold(
            appBar: AppBar(
              title: Text('Welcome to Flutter'),
            ),
            body: Center(
              child: Text('Hello World'),
            ),
          ),
        );
      }
    }
    Tip!!:  
    fluuter 코드 정렬을 이용할 수 있습니다. 
      * Android Studio / IntelliJ IDEA: 코드편집창을 우클릭 후 **Reformat Code with dartfmt** 버튼을 누릅니다.
      * VS Code: 코드편집창을 우클릭 후 **Format Document** 을 누릅니다.
      * Terminal:flutter format <filename> 명령을 이용 합니다.
  2. App을 실행 합니다.

    1. visual source code의 오른쪽 하단 파란색의 stauts 바에서 device를 선택 합니다.
      선택된 device 가 실행 될 것입니다. (simulator라면 simulator가 실행 됩니다.)
    2. Debug > Start Debugging 버튼을 누릅니다.
      vscode status bar

    IDE에 별로 project Run 하는 방법은 다음 link를 참조 하세요. IDE 별 application Run 방법

    아래 이미지 처럼 Android 와 iOS 모두 결과를 확인 할 수 있습니다.

      Tip!: 처음 physical device에 application을 구동시키면 시간이 좀 거릴수 있습니다. 
      한번 구동된 App은 hot reload 로 변경사항을 적용 할 수 있습니다. 
      code를 SAVE하는 action 만으로 hot reload가 됩니다. 

해설

지금은 아래 해설이 조금 어려울 수 있지만, 가볍게 읽고 넘어가시면 됩니다.

  • 이번 Example 은 Material app을 만듭니다. Material 은 화면을 디자인 할 수 있는 언어 입니다.
    flutter는 다양한 Material widget을 제공 합니다.

  • main() method 는 (=>) 를 이용했는데 이는 한줄로 function을 표현하는 방법입니다.
    아래와 같은 코드를 좀 간결하게 표현하는 방식 입니다.

    void main() {
    runApp(
      return myApp();
    );
    }
  • App 은 StatelessWidget 을 상속받아서 제작 합니다. 이 말은 앱 자체가 widget 이란 뜻입니다.
    Flutter에서는 거의 모든것이 widget 입니다. alignment, padding, layout도 위젯입니다.

  • Material library 로 부터 온 Scaffold widget은 default app bar, title, body 등을 제공합니다.

  • widget의 주 역할은 build() method 를 제공하는 것입니다. build 란 widget을 어떻게 출력 할지 결정하는 것입니다.

  • 본 예제의 body는 Center widget과 Text child widget 으로 구성되어 있습니다. Center widget은 subwidget들을 스크린의 중앙에 정렬하는 기능을 합니다.

Step 2: Use an external package

다음 스텝으로 english_words 라는 open-source package를 사용해볼 것입니다. 이 package는 가장 많이 사용한 영어 단어를 제공해줍니다.
그외에도 다양한 open source package가 있습니다.
더 많은 package를 찾고 싶으면, flutter packages 사이트를 참고 하세요.

  1. pubspec.yaml 파일은 App의 dependency 와 asset을 관리 합니다.
    pubspec.yaml 파일에 english_words를 추가 합니다.

     dependencies:
       flutter:
         sdk: flutter
       cupertino_icons: ^0.1.2
       english_words: ^3.1.0
  2. Visual Source Code를 사용한다면 pubspec.yaml 의 우측 상단에 Get packages 버튼을 누릅니다.
    Android Studio와IntelliJ 경우 상단에 Packages get을 클릭 합니다.

    [vscode Get pacakges]
    pubspec_yaml_—_startup_namer

    이를 통해 package를 개발중인 project에 설치 할 수 있습니다.
    console에 아래와 같이 flutter pub get 이 수행된 것을 확인 할 수 있습니다.:

    $ flutter pub get
    Running "flutter pub get" in startup_namer...
    Process finished with exit code 0

    Packages get 명령을 실행하면 pubspec.lock파일이 생깁니다. 설치된 package list가 기록되는 문서 입니다.

  3. lib/main.dart,파일에 english_words pacakge 를 import 합니다.:

      import 'package:flutter/material.dart';
      import 'package:english_words/english_words.dart';
  4. "Hello World" 대신에 english_words package를 이용해 단어를 만들겠습니다.:

     class MyApp extends StatelessWidget {
       @override
       Widget build(BuildContext context) {
         final wordPair = WordPair.random();  //english_words 로부터 random 하게 단어를 생성 합니다. 
         return MaterialApp(
           title: 'Welcome to Flutter',
           home: Scaffold(
               title: Text('Welcome to Flutter'),
             ),
             body: Center(
              child: Text(wordPair.asPascalCase), //hello world 대신 english_words package 를 이용해 단어를 생성 합니다. 
             ),
           ),
         );
    Note!!:"Pascal case" (또는 "upper camel case"),
    는 영문자의 첫단어를 대문자로 표시하는것을 말합니다. 
    예를들면  "UpperCamelCase" 처럼 표시하는 형태를 말합니다.
  5. App이 run 된 후에는 app을 update하기 위해 Restart 버튼 또는 save project를 하면 hot reload가 이루어 지는것을 볼 수 있습니다.
    main_dart_—_startup_namer

    hot reload가 일어날때마다 새로운 단어가 화면에 나타날 것입니다.
    이렇게 되는 이유는 word generate 가 build method 안에서 이루어지기 때문입니다.

Problems?

만약 App이 제대로 동작 하지 않는다면 타이핑 오류는 없는지 점검해보세요.
Debugging tool을 써서 찾아낼 수도 있습니다. (지금은 debugging tool 사용법에 대해 모를테니 나중에 해보겠습니다.)
필요하다면 완성된 코드를 참고해서 잘못된 부분을 찾아 내세요.

  • pubspec.yaml
  • lib/main.dart

Step 3: Stateful widget 추가

Stateless widgets 은 immutable(변경불가) 합니다. 모든 값이 final 이란 의미 입니다.
좀 더 쉽게 말하면 widget이 로드될때 한번 그려지고 다시 그려지는 일이 없다는 의미 입니다.

Stateful widgets 은 state의 변경이 일어날 수 있고 이를 컨트롤 합니다. stateful
widget 을 만들기 위해서는 적어도 두개의 class가 필요 합니다.:
1) StatefulWidget class : State class의 instance 를 생성 합니다.
2) State class.

StatefulWidget classs는 immutable(변경불가) 합니다. State class는 widget이 살아있는 동안 영속 합니다.

이번 과정에서 우리는 stateful widget 인 RandomWords class 를 추가 할 것입니다. RandomWords는
State class 인 RandomWordsState 만듭니다.
그 다음 RandomWords 를 MyApp stateless widget 안에 배치 할 것입니다.

  1. 간단한 state class 를 만듭니다. 아래 소스를 main.dart 파일의 밑에 추가 합니다.

    class RandomWordsState extends State {
      // TODO Add build() method
    }

    RandomWords를 위한 generic State class State<RandomWords>를 사용 하겠습니다.

    대부분의 앱로직과 state는 State class 에 넣습니다. 이 클래스는 RandomWords 의 state를 관리 합니다.
    이 클래스는 생성된 영단어를 저장하고 favorite 선택된 단어를 저장 합니다. 또한 user는 하트 아이콘을 클릭 함으로써 favorite를 추가,삭제 할 수 있습니다.
    RandomWordsState 는 RandomWords class에 종속되어 있습니다. 나중에 추가 할 것입니다.

    1. stateful RandomWords widget 을 main.dart 파일에 추가 합니다.
      RandomWords widget 은 State class를 생성하는 것외에 다른 동작은 하지 않습니다:
      class RandomWords extends StatefulWidget {
        @override
        RandomWordsState createState() => RandomWordsState();
      }

    state class를 추가하면 IDE에서 warning을 보낼 것입니다. build method 가 없다는 메시지 입니다.
    다음 과정에서 build method를 생성 해볼 것입니다.
    build method에서는 영단어를 생성할 것이고, MyApp에서 이 단어를 가져다 사용할 것입니다.

    1. build() method 를 RandomWordsState에 추가 합니다:
      class RandomWordsState extends State {
        @override
        Widget build(BuildContext context) {
          final wordPair = WordPair.random();
          return Text(wordPair.asPascalCase);
        }
      }
    1. MyApp의 단어생성 코드 부분을 삭제 하고 RandowmWords()로 대체 합니다.
      최종적으로 아래와 같은 결과가 될 것입니다.:
     class MyApp extends StatelessWidget {
       @override
       Widget build(BuildContext context) {
         return MaterialApp(
           title: 'Welcome to Flutter',
           home: Scaffold(
               title: Text('Welcome to Flutter'),
             ),
             body: Center(
              child: RandomWords(),
             ),
           ),
         );
       }
    1. 앱 재시작.
      앱이 제대로 동작 하는지 확인합니다. 영어단어 조합이 제대로 출력되면 정상입니다.

    만약 아래와 같인 warning이 나오면 app을 재시작 하세요.
    Reloading…
    Some program elements were changed during reload but did not run when
    the view was reassembled; you might need to restart the app (by pressing "R")
    for the changes to have an effect.

Problems?

문제가 발생한다면 아래 완성 소스와 비교하여 문제점을 찾아 보세요.

  • lib/main.dart

Step 4: 무제한 scrolling ListView 생성

이번 과정에서는, RandomWordsState 를 상속하여 영어단어 list 를 출력 해보겠습니다. list 는 ListView widget 에 의해 보여지고,user가 scroll하면 무제한 scrolling을 지원 합니다.

ListView의builder factory constructor는 list view를 lazi build 할 수 있게 합니다. (어려운 개념이니 일단 넘어가겠습니다.)

  1. 추천단어를 저장하기 위해 _suggestions list 를 RandomWordsState 에 추가 합니다.
    그리고 font size를 키우기 위해 _biggerFont variable 을 추가 합니다.

      class RandomWordsState extends State {
        final _suggestions = [];
        final _biggerFont = const TextStyle(fontSize: 18.0);
        // ···
      }
    Tip!!: underscore(_)로 시작하는 변수는 private 임을 의미 합니다. 

    다음 과정으로, 우리는 _buildSuggestions() function 을 RandomWordsState
    class에 추가 할 것입니다. 이 method는 ListView 를 만들고 ListView를 이용해 추천단어를 출력 합니다.

    ListView class는 builder property 를 제공 합니다.

  2. _buildSuggestions() function 을 RandomWordsState class에 추가:

      Widget _buildSuggestions() {
        return ListView.builder(
            padding: const EdgeInsets.all(16.0),
            itemBuilder: /*1*/ (context, i) {
              if (i.isOdd) return Divider(); /*2*/
    
              final index = i ~/ 2; /*3*/
              if (index >= _suggestions.length) {
                _suggestions.addAll(generateWordPairs().take(10)); /*4*/
              }
              return _buildRow(_suggestions[index]);
            });
      }

    ListView에 itemCount 값을 설정하면 count 만큼 고정된 list를 생성하게 되고 itemCount값이 없으면 무제한 list가 생성 됩니다. 우리는 무제한 scroll 되는 ListView를 구현하고 있습니다.

    _buildSuggestions function을 자세히 살펴보겠습니다.
    1) itemBuilder 는 factory builder 이고 annonymous(익명) function으로 된 callback function을 제공 합니다. (어려우면 그냥 넘어 갑니다.)
    이 callback 함수는 두개의 parameter를 넘깁니다. BuildContext 와 i 라는 row interator 입니다.
    i 는 0부터 시작하여 function이 호출되는 수 만큼 증가 합니다. i 값은 단어 개수의 2배로 증가 하게 되는데, 그 이유는 divider 역시 하나의 item으로 인식 하기 때문입니다.

    itemBuilder callback 은 추천단어 한개당 한번씩 호출 됩니다. 그리고 ListTile row 에 넣습니다.
    짝수 row에는 ListTile를 넣고, 홀수 row에는 Divider widget을 넣습니다.
    Divider는 단어와 단어를 구분하는 역할을 합니다. 작은 화면에서는 Divider가 안보일 수도 있지만, 존재하고 있는 것입니다.

    2) Divider widget을 ListView 에 추가 합니다.

    3) i 값을 2로 나눈 정수값을 index에 할당 합니다.
    i가 홀수일 경우 2) 번 과정에서 divider를 return 합니다.
    짝수일 경우 i 값을 2로 나눈 정수를 index에 할당 하게 됩니다.
    결과적으로 0,1,2,3,4 와 같이 word 에 대한 index 를 생성하게 됩니다.
    For example:0, 2, 4, 6 ,8 짝수 i값을 2로 나누면 0, 1, 2, 3, 4 란 값으로 index에 부여 됩니다.

    4) 단어 list의 끝에 도달하면 10개의 단어를 추가로 생성합니다.

    buildSuggestions() function 은 _buildRow() 를 단어당 한번씩 호출 합니다. 이 함수는 각각의 단어를 ListTitle에 넣습니다.

  3. _buildRow() function 을 RandomWordsState에 추가 합니다:

      Widget _buildRow(WordPair pair) {
        return ListTile(
          title: Text(
            pair.asPascalCase,
            style: _biggerFont,
          ),
        );
      }
  4. RandomWordsState class 에 있는 , build() method를 아래 소스와 같이 수정 하세요. _buildSuggestions()를 사용합니다.
    Scaffold는 기본적인 material Design 의 layout을 제공합니다.

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Startup Name Generator'),
          ),
          body: _buildSuggestions(),
        );
      }
  5. MyApp class 에 있는 build() method 를 수정하세요. title을 변경하고 home을 RandomWords widget 으로 바꿉니다.

     class MyApp extends StatelessWidget {
       @override
       Widget build(BuildContext context) {
         return MaterialApp(
            title: 'Startup Name Generator',
            home: RandomWords(),
         );
       }
  6. 앱을 재시작 하세요. 이제 무제한 list의 단어가 출력되는 것을 볼 수 있습니다..

    Android

    iOS

     

Problems?

해결되지 않는 문제가 있다면 아래 완성된 코드를 참고하여 수정 하세요.

  • lib/main.dart

Next steps

축하합니다! iOS와 Android에서 모두 동작하는 Flutter app 을 완성 하였습니다.
본과정을 통해 아래와 같은 내용을 배워 봤습니다.

  • Flutter app 생성
  • Dart code 사용.
  • 외부 library 사용.
  • hot reload 사용.
  • stateful widget 사용.
  • lazily loaded 및 무제한 scrolling list 생성.

다음 과정에서는 Favorite 단어를 지정하고, 새로운 화면에서 Favorite 단어만 보는 기능을 추가 해보겠습니다.
다음 스텝으로 넘어가 보겠습니다.
part 2

ETC

이 글 공유하기:

  • 인쇄하기 (새 창에서 열림)
  • 페이스북에 공유하려면 클릭하세요. (새 창에서 열림)
  • 트위터로 공유하기 (새 창에서 열림)
  • LinkedIn으로 공유하기 (새 창에서 열림)
  • 구글 +1에서 공유하려면 클릭하세요 (새 창에서 열림)
  • 친구에게 전자우편으로 보내기 (새 창에서 열림)

관련

flutter mobile app tutorial
Flutter

답글 남기기 응답 취소

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.

카테고리

  • a-Tech
  • Aix
  • ETC
  • Flutter
  • Food
  • K_culture
  • Media
  • Power system
  • Storage

그 밖의 기능

  • 로그인
  • 글 RSS
  • 댓글 RSS
  • WordPress.org

최근 글

  • Box Constraint
  • Flutter responsive UI
  • Flutter 레이아웃
  • Flutter widget 소개
  • Write your first Flutter app, part 2
©2023 murmur blog | Powered by WordPress & Superb Themes
loading 취소
글이 전송되지 않았습니다. 이메일 주소를 확인하세요!
이메일 확인에 실패했습니다. 다시 시도하세요
죄송합니다. 귀하의 블로그에서 이메일로 글을 공유할 수 없습니다.