SlideShare a Scribd company logo
처음 시작하는 Flutter
GDG Songdo / Flutter Songdo
@양수장
Getting started with Flutter
Bio
GDG Songdo Organizer (2020~ )
Flutter Songdo Organizer (2022 ~ )
Tech Lead @bluefrog (2020 ~ )
- Android
- Flutter
- Back-end + DevOps
I’m an App Developer.
yangsterchief@duck.com
https://github.com/yangster-chief
https://www.linkedin.com/in/sujang-yang
GDG 인천 & 송도의 새로운 행사
소식은 카톡 오픈채팅방에서 :D
GDG 인천, 송도로 검색! 혹은 QR로 :)
카카오톡 오픈 채팅
https://open.kakao.com/o/gTplSH6
OO으로 처음 시작하는 Flutter
Flutter 왜 해야해요?
Flutter 어떻게 시작 해야해요?
라는 질문 대신에
개인 앱 프로젝트로 처음 시작하는
Flutter
Android, iOS, Web
개인 앱 프로젝트로 처음 시작하는 Flutter
선언형 UI 구조에 익숙하면 바로 시작할 수 있음.
Dart의 문법 구조는 다른언어와 매우 유사함 ( Javascript, Java)
Android - Jetpack Compose UI
iOS - Swift UI
Web - React.js
// Imperative style
b.setColor(red)
b.clearChildren()
ViewC c3 = new
ViewC(...)
b.add(c3)
// Declarative style
return ViewB(
color: red,
child: const ViewC(),
);
var stars = Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.star, color: Colors.green[500]),
const Icon(Icons.star, color: Colors.black),
const Icon(Icons.star, color: Colors.black),
],
);
final ratings = Container(
padding: const EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
stars,
const Text(
'170 Reviews',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w800,
fontFamily: 'Roboto',
letterSpacing: 0.5,
fontSize: 20,
),
),
],
),
);
One Source Multi Platform
개인 앱 프로젝트로 처음 시작하는 Flutter
하나의 소스코드로 여러개의 플랫폼에서 작동하는 어플리케이션 빌드 가능.
Android, iOS, Web, Linux, Windows, macOS
- Framework
- UI 구성요소 및 위젯
- Engine
- 렌더링 엔진
- Embedder
- 엔진을 구동하기 위한 네이티브
코드
Architectural Layers
Flutter Project Overview
name: flutter_example
...
environment:
sdk: ">=2.17.3 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: "^1.0.2"
device_preview: "^1.1.0"
...
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: "^2.0.1"
...
flutter:
uses-material-design: true
assets:
- assets/icons/
- assets/placeholder/
- assets/images/
...
/pubspec.yaml
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
private val openIntent: String = "openIntentChannel"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine)
MethodChannel(flutterEngine.dartExecutor, openIntent).setMethodCallHandler(
IndentHandler(activity)
)
}
}
/Android/app/src/main/kotlin/MainActivity.kt
import UIKit
import Flutter
import FirebaseCore
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func setupFirebase() {
...
}
}
/ios/Runner/AppDelegate.swift
- One Source Multi Platform
- 선언형 UI
- Dart는 Javascript, Java와 매우 유사함.
- Native의 기능을 극한까지 사용하는 경우 외의 대부분의 앱을 만들 수 있음.
- Flutter 공식문서, Codelabs, Flutter 공식 Youtube 로 시작할 수 있음.
정리
나의 개발 커리어로 처음 시작하는
Flutter
Flutter만 배운 개발자가 취업하는 방법
나의 개발 커리어로 처음 시작하는 Flutter
모바일 APP 개발자로 취업
- 부전공이 하나쯤은 꼭 있어야함. (Android / iOS)
- Web 경험도 플러스 요소가 될 수 있음.
Web 개발자로 취업
- … React.js를 배우는게 빠릅니다.
Flutter만 알아도 되지 않나요?
...
<dict>
...
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
...
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>sms</string>
<string>tel</string>
<string>mailto</string>
</array>
...
<key>NSCameraUsageDescription</key>
<string>카메라에 접근하도록 허용합니다.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>위치 접근 권한이 필요합니다.</string>
...
</dict>
</plist>
/ios/Runner/Info.plist
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example">
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<queries>
<!-- If your app checks for SMS support -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="sms" />
</intent>
...
</queries>
<application
android:label="@string/app_name"
android:name="${applicationName}"
android:icon="@mipmap/launcher_icon">
<activity
android:name=".MainActivity"
android:exported="true"
...
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
...
</activity>
...
</application>
</manifest>
/Android/app/src/main/AndroidManifest.xml
// Configuration settings file format documentation can be found at:
// https://help.apple.com/xcode/#/dev745c5c974
BUNDLE_IDENTIFIER=com.example
FLUTTER_TARGET=lib/src/config/env/env_develop.dart
DISPLAY_NAME=flutter_example
GOOGLE_SERVICE_INFO_PLIST=Develop/GoogleService-Dev-Info.plist
FIREBASE_APP_ID_FILE=firebase_app_id_file_dev.json
/ios/Flutter/Develop.xcconfig
...
android {
...
defaultConfig {
applicationId "com.example"
minSdkVersion 23
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
dimension "build-type"
}
signingConfigs {
release {
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
}
}
...
flavorDimensions "build-type"
productFlavors {
...
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
/Android/app/build.gradle
Native Development
Platform Channel
- Flutter에서 실행할 수 없는 코드를
네이티브에서 실행
- Method Channel
- Event Channel
Writing custom platform-specific code | Flutter
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class _MyHomePageState extends State<MyHomePage> {
static const platform = MethodChannel('samples.flutter.dev/battery');
// Get battery level.
String _batteryLevel = 'Unknown battery level.';
Future<void> _getBatteryLevel() async {
String batteryLevel;
try {
final int result = await platform.invokeMethod('getBatteryLevel');
batteryLevel = 'Battery level at $result % .';
} on PlatformException catch (e) {
batteryLevel = "Failed to get battery level: '${e.message}'.";
}
...
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
class MainActivity: FlutterActivity() {
private val CHANNEL = "samples.flutter.dev/battery"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
// This method is invoked on the main thread.
call, result ->
if (call.method == "getBatteryLevel") {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Battery level not available.", null)
}
} else {
result.notImplemented()
}
}
}
}
/Android/app/src/main/kotlin/MainActivity.kt
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let batteryChannel = FlutterMethodChannel(name: "samples.flutter.dev/battery",
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
// This method is invoked on the UI thread.
guard call.method == "getBatteryLevel" else {
result(FlutterMethodNotImplemented)
return
}
self?.receiveBatteryLevel(result: result)
})
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
/ios/Runner/AppDelegate.swift
Native Development
Packages and Plugins (The Boring Flutter Development Show, Ep. 6)
상태관리 라이브러리
var stars = Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.star, color: Colors.green[500]),
const Icon(Icons.star, color: Colors.black),
const Icon(Icons.star, color: Colors.black),
],
);
final ratings = Container(
padding: const EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
stars,
const Text(
'170 Reviews',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w800,
fontFamily: 'Roboto',
letterSpacing: 0.5,
fontSize: 20,
),
),
],
),
);
BuildContext
BuildContext?! | Decoding Flutter
- 부전공이 필요함 (Android, iOS, Web)
- Platform Channel, BuildSettings
- Flutter Web은 아직 시기상조
- 상태관리 라이브러리를 배우자
- GetX 외에도 bloc나 provider를 배우자
- BuildContext 개념 필요
정리
팀의 신규 프로젝트로 처음 시작하는
Flutter
Android 2년차 개발자가 Flutter 프로젝트에 투입
팀의 신규 프로젝트로 처음 시작하는
Flutter
대기업 자회사의 Android 개발자로 채용됨
회사의 그룹웨어 및 신규 프로젝트를 개발하는 TF팀
팀 구성
- Android 9년차 팀장
- iOS 2년차 사원
- Android 5년차 사수
이해관계에 맞는 프로젝트 규모 산정
팀의 신규 프로젝트로 처음 시작하는
Flutter
프로젝트 규모에 따라 사용할 수 있는 상태관리 라이브러리가 달라짐. 일반적으로
- bloc : 대규모
- provider : 중, 소규모
- getX : 소규모
무엇보다도 팀원간의 이해와 소통 (컨벤션) 이 중요합니다.
bloc, provider, GetX 비교 분석
[Flutter Festival GDG Songdo] GetX, provider, bloc 패턴 비교 분석 - 유병욱
협업 방식은 팀바팀, 사바사가 국룰입니다. 하지만,
팀의 신규 프로젝트로 처음 시작하는
Flutter
더 나은 협업을 위해서 고려해볼 몇가지
- DI
- Flutter Theme
- Clean Architecture
- CI / CD
Dependency Injection
Flutter Theme
DevFest Songdo 2022 - Flutter Theme 디자이너와 호감작하기
Clean Architecture
[Flutter Festival GDG Songdo] Flutter에 Clean Architecture를 얹어보자 - 양수장
CI / CD
Github Actions를 활용한 Flutter 배포 자동화하기 - 양수장(GDG Songdo) I 모두콘 2022
Tips & Best Practices
[Flutter Festival GDG Songdo] Flutter 상용화 앱 프로젝트 적용기 - 손민재
- 프로젝트 규모 산정이 최우선
- 핵심 기능이 Flutter로 구현 가능한지 여부 확인
- 협업을 위한 기술
- Flutter Theme
- Clean Architecture
- DI
- CI / CD
정리
처음 시작하는 Flutter
yangsterchief@duck.com
https://github.com/yangster-chief
https://www.linkedin.com/in/sujang-yang

