Flutter 프레임워크 간단 리뷰
Flutter?
구글이 dart 기반으로 만든 모바일 앱 제작 프레임워크로, 한 번의 코딩만으로 안드로이드 앱과 ios 앱을 동시에 만들 수 있게 해준다.
렌더링 엔전은 c++
로 작성되었고, UI 레이어는 dart
로 작성되었다.
사용자는 UI 코드 짤 때는 dart
, 안드로이드 플러그인 코드 짤 때는 kotlin
/ java
, ios 플러그인 코드 짤 때는 Objective-C
/ swift
를 쓸 수 있다
장점
Hot reload
이건 그냥 혁신이다. 이 프레임워크의 존재 가치이자 이 프레임워크를 반드시 써봐야하는 이유이다.
설명은 영상으로.
{{< youtube iPlPk43RbpA >}}
문법
named parameter가 있는 dart 언어의 특성 때문에, 트리 구조인 UI를 코드로 표현했을 때 상당히 깔끔하다. JSX보다도 낫다고 생각한다.
class MyWidget extends StatelessWidget {
final String title;
final String subtitle;
final String redirectTo;
const MyWidget({
Key key,
@required this.title,
@required this.redirectTo,
@required this.subtitle,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return PaddedCard(
child: InkWell(
onTap: () => _goto(context),
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: const Icon(Icons.album),
title: Text(this.title),
subtitle: Text(this.subtitle),
),
],
),
),
);
}
Future<void> _goto(BuildContext context) async {
router.navigateTo(
context,
this.redirectTo,
transition: TransitionType.inFromLeft,
);
}
}
ios, 안드로이드 동시 개발
플러그인만 제외하면 완전히 동시에 개발할 수 있다. 웹으로 만드는 것이랑 비슷한데 Hot reload 있는 정도의 차이라고 해야되나?
import
import 'package:flutter/material.dart';
끝이다.
웹의 경우, 매우 단순한 화면인데도
import Divider from "@material-ui/core/Divider/Divider";
import List from "@material-ui/core/List/List";
import ListItem from "@material-ui/core/ListItem/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText/ListItemText";
import createStyles from "@material-ui/core/styles/createStyles";
import withStyles, { WithStyles } from "@material-ui/core/styles/withStyles";
import InboxIcon from "@material-ui/core/SvgIcon/SvgIcon";
import DeleteIcon from "@material-ui/icons/Delete";
import DraftsIcon from "@material-ui/icons/Drafts";
import MailIcon from "@material-ui/icons/Mail";
import ReportIcon from "@material-ui/icons/Report";
import SendIcon from "@material-ui/icons/Send";
import StarIcon from "@material-ui/icons/Star";
import { Component, ReactNode } from "react";
import * as React from "react";
이런 식의 import가 필요하다.
import의 경우 ide도 dart 쪽이 훨씬 낫다.
async
언어 자체가 async
, await
, async*
,yield
, yield*
를 전부 다 지원한다. 또한 언어의 저 기능들을 충분히 활용할 수 있도록 프레임워크도 여러가지 유틸을 제공한다.
단점
리플렉션의 부재
리플렉션이 없다보니 코드 생성기로 잡다한 일들을 해야 하는데 참 골 때리는 일이다.
rust
언어의 경우엔 trait
기반이라 생성된 코드가 원래 코드에 무언가를 추가하기 쉽지만 dart는 interface
기반 언어이므로..
타입 시스템
rust였다면
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct Noti {
pub title: String;
pub path: String;
}
로 해결될 게
built_value.dart라는 라이브러리를 설정하고 flutter packages pub run build_runner watch
를 백그라운드로 실행하면서
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
import 'package:typed_firestore/typed_firestore.dart';
part 'notification.g.dart';
abstract class Noti implements Built<Noti, NotiBuilder>, DocData {
static Serializer<Noti> get serializer => _$notiSerializer;
String get title;
String get path;
Noti._();
factory Noti([updates(NotiBuilder b)]) = _$Noti;
}
이런 식의 더러운(?) 코드를 짜야 해결된다. 리팩토링은 당연히 매우 힘들다.
Self타입과 Associated type이 없어서 발생하는 문젠데, dart가 이걸 추가하긴 힘들 것 같고 개선된다고 해도 Noti._();
와 factory Noti([updates(NotiBuilder b)]) = _$Noti;
를 없애는 정도가 한계일 거라 생각한다.
플랫폼
현재 ios, 안드로이드 앱만 만들 수 있다.
ide
- 아직 Copy-Paste 시 import도 붙여넣는 기능이 없다.