안드로이드 데브 서밋 2019 Extended Seoul@GoogleForStartups

2019. 12. 21. 17:35안드로이드 개발

서울 강남의 구글 캠퍼스. Google for Startups 와서 Android Dev Summit 2019 Extended Seoul을 들었다. GDG Seoul 주최 이벤트 두번째 참여입니다. (2019년 12월 21일)

라이트닝 토크 (FINDA, 뱅크샐러드)

FINDA

손쉬운 금융, 나만의 금융

개인 금융 데이터를 가지고 손쉽게 쇼핑할 수 있게

고객과 금융기관을 잇다. 자체 서버보다는 OpenAPI 방식으로 시스템을 연동하고 있음. 사용자 경험을 제공하기 위해 가독성이 높고 이해하기 쉬운 코드 작성 -> 최고 품질, 안정성

채용 : Android / iOS Mobile Developer 

뱅크샐러드

좋은 서비스 -> 데이터 더 모임 -> 더 좋은 서비스 (선순환)

12/22까지 내면 일주일 내에 가능 

AndroidX Security Library

소개

구글에서 Stackoverflow 등 AES 암호화 같은 거 그대로 쓰지 마라. 하면서 모듈을 만들어 주었다. 사용하기는 편해졌음

minSDK 23. 아직 알파 버전인데 5월에 발표한 게 마지막.

EncryptedSharedPreferences. EncryptedFile을 제공한다. 

 

Google Tink : 오픈소스. 크로스 플랫폼 지원.

 

google/tink

Tink is a multi-language, cross-platform, open source library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse. - google/tink

github.com

쓰는 방법 : 간단하게 dependency 추가하면 됨. minSdk 23으로 올려야 사용이 가능하다. 

 

EncryptedSharedPreferences

쓰는 방법은 같은데, GeneratedKey랑 MasterKey 생성 정도만 다르다. 추가로는 암호화 방법 정도? Alias -> 스트링 값이라서 안 써도 굳이 상관은 없다. 

val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)

Alias 키가 중요해서 없어지면 값을 불러올 수 없지. 그래서 key도 value도 둘 다 암호화가 된다. 그러니까 하나의 Alias를 해 줘야 함. 

 

EncryptedFile

val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)

파일 전체에 대한 암호화가 들어감. 오히려 SharedPreferences랑 방법이 더 비슷하다. 털릴 수 있으니 제발 하라는 대로 하라고..

 

Read / Write

BufferedWriter 등으로 쓰고 등등 읽자. 똑같다.

 

Warning

masterKeyAlias는 변경 가능하고 동작에 문제가 없지만 MasterKeys사용이 권장됨.

EncryptedFile의 경우, 생성된 동일 파일이 있으면 Exception이 발생한다. 동일 파일 명으로 Output 할 경우 예외 발생하니까 새로운 데이터 append 후 저장하는 것으로 하거나 기존 파일 제거 마렵다.

 

Biometric Authentication

minSDK 23, 내부적으로 keyAlias 사용하는 듯. 생각보다 최신 빌드임 (12/18, 1.0.1) 이것도 dependencies로 바로 가능한데, 이제 팝업이 사용 가능한데 아래에서 뜬다. Dialog 처럼 뜬다. 그런데 딱 지문만 쓴다. 이런 게 안 됨.

New in Android Studio

안드로이드 스튜디오 4.0

 

build.gradle - 새로운 버전 (녹색) 뜨지. 이제 $kotlin_version 이런 것도 잘 뜬다. 하드코딩만 떴었는데!

Build Speed

빌드가 너무 느려요.. -> Critical Path를 기준으로. 확인. Critical path : Gradle이 연속적으로 실행.

주요 경로가 빌드 시간을 결정. Build Speed insights available. UI 그래프가 나오는데?

태스크 단위로 얼마나 시간이 걸리는 지도 알 수 있겠다. 시간 복잡도까지. 

첫 빌드 127초 -> 두번째 빌드 7초. 어떻게 시간이 차이가 나는지도 알 수 있겠다.

 

Multi Preview

다양한 디바이스 및 Configuration과 관련된 레이아웃을 동시에 미리 볼 수 있는 디자인 도구 -> Pixel Devices, Locale (Language), Color Blind Mode 등 멀티 프리뷰를 통해 사용이 가능하다. XML 화면 오른쪽에 Code / Split / Design 클릭해서 사용할 수가 있겠다. 

 

Desugaring

이전 Android Studio 3.x => java 8 사용 가능하나 최저 버전이 존재함. (한계)

이제 Android Studio 4.0 => 최소 API 레벨을 요구하지 않음. 누락된 API 구현을 별도의 Library DEX 파일로 포함이 됨. 

coreLibraryDesugaringEnabled true

APK 용량은 (당연하겠지만) 증가된다. 

 

View Binding

View와 상호작용하는 코드를 쉽게 작성. 대부분의 findViewById가 대체된다.

findViewById의 차이점 : Null Safety. 원래는 Nullable인데 (R 접근 다 가능하니까..)

Data Binding 차이점 : 사용이 더 쉬움

 

Jetpack Compose