More Related Content

Similar to [Google I_O Extended Daejeon 2023] 처음 시작하는 Flutter

Python on Android
Python on AndroidPython on Android
Python on Android
용 최
 
TestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing toolTestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing tool
hyunae lee
 
TestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing toolTestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing tool
hyunae lee
 
Portfolio
PortfolioPortfolio
Portfolio
MyeongSeokKim2
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
Arawn Park
 
The roadtocodecraft
The roadtocodecraftThe roadtocodecraft
The roadtocodecraftbbongcsu
 
Flipper 불완전 정복
Flipper 불완전 정복Flipper 불완전 정복
Flipper 불완전 정복
Sewon Ann
 
[Flutter Meetup In Songdo] 상태관리 올바르게 쓰기
[Flutter Meetup In Songdo] 상태관리 올바르게 쓰기[Flutter Meetup In Songdo] 상태관리 올바르게 쓰기
[Flutter Meetup In Songdo] 상태관리 올바르게 쓰기
SuJang Yang
 
Data-binding AngularJS
Data-binding AngularJSData-binding AngularJS
Data-binding AngularJS
EunYoung Kim
 
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기
John Kim
 
사업소개서 Ab180(공개버전)
사업소개서 Ab180(공개버전)사업소개서 Ab180(공개버전)
사업소개서 Ab180(공개버전)
Sungpil Nam
 
