우동우동우's note

[Flutter] 시작하기 본문

Flutter/Flutter 첫 걸음

[Flutter] 시작하기

우동우동우 2020. 2. 10. 00:30

 

 

Google에서 2017년에 처음으로 Flutter를 릴리즈하였다. Flutter는 Dart라는 언어로 되어 있으며, 멀티플랫폼(Web, Android, iOS) 지원 되는 UI 툴킷이다. Flutter를 활용하여 빠르고 쉽게 UI를 개발할 수 있으며, 뛰어난 퍼포먼스를 낼 수 있다. 또한, Flutter에서는 다양한 기본 UI 라이브러리를 제공하고 있어서 매력적인 UI를 개발하기에는 매우 적합한 플랫폼이라고 할 수 있다. 

Flutter 개발환경 설정 

설지하는 방법에 대해서는 다루지 않겠다. 개발환경 설정을 하는 방법은 자주 변경되기도 하고, 그렇게 어렵지도 않기 때문이다. 일단 한국어로 번역된 flutter.dev 사이트 링크를 넣어 두겠다. 

설치

Flutter를 설치할 운영 체제를 선택해주세요:{{site.alert.note}} **Are you on Chrome OS?** If so, see the official [Chrome OS Flutter installation docs!](/docs/get-started/install/chromeos){{site.alert.end}}

flutter-ko.dev

에디터 설정

Flutter 개발용 IDE는 대표적으로 Android Studio/IntelliJ, Visual Studio Code 이렇게 두가지가 대표적이다. 각각의 장단이 있지만 개인적으로는 VS Code를 추천한다. 이유로는 VS Code가 가볍고, Android Studio 보다는 커스텀의 범위도 넓고 기본 단축키가 IntelliJ 보다는 편리한 느낌이다. 개인의 취향임으로 필요한 것으로 설치하시면 됩니다. VS Code에서 가장 마음에 드는 것은 Show All Commend 기능이다. 

Visual Studio Code 설정 방법

VS Code로 개발하려면 VSCode를 설치해야 겠죠? VSCode를 code.visualstudio.com 사이트에서 다운로드 받아서 설치하면됩니다. 설치방법은 사이트 튜토리얼을 참고하세요. 

VS Code 설치를 마쳤다면, 좌측에 Extensions 탭으로 이동하여, Dart, Flutter Extension을 설치한다. 

 

 

 

첫번째 앱 만들기

Show All Command(win : Ctrl+Shift+P, mac : Cmd+Shift+P)를 실행하여 입력창에다가 Flutter: New Project를 입력하여 실행한다. 

 

Flutter: New Project 실행

 

원하는 이름으로 프로젝트를 만들어 보자. 

 

프로젝트 명 설정

 

주의! 대문자는 쓸 수 없다. 때문에 Underscore(_)를 사용하면 된다. 즉, 낙타는 안되고 지렁이는 사용가능하다. 

 

대문자는 에러

 

프로젝트 명을 입력하면 프로젝트를 저장하는 위치를 지정하면 된다. 지정을 완료하면 다음과 같이 나온다. 

 

 

폴더 구조를 보면 ios와 android 프로젝트를 내부에 포함 하고 있고, flutter 소스를 저장하는 lib 폴더가 있다. 여기서 test 폴더는 실행 전 테스트 코드를 담아두는 곳이다. 

이제 이 프로젝트를 실행 해보자. F5를 눌러 보자. 원하는 에뮬레이터를 선택하고 실행해보자. 다음과 같은 화면이 나타날 것이다. 

 

first_app 실행화면

 

약간의 코드 분석

위 앱을 만들기위해서 필요한 코드는 다음의 61줄 짜리 코드이다. (주석을 삭제한 코드이다.) 생각보다 매우 짧다. 하지만 어느정도 기능이 있다. 상단에 App Bar를 표현하고 있으며 App Bar에는 title이 있고, 중앙에는 2줄의 텍스트를 나타내고 있으며 두번째 줄은 우측 하단의 버튼을 누른 횟수를 나타내도록 되어 있다. 61줄로 표현하기에는 생각보다 많은 기능을 가지고 있다. 나는 이러한 이유로 Flutter는 매우 효율적인 플랫폼이라고 생각한다. 다양한 기능을 짧은 코드로 작성할 수 있기 때문이다. 

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

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

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState 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>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), 
    );
  }
}

이제 이 코드를 자세하게 하나씩 살펴보자. 각 한줄 한줄의 코드에 다양한 정보를 담고 있으니 한줄한줄 자세히 보는 것이 Flutter를 이해하는 데 도움이 많이 될것이다. 

모든 프로그램의 시작은 main에서 부터이다. main 코드에서는 runApp 함수에 MyApp 클래스 객체를 추가하여 실행하도록 되어 있다. 