XML 없이 사용하는 게 보통이다.

다크 모드나 등등 프리뷰도 다 가능하다. 

근데 해보고 싶기도 하고 그렇지만 Pre-Alpha 버전이라; Fixed도 안돼서; 아직은 조금 이르다.

 

Editor ~ Debugging

디버깅 중 Break Point 라인을 지나침 / 또는 디버깅 중 코드 더 넣고 싶어진다면?

Apply Changes로.

 

Layout Inspector

이 컬러가 어디서 와서 들어왔는가? 이것도 알 수가 있겠다! 원래는 머터리얼이다. 또는 임의로 변경이 되었다 등등 이렇게 찾아가볼 수가 있겠다. 그래서 오버랩된 것도 알 수가 있겠다.

 

3D로도 볼 수가 있어서 Depth를 볼 수가 있다. Child만 볼 수도 있겠다. 

 

Motion Editor

ConstraintLayout, MotionLayout. ConstraintLayout을 MotionLayout으로 변경을 할 수가 있겠다. After Effect처럼 트랜지션을 볼 수가 있다! 

 

Emulator

디스플레으를 넣고 멀티플 디스플레이가 가능하다. GPS도 변경됨 (이건 써 봤네)

 

Android Studio Plugin 4.0.0

피쳐 : 한번에 다 볼 수가 있겠다. 

Themes

재사용 가능하고, 적은 코드로, 유지 가능한, 다양한(다크) 테마.

 

Themes

테마랑 스타일의 정의 방법은 동일하나, 사용 방법이 다르다.

styles : View, attribute, values의 맵.

themes: theme attribute, values의 맵.

 

?attr => 현재 테마의 values를 가져와 달라.

변경하고자 하는 값을 추출해서 테마로 하면 조합이 될텐데..

 

styles: 단일 뷰

themes: Context와 연결되고 뷰 계층과 관련이 있음. android:theme="@style/MyTheme"

 

색만 다르고 나머지는 같을 때, ThemeOverlay 라는 아이디어로 사용. (parent="")

이렇게 하면 Theme.Owl.Pink, Theme.Owl.Blue 이렇게 따로따로 했던 게 Theme.Owl.Pink와 이에 오버레이되는 ThemeOverlay.Owl.Blue 씌우면 쉽게 할 수 있겠다.

 

ContextCompat.getColor(context, R.color.color) 에서 Context를 뭘로 하냐에 따라 원하는 걸 못 얻을 수도 있으니 가장 가까운 뷰의 Context를 얻자.

 

Colors

리소스를 앱에 적용.

ARGB, 컬러 태그

ColorStateLists: 컬러들을 래핑. state_pressed=true 같은 걸 쉽게 구현. 다르게 보이게.

CoorSateLists도 가장 구체적인 아이템을 위에, 디폴트는 아래에 한다 => 매치되는 첫번째 State의 값을 바로 반환되기 때문.

 

Resource Name

colorPrimary, colorPrimaryDark 이렇게 쓰지 말고 그 자체의 이름을 쓰라고 권장한다.

 

일관된 이름을 사용

Theme.AppName.Blue

Widget.AppName.Toolbar.Green 이렇게 좀 분리해서 알자. 이게 테마인지 스타일인지? (style 태그는 똑같이 쓰니까 구별이 안됨) 

첫번째는 범주, 두번째는 모듈, 세번째는 위젯명, 마지막은 컬러 (sub)

 

목적에 따라 파일을 분리

styles.xml dimens.xml strings.xml colors.xml 이렇게 분리해서 써야지. 근데 엄청나게 커지니까 번거로워짐.

그래서 조금 더 추가로 나눈다. 

 

Material Theming

Typography, Shape, Color. => 다른 Look & Feel

타이포그래피 : 텍스트 값을 좀 정리할 필요가 있겠다. TextApperance. TextView 등에서

android:textAppearance="?attr/textAppearanceBody1"/>

컬러 : colorPrimary colorSecondary. 대비 효과를 위한 Varient. colorSurface => 높이 다름을 색상으로 나타낼 때. colorError. colorOnSurface 등등. On은 비슷한 이름과 대비.

쉐이프 : 위젯에 따라 다양한 모양. 쉐이프도 overlay가 가능하다.  

 

material-components/material-components-android-examples

Companion example apps and code for MDC-Android. Contribute to material-components/material-components-android-examples development by creating an account on GitHub.

github.com

 

 

material-components/material-components-android

Modular and customizable Material Design UI components for Android - material-components/material-components-android

github.com

Dark Mode

현재 모드가 Daylight? Dark? 에 따라 리소스.

그래서 textColor같은 걸 하드코드 하지 말고 attribute에서.

 

colorPrimary - Light Mode : 500 톤. Dark Mode : 200 톤.으로

Elavation Overlay. Light와 Dark 표현 방법이 다름.

Live Data & Coroutines

Layered architecture

View -> (LiveData) ViewModel <-> (Suspend fun) UseCase <-> (suspend fun) Repository <-> (suspend fun) DataSource

 

LiveData & Coroutines.