[25]안드로이드에서 코루틴은 어떻게 적용할 수 있을까?: 코루틴 적용 및 ReactiveX(RxJava/RxKotlin)와 비교한다면?
[25]안드로이드에서 코루틴은 어떻게 적용할 수 있을까?: 코루틴 적용 및 ReactiveX(RxJava/RxKotlin)와 비교한다면?[25]안드로이드에서 코루틴은 어떻게 적용할 수 있을까?: 코루틴 적용 및 ReactiveX(RxJava/RxKotlin)와 비교한다면?
[25]안드로이드에서 코루틴은 어떻게 적용할 수 있을까?: 코루틴 적용 및 ReactiveX(RxJava/RxKotlin)와 비교한다면?
NAVER Engineering
 
Flutter로 글로벌앱 출시를 위한 꿀팁 - Droidknights2020
Flutter로 글로벌앱 출시를 위한 꿀팁 - Droidknights2020Flutter로 글로벌앱 출시를 위한 꿀팁 - Droidknights2020
Flutter로 글로벌앱 출시를 위한 꿀팁 - Droidknights2020
Bansook Nam
 
응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angular응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angular
redribbon1307
 
원모먼트 Vue js 적용기
원모먼트 Vue js 적용기원모먼트 Vue js 적용기
원모먼트 Vue js 적용기
우현 김
 