void main() => runApp(MyApp());

MyApp 클래스를 관찰하면 StatelessWidget을 확장하여 만들어진 클래스이다. Flutter에는 크게 두가지 Widget으로 나뉠 수 있고, 이는 StatelessWidget과 StatefulWidget으로 나뉘어 진다. 추후에 이에 대해서 자세하게 다루겠다. 간단하게만 설명하면 상태에 따라서 widget를 다시 그리는 것이 StatefulWidget 이고 StatelessWidget은 한번 그리면 다시 그리지 않는다고 보면 되겠다. StatelessWidget를 확장하면 build 함수를 정의해야 한다. build 함수에서는 Widget을 반환한다. 여기서 반환하는 객체는 MaterialApp 객체이다.

MaterialApp에는 title, theme, home에 대한 정보를 title은 OS에서 앱에 대해서 1줄 설명을 나타내는 정보를 포함한다. API Docs를 참고하면 Android에서는 task manager에서 나타나고 ios에서는 사용되지 않는다고 한다. theme은 앱의 테마 정보를 나타낸다. home은 MaterialApp에서 화면으로 나타낼 Widget 객체를 반환한다. 

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

MyHomePage는 StatefulWidget을 확장하면 State를 반환하는 createState 함수를 override하고 _MyHomePageState 객체를 반환한다. _MyHomePageState 클래스에서는 build 함수를 만들어야 하고 여기서 View로 나타나는 Widget 객체를 반환한다. build 함수를 살펴보면 Scaffold 객체를 반환한다. Scaffold는 기본 앱에서 사용되는 기본적인 화면을 구성하는 클래스라고 보면된다. Scaffold라는 뜻은 비계라는 뜻으로 건축을 지을 때 임시로 설치하는 가시설물이라는 뜻이란다. 앱을 만들기위헤서 사용되는 가시설물 정도 느낌이다. 실제로 Scaffold는 뷰로는 나타나지 않는다.

Scaffold의 클래스의 객체를 만들기 위해서 사용하는 파라미터는 appBar, body, floatingActionButton가 사용되어 있다. 각각의 파라미터를 하나씩 보겠다. appBar는 앱의 상단에 나타나는 appBar를 나타내는 부분이다. appBar에는 AppBar 클래스의 객체를 만들어서 넣어준다. (아주 친절하지 않은가? ㅎㅎ) AppBar에 title 에 Text 객체를 넣어준다. Text는 Text를 표시하는 widget을 나타낸다. 여기서 Text(widget.title)이 있는데 widget은 MyHomePage를 나타내고 있고, title은 내부 필드인 title을 나타낸다. 

 

AppBar

 

body는 앱의 몸통부분을 나타낸다. 우측 아래에 있는 버튼을 제외한 부분을 나타낸다. 여기서 Center는 전체화면에서 중앙에 위치하도록 하는 객체이며 Column은 다수의 하위 wiget을 배열로 가지며 배열 내에 포함된 Widget들을 차례로 표시한다. 2번째 나타나는 Widget에서 '$_counter' 부분을 보면 $는 String 내부에 코드를 인용하는 부분을 나타낸다. 즉, 2번째 Widget은 _MyHomePageState 내부에 있는 _counter 변수를 String으로 변환하여 나타내는 것이다. 

 

body

 

마지막으로 floatingActionButton 파라미터에는 FloatingActionButton 클래스를 추가한다. 여기서 child에는 버튼 내에 들어가는 widget을 넣으면 되고, tooltip에는 길게 누르면 나타나는 Text 설명이 들어간다. 그리고 onPressed에는 클릭 시 부르는 함수를 추가한다. 여기서 부르는 함수는 _incrementCounter() 함수이다. _incrementCounter 함수를 보면 setState함수를 부르고 있고 setState 함수에서는 _counter 값을 1 증가 시키고 있다. StatefulWidget 에서 state가 변하면 build 함수를 다시 부르게 되어있다. 때문에 전체 화면을 다시 그리도록 되어 있다. 버튼을 눌어보자 글자가 증가하는 것이 보일 것이다. 

 

FloatingActionButton

 

 

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState 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>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), 
    );
  }
}

 

생각보다 많은 내용이 이 간단한 61줄에 포함되어 있다. 그러다 보니 많은 내용을 이해해야만 이 내용을 이해할 수 있을 것이다. 일단 그냥 간단하게 앱이 어떻게 구성되어 있는지 정도만 이해하자 여기서 각각에 대해서 다음 포스트부터 자세하게 조목조목 알아보자. 

Flutter 생각보다 재미있습니다. 

'Flutter > Flutter 첫 걸음' 카테고리의 다른 글

[Flutter] StatelessWidget과 StatefulWidget 기본  (0) 2020.02.12
Comments