GlobalScope.launch {} 선호 X. scope의 혼동이 있을 수 있음. 

와 scope 모르겠다.

lifecycleScope.launch {} lifecycleScope.launchWhenResumed {} 이렇게 resume됐을 때 실행할 걸 할 수 있음. 매번 호출되진 않았으면 좋겠는 거. 

ex)

lifecycleScope.launch{ 초마다 1씩 올리면} => 돌다가 홈 나갔다가 좀 후에 다시 나오면 이미 돼있다.

lifecycleScope.launchWhenResumed {초마다 1씩 올리면}=> 돌다가 홈 나갔다가 좀 후에 다시 오면 아까 거기부터 마저 시작됨.

 

LiveData 전달

liveData coroutine builder.

CoroutineLiveData

Dispatchers.Main.immediate ? => 

초기에 어떤 값 => LiveData

LiveData emit(~); emitSource(source)

 

flow->LiveData => flow.asLiveData

WorkManager

AlarmManager -> JobScheduler -> Doze mode -> GCM -> Evernote -> Firebase => Deprecated

이제는 Jetpack의 WorkManager!

 

Basic

작업, 요청 사항 => 특정 상황 요청됐을때.

DB 사용해서 저장이 됨. 강제 종료 됐을 때 리스케쥴이 됨!

 

Worker

Worker, RxWorker, CoroutineWorker.

androidx.work:work-gcm, work-runtime (근데 M 이상에서는 -gcm deprecated 됨 ㅋㅋ)

 

New in 2.3

Progress : WOrker가 결과만 보여줬는데 이제는 진행 상황도 보여줌. 최종적으로는 Result 전달.

- setProgress(workDataOf(PROGRESS to 50) ~ return result.

어떤 값이든 전달이 가능! progress는 work가 RUNNING STATE일 때만 사용하라고 함.

긴 작업 : Foreground에서 노티피케이션을 통해 작업이 중지되지 않도록 보장할 수 있음 (Cancel도 가능)

- setForeground(createForegroundInfo())

val notification ~ .build() return ForegroundInfo(0, notification)

안드로이드 DI

의존성 생성 -> new

class Car {
    private var engine: Engine = Engine()
}

의존성 주입 -> 다른 곳에서 생성.

class Car {
    private val engine: Engine
}

DI :

1. 쉬운 리펙토링이 가능. 각각의 역할을 나누어서 생각할 수 있고 Car는 그것들을 의존. Loosed Coupling. Smaller-focused.

2. 재사용성

val electricCar = Car(ElectricEngine())
val gasolinCar = Car(GasolinEngine())

엔진만 바꿔서 가능.

3. 테스트 쉬움

의존성을 교체할 수 있음. fake 객체를 넣으면 그 의존성을 쉽게 교체할 수 있게 됨.

 

=> Why DI ? => Loosed Coupling. 필요한 부분 교체하려면 그것만 딱. 의존성을 낮추게! 유연하게.

 

DI 방법 

Manual (개발자가 직접 생성).

Koin : Service Locator - 런타임으로 타입 체크 (단점).

Dagger : Generated Code - 컴파일 타임 타입 체크. 에러 인지가 빠르고 안전하지만, 학습비용이 높음 - 어렵다 (단점). 

구글 : 프로젝트가 작으면 아무거나. 중간이거나 프로젝트가 크면 Dagger를 써라.

 

Dagger 구성 : Module, Bind/Provide, Component.

Module : 의존성 생성 Class

Bind/Provide : 의존성 생성 Method

Component : Module 실행.

 

AndroidInjector 이용

알아서 인젝트가 됨.

각각을 만들어서 인젝트.

흐름 - 그래프

AppComponent 선언.

ActivitySubComponent 선언.

Module 선언.

의존성 생성.

Component 생성

Module 연결

Inject.

 

AndroidInjector 이용 > Google Guide 따르기. (미성숙)

역할이 나뉘어서 구글 가이드가 편해보이나, 많아지면 불편하므로 AndroidInjector가 훨씬 편하다. AndroidInjector가 안드로이드 구조에 편하다. Dagger : Java에 편한데, 안드로이드 구조가 정형화됐으므로 AndroidInjector가 딱 맞게 나와 있음. 

 

Dagger2 - Bind / Provide.

mainView 라는 의존성을 요구. 우리 앱밖에 없는 구성. - Focus on Bindings. 컴포넌트를 정의하는 걸 없애자.

@EntryPoint 추가하고 Module Discovery 삭제. Inject 됨

구글 가이드 : Component 선언을 다 해야 됨. 그런데 이제는 @InstallIn이라는 걸 해서 모듈에서 컴포넌트를 연결. 그러면 모듈만 계속 보면 된다. Component에 신경써야 할 걸 제거함. 미리 컴포넌트를 만들어 놨으니까 선언하지 말고 만든걸 넣어라. 선언 안해도 알아서 안드로이드 구조에 맞게 됨

 

Testing

TestEntryPointRule => 테스트 클래스에서 fakeCar 하듯이 함. CarTestModule { provideFakeCar()} 이렇게. 문제는 안 만들어져 있음 (?) Concept.

 

@ienground