소소한 개발 공부

[Flutter] 플러터에서 Dart 언어 기본 구조 본문

개발/앱 개발

[Flutter] 플러터에서 Dart 언어 기본 구조

이내내 2022. 2. 10. 17:18

1. Dart 개요

flutter를 개발할 때 사용하는 언어인 Dart 언어는 객체지향 언어로

변수로 쓸 수 있는 모든 것은 객체(Object)이며 모든 객체는 클래스(class)의 인스턴스(instance)로서 존재한다.

모든 숫자(number), 함수(function), null 까지 object라고 할 수 있다.

null을 제외하고 모든 객체(Object)는 Object 클래스를 상속받는다.

 

Dart 언어는 강한 타입 언어이지만

(- 컴파일 시간 혹은 런타임에 타입 검사를 실행하고 서로 다른 타입의 형변환을 위해서는 명시적 선언이 필요)

Dart가 타입을 암시할 수 있기에 타입을 명시하지 않아도 된다. ex) var 자료형

 

Dart의 기본 자료형은 5가지로 int, double, String, bool, dynamic 이 있다.

활용은 아래의 코드와 같다.

void main() {
  /*
   int
   double
   String
   bool
   dynamic - 런타임 동안 값, 자료형을 변경할 수 있는 변수
   */
  
  int amount1 = 100;
  var amount2 = 200; // var amount2 는 int 로 인식
  
  print('Amount 1: $amount1 | Amount2 : $amount2 \n');
  
  double dAmount1 = 100.11;
  var dAmount2 = 200.22;  // var dAmount2 는 double 로 인식
  
  print('dAmount 1: $dAmount1 | dAmount2 : $dAmount2 \n');
  
  String name1 = 'aa';
  var name2 = 'bb';	// var name2 는 String 으로 인식
  
  print('My name is : $name1 $name2 \n');
  
  bool isItTrue1 = true;
  var isItTrue2 = false;	// var isItTrue2 는 bool 로 인식
  
  print('isItTrue1: $isItTrue1 | isItTrue2: $isItTrue2 \n');
  
  dynamic weakVariable = 100;	// weakVariable 은 int
  print('WeakVariable 1: $weakVariable \n');
  
  weakVariable = 'Dart Programming';	// weakVariable 은 String
  print('WeakVariable 2: $weakVariable \n');
  
  for (var i = 0; i < 4; i++) {
    if (i % 2 == 0) print('hello $i' + " times"); // 문자열은 '+'로 합칠 수 있고 ''와 "" 모두 쓸 수 있음
  }
}

출력

1. 물음표 (?)

Dart는 자료형의 뒤에 물음표(?)를 붙임으로써 변수를 nullable 하게 만들 수 있다.

예를 들어, int? 는 정수 혹은 null을 가진다.

 

2. 제네릭

List<int> 같은 제네릭 타입을 지원한다.

 

3. 계층적 구조

최상위 함수(main 함수)를 지원하며 함수 안에 함수를 생성하는 것도 가능하다.

 

4. private 표현

public, private, protected 의 접근제한자를 사용하지 않고 언더바(_)를 통해 private를 표현한다.

ex) String _name; => private string name;

 

5. 문장

연산자 (ex. 삼항 연산자 condition ? expr1 : expr2) 와 if-else 문장을 사용할 수 있다.

 

6. 느낌표 (!)

또한 느낌표(!)는 nullable 타입의 non-nullable 타입으로의 전환을 나타낸다

https://stackoverflow.com/questions/63253015/what-does-the-exclamation-mark-mean-before-a-function-call

 

What does the exclamation mark mean before a function call?

I was following a PR for Flutter and came across this code: if (chunkCallback != null) { chunkCallback!(0, 100); } What does the exclamation mark mean after chunkCallback? Nothing I search on Go...

stackoverflow.com

 

2. Flutter에서의 Dart

기본 flutter 프로젝트의 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(
        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),
      ),
    );
  }
}

클래스와 메서드 단위로 나눠서 보면

1) main 함수

import 'package:flutter/material.dart';

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

패키지를 임포트하고 main 함수에서 MyApp()이라는 클래스를 실행한다. MyApp이 앱을 표현하게 된다.

runApp() 함수의 괄호 안에 사용할 위젯(Widget)을 삽입하면 해당 위젯을 사용할 수 있다. (flutter의 모든 것은 위젯Widget이라 할 수 있다.)

아래와 같이 한 줄로도 표현할 수 있다.

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

 

2) Widget

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();
}

MyApp은 전체화면에 해당하며 그 안의 build()는 작성한 위젯을 프레임워크를 돌려 화면에 표시할 수 있게 해주는 역할이다.

 

Key? key 는 key가 nullable 하다는 것을 의미한다. 즉, key가 있을 수도, null일 수도 있음을 의미.

Widget build는 stateless 한 위젯인 MyApp을 규정한다.

- MaterialApp 아니면 CupertinoApp을 사용한다.

- Material은 모바일 및 웹에서 표준으로 사용되는 시각 디자인 언어라고 한다.

title은 상단에 이름을 보여주고 theme은 위젯의 스타일을 정해준다.

home 은 위젯으로 안에 MyHomePage를 넣어서 정의했으며 StatefulWidget이다.

MyHomePage의 State는 _MyHomePageState()에서 만들어준다.

 

StatelessWidget(무상태위젯) / StatefulWidget(상태위젯)
모든 UI 컴포넌트에 해당한다.

👌 StatelessWidget 무상태위젯 : 변화가 없는 화면만 표시.
👌 StatefulWidget 상태위젯 : 변경 가능한 상태를 가진 위젯. UI가 생명주기 동안 변경됨. 생성 시 2개의 클래스가 기본으로 생성된다. (ex / MyHomePage - _MyHomePageState)

전체는 stateless, 안의 구성 요소는 stateful 로 관리할 수 있다.

 

3) State 클래스

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),
      ),
    );
  }
}

Stateful 위젯의 상태를 정의하는 부분이다.

 

build에서 위젯의 표현 양식(Scaffold) + 버튼의 기능(floatingActionButton)을 작성한다.

버튼이 눌리면(onPressed) _incrementCounter 메서드가 실행되어 _counter 변수가 증가함 이를 위젯의 중앙에서 확인할 수 있다.

 

표시해둔 곳이 floatingActionButton. 버튼을 누르면 현재 2인 숫자가 3,4,5,... 순으로 증가한다.

 

 

참고 :

Dart Programming Tutorial - Full Course - freeCodeCamp.org / Dart Docs 

dart 프로그래밍 실습 사이트 : https://dartpad.dartlang.org