[Hello World 천안아산] 안드로이드 입문
[Hello World 천안아산] 안드로이드 입문[Hello World 천안아산] 안드로이드 입문
[Hello World 천안아산] 안드로이드 입문
Taeho Kim
 
테스트가 뭐예요?
테스트가 뭐예요?테스트가 뭐예요?
테스트가 뭐예요?
Kyoung Up Jung
 
Android와 Flutter 앱 개발의 큰 차이점 5가지
Android와 Flutter 앱 개발의 큰 차이점 5가지Android와 Flutter 앱 개발의 큰 차이점 5가지
Android와 Flutter 앱 개발의 큰 차이점 5가지
Bansook Nam
 
Angular 2 rc5 조사
Angular 2 rc5 조사Angular 2 rc5 조사
Angular 2 rc5 조사
Rjs Ryu
 
react-ko.pdf
react-ko.pdfreact-ko.pdf
react-ko.pdf
ssuser65180a
 

Similar to [Google I_O Extended Daejeon 2023] 처음 시작하는 Flutter (20)

Python on Android
Python on AndroidPython on Android
Python on Android
 
TestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing toolTestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing tool
 
TestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing toolTestExplorer 소개 - Android application GUI testing tool
TestExplorer 소개 - Android application GUI testing tool
 
Portfolio
PortfolioPortfolio
Portfolio
 
코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우코틀린 멀티플랫폼, 미지와의 조우
코틀린 멀티플랫폼, 미지와의 조우
 
The roadtocodecraft
The roadtocodecraftThe roadtocodecraft
The roadtocodecraft
 
Flipper 불완전 정복
Flipper 불완전 정복Flipper 불완전 정복
Flipper 불완전 정복
 
[Flutter Meetup In Songdo] 상태관리 올바르게 쓰기
[Flutter Meetup In Songdo] 상태관리 올바르게 쓰기[Flutter Meetup In Songdo] 상태관리 올바르게 쓰기
[Flutter Meetup In Songdo] 상태관리 올바르게 쓰기
 
Data-binding AngularJS
Data-binding AngularJSData-binding AngularJS
Data-binding AngularJS
 
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기NODE.JS 글로벌 기업 적용 사례  그리고, real-time 어플리케이션 개발하기
NODE.JS 글로벌 기업 적용 사례 그리고, real-time 어플리케이션 개발하기
 
사업소개서 Ab180(공개버전)
사업소개서 Ab180(공개버전)사업소개서 Ab180(공개버전)
사업소개서 Ab180(공개버전)
 
[25]안드로이드에서 코루틴은 어떻게 적용할 수 있을까?: 코루틴 적용 및 ReactiveX(RxJava/RxKotlin)와 비교한다면?
[25]안드로이드에서 코루틴은 어떻게 적용할 수 있을까?: 코루틴 적용 및 ReactiveX(RxJava/RxKotlin)와 비교한다면?[25]안드로이드에서 코루틴은 어떻게 적용할 수 있을까?: 코루틴 적용 및 ReactiveX(RxJava/RxKotlin)와 비교한다면?
[25]안드로이드에서 코루틴은 어떻게 적용할 수 있을까?: 코루틴 적용 및 ReactiveX(RxJava/RxKotlin)와 비교한다면?
 
