Flutter 간단 정리하기
Flutter 에 대해서 간단하게 정리해보고자 한다.
Flutter 는 Google 에서 만든 Cross-Platform Framework 이다.
하나의 코드 Base 로 Android / iOS 심지어 Desktop App 까지 개발 할 수 있다.
모든 것은 Widget 이다.
Flutter 에서는 모든것이 Widget 으로 시작한다.
Image, Icon, Text 그리고 Row, Column, Padding 도 모두 Widget이다.
flutter create
로 프로젝트를 만들어보면, main.dart 에서 runApp 함수에 Widget 을 전달하는 것부터 앱을 시작하는 것을 확인 할 수 있다.
Center Widget 아래 child 으로 Text Widget 를 전달하여, 화면에 가운데 정렬을 하여, “Hello, world” Text 가 노출되는 화면을 구성하였다.
Text Widget 은 단독으로 쓰일 수 없으며, 반드시, 위치를 지정해줄 Layout Widget 이 필요하다.
Rendering
Flutter 는 Widget 으로 만들어진 Layer Tree 를 Skia 라는 그래픽 라이브러리를 이용하여 화면을 만들어낸다.
Skia 는 Android, iOS, Chrome, Firefox 등 다양한 환경 에서 공통 API를 가지고 화면을 그릴수 있도록 도와주는 오픈 소스 2D 그래픽 라이브러리 이다.
void draw(SkCanvas* canvas) {
canvas->drawColor(SK_ColorWHITE); SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(8);
paint.setColor(0xff4285F4);
paint.setAntiAlias(true);
paint.setStrokeCap(SkPaint::kRound_Cap); SkPath path;
path.moveTo(10, 10);
path.quadTo(256, 64, 128, 128);
path.quadTo(10, 192, 250, 250);
canvas->drawPath(path, paint);
}
Skia 가 만들어낸 View Data 를 가지고 각 디바이스 들은 CPU 와 GPU 를 이용해, 화면에 그려낸다.
Flutter 는 각각의 디바이스 ( iOS 나 Android )에서 렌더링하는 방법을 Skia 에게 맞겨 버리기 때문에 각각의 디바이스에 제한 없이 동일한 화면으로 렌더링이 가능하다.
각각의 디바이스 ( iOS 나 Android ) 들의 Native Component 를 사용하지 않기 때문에, 동일한 스타일의 화면을 만들어 낼 수 있다.
Flutter 는 React 와 ReactNative 에서 영감을 받았기 때문에, 개발자로 하여금, 구현 코드와 상태 관리에만 신경을 쓰게 하여, 렌더링의 복잡도를 줄이고, 빠른 구현이 가능하게 한다.
StatelessWidget 과 StatefulWidget
Flutter 의 Widget 은 StatelessWidget 과 StatefulWidget 를 상속 받아 만들 수 있다.
Widget 은 Build 메서드를 포함하며, 이 Build 메서드를 이용해서 Layer Tree 를 만든다.
StatelessWidget 은 단 한번 만 Build 과정이 일어난다. 때문에, 한번 그려진 화면은 계속 유지되며, 성능 상 장점이 생긴다.
StatefulWidget 은 state 를 포함하며, setState 가 발생할때마다 다시 Build 과정이 일어난다. 때문에, 동적 화면을 쉽게 구현이 가능하다.
State life cycle
Flutter Widget 은 life cycle 이 존재한다.
- StatefulWidget.createState 시점에 state 가 생성된다.
- BuildContext 와 연결된다.
Widget build(BuildContext context)
- State.initState 를 딱 한번 호출한다.
- State.didChangeDependencie 를 호출한다.
- setState 가 호출될 때마다 State.didUpdateWidget을 호출한다.
- widget 이 트리에서 제거되는 순간 State.deactivate 호출한다.
- 모든 랜더링이 완전히 끝나고, State.dispose 를 호출하여 자원을 해제한다.
State Management
Flutter 는 State Management 로 Reactive Application 을 전체 앱의 동작과 상태를 관리한다.
setState 로 Widget 의 state 를 변경하며, 그때 마다 Layer Tree 를 다시 만든다.
이 Layer Tree 을 가지고 Skia 가 화면을 다시 그리기 때문에, UI = f(state)
이다. 즉 화면은 상태와 같다.
이는 마치 React 와 ReactNative 에서 상태 관리를 통해 앱을 동작시키는것과 비슷하다.
Provider 로 간단하게 예를 들어보자.
Provider package 에는 ChangeNotifierProvider 를 제공하고 있다.
ChangeNotifier 에서 발생한 notify 를 구독하여, 각각의 Consumer 에게 이 변경 상태를 전달할 수 있는데, 마치 React 16.3 부터 제공한 Context API 와 같다.
ChangeNotifier 를 상속받아 Model Class 를 정의한다.
특정 메서드로 상태가 변경될때 notifyListeners
를 호출해 Provider 에게 알린다.
ChangeNotifierProvider 로 Model Class 를 정의하고, child 에게 Model Class를 전달한다.
Consumer 로 Provider 로 부터 상태를 구독하고, 변경 상태를 전달 받으면 해당 Widget 을 재 랜더링한다.
전달 받은 Model class 의 method 를 이용해, 상태 변경을 요청할 수도 있다.
상태 관리를 Model class 에게 맞겨 Widget 은 화면 그리는것에만 충실 할 수 있다.
provier 뿐만이 아니라, Redux, BLoC / rxdart, MobX 형태도 SDK 로 제공하기 때문에, 해당 상태관리 패턴도 가능하다.
Dart packages
Flutter SDK 를 사용하기 위해서는 Dart Packages 인 pub 에서 제공하는 package 를 pubspec.yaml 에 세팅해야 한다.
pub 은 npm 와 같이 Flutter 에서 사용할 package 를 찾을 수 있다.
위 예제에서 사용한 provier 를 설치하기 위해서는, pubspec.yaml 에서 dependencies 영역에 provider: ^3.0.0
로 세팅후 flutter pub get
으로 패키지를 설치할 수 있다.
// pubspec.yaml
dependencies:
flutter:
sdk: flutter
provider: ^3.0.0
이후 import ‘package:provider/provider.dart’;
으로 import 할 수 있으며, 이때 앱은 재부팅 하여야 사용이 가능하다.
사용할 이미지 등 도 pubspec.yaml 에 세팅하여야 적용이 가능하다.
assets:
- assets/my_icon.png
- file/
이때 파일 명을 지정할 경우 해당 파일만 사용이 가능하고, 폴더 명을 지정할 경우 폴더 내의 파일들 모두 사용이 가능하다.
디자인
Flutter 는 크게 Material Widget 과 Cupertino Widget 을 제공한다.
Material 은 Google Android 스타일의 Widget 이고, Cupertino 는 Apple iOS 스타일의 Widget 이다.
각 OS 별로 버튼 디자인이 달라야 할 경우가 존재한다.
이경우 Platform 을 이용하여 각 디바이스에 따라 스타일을 다르게 설정 할 수 있다.
import ‘dart:io’ show Platform;if (Platform.isAndroid) {
// Android-specific code
} else if (Platform.isIOS) {
// iOS-specific code
}
혹은 iOS 와 Android 를 동일한 화면을 공유 하도록 개발 할 수 있다.
라우터 Router
Flutter 에서는 Navigator Widget 으로 Route 객체의 스택을 관리한다.
Navigator.push 및 Navigator.pop 으로 Route 스택 관리한다.
Navigator 를 직접 구현할 수도 있지만, WidgetsApp 또는 MaterialApp 위젯으로 미리 만들어 져 있는 Navigator 를 사용할 수 있다.
push 대신 pushName 도 가능하다.
MaterialApp 에서 처음 위치인 initialRoute과 각 페이지들을 routes 를 설정한한후, Navigator.pushNamed 로 routes 에서 설정한 path 를 전달하여, 페이지를 전환할 수 있다.
마무리
Flutter 를 간단히 테스트 해보면서 느낀점은 정말 쉽고 빠르게 간단한 앱을 만들어볼 수 있다는 장점이 있다.
ReactNative 도 똑같은 장점을 가지고 있지만, ReactNative 와는 정말 다른 느낌의 개발경험을 부여해주어서 매우 즐거웠다.
단점은 아직 익숙하지 않은 Dart 언어를 배워야 한다는 점인데, Dart 언어를 배워도 괜찮을 정도로 상당히 매력적인 것같다.
다음 포스트로 Flutter 로 간단한 앱을 만들어보면서, 격은 삽집기나 팁을 공유할 수 있으면 좋겠다.