Flutter로 글로벌앱 출시를 위한 꿀팁 - Droidknights2020
Flutter로 글로벌앱 출시를 위한 꿀팁 - Droidknights2020Flutter로 글로벌앱 출시를 위한 꿀팁 - Droidknights2020
Flutter로 글로벌앱 출시를 위한 꿀팁 - Droidknights2020
 
응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angular응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angular
 
원모먼트 Vue js 적용기
원모먼트 Vue js 적용기원모먼트 Vue js 적용기
원모먼트 Vue js 적용기
 
[Hello World 천안아산] 안드로이드 입문
[Hello World 천안아산] 안드로이드 입문[Hello World 천안아산] 안드로이드 입문
[Hello World 천안아산] 안드로이드 입문
 
테스트가 뭐예요?
테스트가 뭐예요?테스트가 뭐예요?
테스트가 뭐예요?
 
Android와 Flutter 앱 개발의 큰 차이점 5가지
Android와 Flutter 앱 개발의 큰 차이점 5가지Android와 Flutter 앱 개발의 큰 차이점 5가지
Android와 Flutter 앱 개발의 큰 차이점 5가지
 
Angular 2 rc5 조사
Angular 2 rc5 조사Angular 2 rc5 조사
Angular 2 rc5 조사
 
react-ko.pdf
react-ko.pdfreact-ko.pdf
react-ko.pdf
 

[Google I_O Extended Daejeon 2023] 처음 시작하는 Flutter

  • 1. 처음 시작하는 Flutter GDG Songdo / Flutter Songdo @양수장 Getting started with Flutter
  • 2. Bio GDG Songdo Organizer (2020~ ) Flutter Songdo Organizer (2022 ~ ) Tech Lead @bluefrog (2020 ~ ) - Android - Flutter - Back-end + DevOps I’m an App Developer. yangsterchief@duck.com https://github.com/yangster-chief https://www.linkedin.com/in/sujang-yang
  • 3. GDG 인천 & 송도의 새로운 행사 소식은 카톡 오픈채팅방에서 :D GDG 인천, 송도로 검색! 혹은 QR로 :) 카카오톡 오픈 채팅 https://open.kakao.com/o/gTplSH6
  • 5.
  • 6.
  • 7. Flutter 왜 해야해요? Flutter 어떻게 시작 해야해요? 라는 질문 대신에
  • 8. 개인 앱 프로젝트로 처음 시작하는 Flutter
  • 9. Android, iOS, Web 개인 앱 프로젝트로 처음 시작하는 Flutter 선언형 UI 구조에 익숙하면 바로 시작할 수 있음. Dart의 문법 구조는 다른언어와 매우 유사함 ( Javascript, Java) Android - Jetpack Compose UI iOS - Swift UI Web - React.js
  • 10.
  • 12. // Declarative style return ViewB( color: red, child: const ViewC(), );
  • 13. var stars = Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.star, color: Colors.green[500]), const Icon(Icons.star, color: Colors.black), const Icon(Icons.star, color: Colors.black), ], ); final ratings = Container( padding: const EdgeInsets.all(20), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ stars, const Text( '170 Reviews', style: TextStyle( color: Colors.black, fontWeight: FontWeight.w800, fontFamily: 'Roboto', letterSpacing: 0.5, fontSize: 20, ), ), ], ), );
  • 14. One Source Multi Platform 개인 앱 프로젝트로 처음 시작하는 Flutter 하나의 소스코드로 여러개의 플랫폼에서 작동하는 어플리케이션 빌드 가능. Android, iOS, Web, Linux, Windows, macOS
  • 15. - Framework - UI 구성요소 및 위젯 - Engine - 렌더링 엔진 - Embedder - 엔진을 구동하기 위한 네이티브 코드 Architectural Layers
  • 17. name: flutter_example ... environment: sdk: ">=2.17.3 <3.0.0" dependencies: flutter: sdk: flutter cupertino_icons: "^1.0.2" device_preview: "^1.1.0" ... dev_dependencies: flutter_test: sdk: flutter flutter_lints: "^2.0.1" ... flutter: uses-material-design: true assets: - assets/icons/ - assets/placeholder/ - assets/images/ ... /pubspec.yaml
  • 18. import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import io.flutter.plugins.GeneratedPluginRegistrant class MainActivity: FlutterActivity() { private val openIntent: String = "openIntentChannel" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine) MethodChannel(flutterEngine.dartExecutor, openIntent).setMethodCallHandler( IndentHandler(activity) ) } } /Android/app/src/main/kotlin/MainActivity.kt
  • 19. import UIKit import Flutter import FirebaseCore @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } private func setupFirebase() { ... } } /ios/Runner/AppDelegate.swift
  • 20. - One Source Multi Platform - 선언형 UI - Dart는 Javascript, Java와 매우 유사함. - Native의 기능을 극한까지 사용하는 경우 외의 대부분의 앱을 만들 수 있음. - Flutter 공식문서, Codelabs, Flutter 공식 Youtube 로 시작할 수 있음. 정리
  • 21. 나의 개발 커리어로 처음 시작하는 Flutter
  • 22. Flutter만 배운 개발자가 취업하는 방법 나의 개발 커리어로 처음 시작하는 Flutter 모바일 APP 개발자로 취업 - 부전공이 하나쯤은 꼭 있어야함. (Android / iOS) - Web 경험도 플러스 요소가 될 수 있음. Web 개발자로 취업 - … React.js를 배우는게 빠릅니다.
  • 25. <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example"> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <queries> <!-- If your app checks for SMS support --> <intent> <action android:name="android.intent.action.VIEW" /> <data android:scheme="sms" /> </intent> ... </queries> <application android:label="@string/app_name" android:name="${applicationName}" android:icon="@mipmap/launcher_icon"> <activity android:name=".MainActivity" android:exported="true" ... android:windowSoftInputMode="adjustResize"> <!-- Specifies an Android theme to apply to this Activity as soon as the Android process has started. This theme is visible to the user while the Flutter UI initializes. After that, this theme continues to determine the Window background behind the Flutter UI. --> ... </activity> ... </application> </manifest> /Android/app/src/main/AndroidManifest.xml
  • 26. // Configuration settings file format documentation can be found at: // https://help.apple.com/xcode/#/dev745c5c974 BUNDLE_IDENTIFIER=com.example FLUTTER_TARGET=lib/src/config/env/env_develop.dart DISPLAY_NAME=flutter_example GOOGLE_SERVICE_INFO_PLIST=Develop/GoogleService-Dev-Info.plist FIREBASE_APP_ID_FILE=firebase_app_id_file_dev.json /ios/Flutter/Develop.xcconfig
  • 27. ... android { ... defaultConfig { applicationId "com.example" minSdkVersion 23 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName dimension "build-type" } signingConfigs { release { storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null storePassword keystoreProperties['storePassword'] keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] } } ... flavorDimensions "build-type" productFlavors { ... } } flutter { source '../..' } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } /Android/app/build.gradle
  • 28. Native Development Platform Channel - Flutter에서 실행할 수 없는 코드를 네이티브에서 실행 - Method Channel - Event Channel Writing custom platform-specific code | Flutter
  • 29. import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class _MyHomePageState extends State<MyHomePage> { static const platform = MethodChannel('samples.flutter.dev/battery'); // Get battery level. String _batteryLevel = 'Unknown battery level.'; Future<void> _getBatteryLevel() async { String batteryLevel; try { final int result = await platform.invokeMethod('getBatteryLevel'); batteryLevel = 'Battery level at $result % .'; } on PlatformException catch (e) { batteryLevel = "Failed to get battery level: '${e.message}'."; } ...
  • 30. import androidx.annotation.NonNull import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity: FlutterActivity() { private val CHANNEL = "samples.flutter.dev/battery" override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { // This method is invoked on the main thread. call, result -> if (call.method == "getBatteryLevel") { val batteryLevel = getBatteryLevel() if (batteryLevel != -1) { result.success(batteryLevel) } else { result.error("UNAVAILABLE", "Battery level not available.", null) } } else { result.notImplemented() } } } } /Android/app/src/main/kotlin/MainActivity.kt
  • 31. @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let batteryChannel = FlutterMethodChannel(name: "samples.flutter.dev/battery", binaryMessenger: controller.binaryMessenger) batteryChannel.setMethodCallHandler({ [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in // This method is invoked on the UI thread. guard call.method == "getBatteryLevel" else { result(FlutterMethodNotImplemented) return } self?.receiveBatteryLevel(result: result) }) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } /ios/Runner/AppDelegate.swift
  • 32. Native Development Packages and Plugins (The Boring Flutter Development Show, Ep. 6)
  • 34. var stars = Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.star, color: Colors.green[500]), const Icon(Icons.star, color: Colors.black), const Icon(Icons.star, color: Colors.black), ], ); final ratings = Container( padding: const EdgeInsets.all(20), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ stars, const Text( '170 Reviews', style: TextStyle( color: Colors.black, fontWeight: FontWeight.w800, fontFamily: 'Roboto', letterSpacing: 0.5, fontSize: 20, ), ), ], ), );
  • 36. - 부전공이 필요함 (Android, iOS, Web) - Platform Channel, BuildSettings - Flutter Web은 아직 시기상조 - 상태관리 라이브러리를 배우자 - GetX 외에도 bloc나 provider를 배우자 - BuildContext 개념 필요 정리
  • 37. 팀의 신규 프로젝트로 처음 시작하는 Flutter
  • 38. Android 2년차 개발자가 Flutter 프로젝트에 투입 팀의 신규 프로젝트로 처음 시작하는 Flutter 대기업 자회사의 Android 개발자로 채용됨 회사의 그룹웨어 및 신규 프로젝트를 개발하는 TF팀 팀 구성 - Android 9년차 팀장 - iOS 2년차 사원 - Android 5년차 사수
  • 39. 이해관계에 맞는 프로젝트 규모 산정 팀의 신규 프로젝트로 처음 시작하는 Flutter 프로젝트 규모에 따라 사용할 수 있는 상태관리 라이브러리가 달라짐. 일반적으로 - bloc : 대규모 - provider : 중, 소규모 - getX : 소규모 무엇보다도 팀원간의 이해와 소통 (컨벤션) 이 중요합니다.
  • 40. bloc, provider, GetX 비교 분석 [Flutter Festival GDG Songdo] GetX, provider, bloc 패턴 비교 분석 - 유병욱
  • 41. 협업 방식은 팀바팀, 사바사가 국룰입니다. 하지만, 팀의 신규 프로젝트로 처음 시작하는 Flutter 더 나은 협업을 위해서 고려해볼 몇가지 - DI - Flutter Theme - Clean Architecture - CI / CD
  • 43. Flutter Theme DevFest Songdo 2022 - Flutter Theme 디자이너와 호감작하기
  • 44. Clean Architecture [Flutter Festival GDG Songdo] Flutter에 Clean Architecture를 얹어보자 - 양수장
  • 45. CI / CD Github Actions를 활용한 Flutter 배포 자동화하기 - 양수장(GDG Songdo) I 모두콘 2022
  • 46. Tips & Best Practices [Flutter Festival GDG Songdo] Flutter 상용화 앱 프로젝트 적용기 - 손민재
  • 47. - 프로젝트 규모 산정이 최우선 - 핵심 기능이 Flutter로 구현 가능한지 여부 확인 - 협업을 위한 기술 - Flutter Theme - Clean Architecture - DI - CI / CD 정리