<commit_before>---
title: '구글 I/O 2018 안드로이드 파트 리뷰'
author: gyooha
tags: [google-io-2018, android]
date: 2018-06-11 00:00:00
---
<base href="http://tech.lezhin.com">

구글 I/O 2018에 발표된 안드로이드 기술 관련 내용을 리뷰합니다. 이번 구글 I/O에서는 62개의 크고 작은 세션들을 개발자에게 공개했습니다. 다양한 세션 중 이번 글에서는 안드로이드 개발과 관련있는 새로운 기능, 안드로이드 제트팩(Android JetPack), 안드로이드 P(Android P)에 관해 정리하고자 합니다.


## 새로운 기능을 더한 안드로이드

안드로이드 앱 사이즈를 효과적으로 줄일 수 있는 앱 번들과 동적 전달(App Bundle & Dynamic Delivery), 안드로이드 개발을 도와주는 라이브러리, 도구 등을 제공하는 안드로이드 제트팩(Android JetPack), 안드로이드 스튜디오(Android Studio)를 소개했고, 그 밖의 새로운 기능들을 추가해서 더 자유롭고 재미있는 개발이 가능해졌습니다.

### [앱 번들과 동적 전달(App Bundle & Dynamic Delivery)](https://developer.android.com/guide/app-bundle/)

<img src="https://1.bp.blogspot.com/-lwdb_wiD6vM/WvHRpCJz0TI/AAAAAAAAFWY/kO_wnXli8PUFmEe7ELWpwOu5m-A7TGLPACLcBGAs/s1600/App-Bundle-Animation_GIF.gif" width="800" alt>

구글은 안드로이드 앱의 크기를 동적으로 줄일 수 있는 앱 번들과 동적 전달을 발표했습니다. 안드로이드 앱을 모든 기기에서 작동하려면 많은 리소스가 필요하지만 새로운 번들 시스템을 사용하면 앱을 다운로드할 때 플레이스토어(Play Store)가 앱 구동에 필요한 리소스만 전달합니다. 번들이 모든 리소스를 가지고 있는 것은 기존과 같습니다.

* 이 기술을 먼저 적용한 링크드인은 23%, 트위치는 35%, 조모는 50%가량 앱의 크기가 줄었다고 합니다.

### [안드로이드 제트팩(Android JetPack)](https://developer.android.com/jetpack/docs/)

<img src="https://1.bp.blogspot.com/-dwL58chu7wo/WvD1RrHln3I/AAAAAAAAFUg/cRTc0IZga_wMPTWr3CI53IZ5BwtnZMeYACLcBGAs/s1600/Screen%2BShot%2B2018-05-05%2Bat%2B11.49.30%2BAMimage1.png" width="800" alt>

안드로이드 제트팩은 안드로이드 개발을 도와주는 라이브러리, 도구들을 포함한 라이브러리 모음입니다. 기존의 서포트 라이브러리, 안드로이드 아키텍처 컴포넌트와 이번에 추가된 새로운 라이브러리를 병합하여 크게 4가지 구성요소로 나누었습니다. 기존 안드로이드 버전들과 호환될 뿐만 아니라 불필요한 코드들(Boiler plate)을 제거했고, 패키지 이름을 AndroidX로 변경했습니다. 패키지 이름 변경이 패키지 경로(Package path) 문제를 유발하지 않도록 안드로이드 스튜디오 3.2에서 리팩터(Refactor)기능을 지원한다고 합니다.

### [안드로이드 스튜디오(Android Studio)](https://developer.android.com/studio/preview/)

위에서 소개한 앱 번들과 동적 전달, 안드로이드 제트팩에서 필요한 메뉴들(App Bundle Menu, JetPack Refactor Menu)을 안드로이드 스튜디오에 추가했습니다. 이것과는 별개로 기존 에뮬레이터(Emulator)에 스냅샷(Snapshot) 기술을 적용하여 속도를 개선했고, 에너지 프로파일링(Energy Profiling) 기술을 적용하여 앱의 배터리 소모를 추적할 수 있습니다.

## 안드로이드 제트팩

<img src="https://developer.android.com/static/images/jetpack/jetpack-hero.svg" width="300" alt>

안드로이드 제트팩에 새롭게 추가된 라이브러리를 알아보려 합니다.

### [워크매니저(WorkManager)](https://developer.android.com/topic/libraries/architecture/workmanager)

안드로이드는 UI 작업을 제외한 작업을 백그라운드 작업으로 분류해야 합니다. 워크매니저는 백그라운드 작업을 조금 더 쉽게 할 수 있도록 개발자를 돕는 라이브러리 입니다. 워크매니저는 3가지 백그라운드 작업을 지원합니다.

* 연결 작업
* 병렬 작업
* 반복 작업

#### 연결 작업

<img src="https://cdn-images-1.medium.com/max/1600/1*Z-WI-fSc-FkW1pG0d5II4g.png" width="300" alt>

```kt
WorkManager.getInstance()
      .beginWith(workA)
      .then(workB)
      .enqueue();
```
#### 병렬 작업

 <img src="https://cdn-images-1.medium.com/max/1600/1*oS0-Fb5RfPLSNCb9V-FqCQ.png" width="400" alt>

```kt
WorkManager.getInstance()
      .beginWith(workA1, workA2, workA3)
      .then(workB)
      .then(workC1, workC2)
      .enqueue();
```
#### 반복 작업

```kt
val request = PeriodicWorkRequest
      .Builder(RepeatWork::class.java, 6, TimeUnit.HOURS)
      .build()
```

UUID나 TAG를 사용하여 작업 취소가 편리하며, 안드로이드 SDK 버전 14 이상부터 호환되므로 거의 모든 안드로이드 기기에서 사용할 수 있습니다. 그 밖에 여러 가지 작업을 순차적으로 실행하는 연결 작업, 동시에 여러 가지 작업을 실행하는 병렬 작업, 일정 시간마다 반복해서 실행하는 반복 작업이 가능합니다. 추가로 같은 안드로이드 아키텍처 컴포넌트(Android Architecture Component)인 라이브데이터(LiveData)와 함께 사용할 수 있습니다.

구글 코드랩(CodeLab) 예제를 이용해 만든 프로젝트를 깃허브(Github)에 정리했습니다. [워크매니저 예제](https://github.com/gyooha/WorkManagerExample.git)를 참고해주세요.

### [네비게이션(Navigation)](https://developer.android.com/topic/libraries/architecture/navigation/)

<img src="/files/2018-06-11-google-io/1.png" width="600" alt>

네비게이션 아키텍처 컴포넌트(Navigation Architecture Component)는 액티비티(Activity) 및 프래그먼트(Fragment) 전환, 스택(Stack), 값 전달(Passing Argument), 딥링크(Deep Links), 테스트(Test) 등을 더욱 편하게 관리할 수 있도록 도와주는 라이브러리입니다.

네비게이션 XML 파일로 화면의 동작을 정의하는 메타데이터(MetaData)를 작성할 수 있으며, 작성한 메타데이터를 이용하여 바텀네비게이션뷰(BottomNavigationView), 네비게이션 드로어(Navigation Drawer)의 각 메뉴에 화면을 바인드(Bind) 할 수 있고, 뿐만 아니라 코드상에서 프래그먼트(Fragment)의 영원한 서포터인 서포트프래그먼트매니저(SupportFragmentManager), 차일드프래그먼트매니저(ChildFragmentManager)가 하는 역할을 네비게이션 아키텍처 컴포넌트에 위임할 수 있습니다.

#### 네비게이션 정의

```xml
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    app:startDestination="@id/mainFragment">

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.seroo.gyooha.navigationexample.ui.main.MainFragment"
        android:label="fragment_main"
        tools:layout="@layout/fragment_main" >
        <deepLink app:uri="test://main" />
        <argument
            android:name="test"
            android:defaultValue="0"
            app:type="integer" />
    </fragment>
</navigation>
```

#### 액티비티(Activity) 정의

```xml
<fragment
      android:id="@+id/fm_activity_main"
      android:name="androidx.navigation.fragment.NavHostFragment"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:defaultNavHost="true"
      app:navGraph="@navigation/nav_graph"
```

```kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        tb_activity_main.title = getString(R.string.app_name)

        setUpBottomNavigation((supportFragmentManager
            .findFragmentById(R.id.fm_activity_main) as NavHostFragment).navController)
    }

    private fun setUpBottomNavigation(navController: NavController) {
        NavigationUI.setupWithNavController(bn_activity_main, navController)
    }
}
```

#### 프래그먼트(Fragment) 이동

```kt
 // 이곳의 프래그먼트 Id는 네비게이션 XML에서 행동을 정의한 프래그먼트의 Id 입니다.
 button.setOnClickListener { Navigation.findNavController(it).navigate(R.id.mainFragment, null) }
```

* 엔드포인트(EndPoint)를 이용하여 프래그먼트(Fragment)에서 액티비티(Activity)로 지정할 수 있습니다.
* 네비게이션(Navigation) 안에서 액티비티(Activity)간 이동은 허용하지 않습니다.(아래 그림 참고)

<img src="/files/2018-06-11-google-io/error1.png" width="300" alt>

더 자세한 코드는 깃허브에 정리했습니다. [네비게이션 예제](https://github.com/gyooha/NavigationExample.git)를 참고해주세요.

### [슬라이스(Slices)](https://developer.android.com/guide/slices/)

<img src="http://img.youtube.com/vi/a7IVH5aNwwc/0.jpg" width="480" alt>

슬라이스(Slices)는 외부에 콘텐츠를 공유하거나, 공유받아 사용할 수 있는 라이브러리입니다. 슬라이스 콘텐츠(Slices Content)가 정의되어 있는 다른 앱의 콘텐츠를 슬라이스 프로바이더(Slices Provider)를 통해 가져올 수 있으며, 화면에 출력한 컨텐츠는 정의한 것에 한해 자유롭게 사용할 수 있습니다.

#### 슬라이스 URI 분류

```kt
override fun onBindSlice(sliceUri: Uri?): Slice {
        return when (sliceUri?.path) {
            "/temperature" -> createTemperatureSlice(sliceUri)
            else -> throw IllegalStateException("is Not exist")
        }
    }
```

#### 슬라이스 펜딩인텐트(PendingIntent) 제작

```kt
  private fun getChangeTempIntent(value: Int): PendingIntent =
        Intent(ACTION_CHANGE_TEMP).apply {
            setClass(context, MyBroadcastReceiver::class.java)
            putExtra(EXTRA_TEMP_VALUE, value)
        }.let {
            PendingIntent.getBroadcast(context, reqCode++, it, PendingIntent.FLAG_UPDATE_CURRENT)
        }
```
#### 슬라이스 UI
<commit_msg>fixed contents<commit_after>---
title: '구글 I/O 2018 안드로이드 파트 리뷰'
author: gyooha
tags: [google-io-2018, android]
date: 2018-06-11 00:00:00
---
<base href="http://tech.lezhin.com">

구글 I/O 2018에 발표된 안드로이드 기술 관련 내용을 리뷰합니다. 이번 구글 I/O에서는 62개의 크고 작은 세션들을 개발자에게 공개했습니다. 다양한 세션 중 이번 글에서는 안드로이드 개발과 관련있는 새로운 기능, 안드로이드 제트팩(Android JetPack), 안드로이드 P(Android P)에 관해 정리하고자 합니다.


## 새로운 기능을 더한 안드로이드

안드로이드 앱 사이즈를 효과적으로 줄일 수 있는 앱 번들과 동적 전달(App Bundle & Dynamic Delivery), 안드로이드 개발을 도와주는 라이브러리, 도구 등을 제공하는 안드로이드 제트팩(Android JetPack), 새로운 기능이 추가된 안드로이드 스튜디오(Android Studio)를 소개했고, 그 밖의 새로운 기능들을 추가해서 더 자유롭고 재미있는 개발이 가능해졌습니다.

### [앱 번들과 동적 전달(App Bundle & Dynamic Delivery)](https://developer.android.com/guide/app-bundle/)

<img src="https://1.bp.blogspot.com/-lwdb_wiD6vM/WvHRpCJz0TI/AAAAAAAAFWY/kO_wnXli8PUFmEe7ELWpwOu5m-A7TGLPACLcBGAs/s1600/App-Bundle-Animation_GIF.gif" width="800" alt>

구글은 안드로이드 앱의 크기를 동적으로 줄일 수 있는 앱 번들과 동적 전달을 발표했습니다. 안드로이드 앱을 모든 기기에서 작동하려면 많은 리소스가 필요하지만 새로운 번들 시스템을 사용하면 앱을 다운로드할 때 플레이스토어(Play Store)가 앱 구동에 필요한 리소스만 전달합니다. 번들이 모든 리소스를 가지고 있는 것은 기존과 같습니다.

* 이 기술을 먼저 적용한 링크드인은 23%, 트위치는 35%, 조모는 50%가량 앱의 크기가 줄었다고 합니다.

### [안드로이드 제트팩(Android JetPack)](https://developer.android.com/jetpack/docs/)

<img src="https://1.bp.blogspot.com/-dwL58chu7wo/WvD1RrHln3I/AAAAAAAAFUg/cRTc0IZga_wMPTWr3CI53IZ5BwtnZMeYACLcBGAs/s1600/Screen%2BShot%2B2018-05-05%2Bat%2B11.49.30%2BAMimage1.png" width="800" alt>

안드로이드 제트팩은 안드로이드 개발을 도와주는 라이브러리, 도구들을 포함한 라이브러리 모음입니다. 기존의 서포트 라이브러리, 안드로이드 아키텍처 컴포넌트와 이번에 추가된 새로운 라이브러리를 병합하여 크게 4가지 구성요소로 나누었습니다. 기존 안드로이드 버전들과 호환될 뿐만 아니라 불필요한 코드(Boiler plate)를 제거했고, 패키지 경로(Package path)를 AndroidX로 통일하였습니다. 패키지 경로가 통일됨에 따라 패키지 경로 문제를 유발하지 않도록 안드로이드 스튜디오 3.2에서 리팩터(Refactor)기능을 지원한다고 합니다.

### [안드로이드 스튜디오(Android Studio)](https://developer.android.com/studio/preview/)

위에서 소개한 앱 번들과 동적 전달, 안드로이드 제트팩에서 필요한 메뉴들(App Bundle Menu, JetPack Refactor Menu)을 안드로이드 스튜디오에 추가했습니다. 이것과는 별개로 기존 에뮬레이터(Emulator)에 스냅샷(Snapshot) 기술을 적용하여 속도를 개선했고, 에너지 프로파일링(Energy Profiling) 기술을 적용하여 앱의 배터리 소모를 추적할 수 있게 되었습니다.

## 안드로이드 제트팩

<img src="https://developer.android.com/static/images/jetpack/jetpack-hero.svg" width="300" alt>

안드로이드 제트팩에 새롭게 추가된 라이브러리를 알아보려 합니다.

### [워크매니저(WorkManager)](https://developer.android.com/topic/libraries/architecture/workmanager)

안드로이드는 UI 작업을 제외한 작업을 백그라운드 작업으로 분류해야 합니다. 워크매니저는 백그라운드 작업을 조금 더 쉽게 할 수 있도록 개발자를 돕는 라이브러리 입니다. 워크매니저는 3가지 백그라운드 작업을 지원합니다.

* 연결 작업
* 병렬 작업
* 반복 작업

#### 연결 작업

<img src="https://cdn-images-1.medium.com/max/1600/1*Z-WI-fSc-FkW1pG0d5II4g.png" width="300" alt>

```kt
WorkManager.getInstance()
      .beginWith(workA)
      .then(workB)
      .enqueue();
```
#### 병렬 작업

 <img src="https://cdn-images-1.medium.com/max/1600/1*oS0-Fb5RfPLSNCb9V-FqCQ.png" width="400" alt>

```kt
WorkManager.getInstance()
      .beginWith(workA1, workA2, workA3)
      .then(workB)
      .then(workC1, workC2)
      .enqueue();
```
#### 반복 작업

```kt
val request = PeriodicWorkRequest
      .Builder(RepeatWork::class.java, 6, TimeUnit.HOURS)
      .build()
```

UUID나 TAG를 사용하여 작업 취소가 편리하며, 안드로이드 SDK 버전 14 이상부터 호환되므로 거의 모든 안드로이드 기기에서 사용할 수 있습니다. 그 밖에 여러 가지 작업을 순차적으로 실행하는 연결 작업, 동시에 여러 가지 작업을 실행하는 병렬 작업, 일정 시간마다 반복해서 실행하는 반복 작업이 가능합니다. 추가로 같은 안드로이드 아키텍처 컴포넌트(Android Architecture Component)인 라이브데이터(LiveData)와 함께 사용할 수 있습니다.

구글 코드랩(CodeLab) 예제를 이용해 만든 프로젝트를 깃허브(Github)에 정리했습니다. [워크매니저 예제](https://github.com/gyooha/WorkManagerExample.git)를 참고해주세요.

### [네비게이션(Navigation)](https://developer.android.com/topic/libraries/architecture/navigation/)

<img src="/files/2018-06-11-google-io/1.png" width="600" alt>

네비게이션 아키텍처 컴포넌트(Navigation Architecture Component)는 액티비티(Activity) 및 프래그먼트(Fragment) 전환, 스택(Stack), 값 전달(Passing Argument), 딥링크(Deep Links), 테스트(Test) 등을 더욱 편하게 관리할 수 있도록 도와주는 라이브러리입니다.

네비게이션 XML 파일로 화면의 동작을 정의하는 메타데이터(MetaData)를 작성할 수 있으며, 작성한 메타데이터를 이용하여 바텀네비게이션뷰(BottomNavigationView), 네비게이션 드로어(Navigation Drawer)의 각 메뉴에 화면을 바인드(Bind) 할 수 있고, 뿐만 아니라 코드상에서 프래그먼트(Fragment)의 영원한 서포터인 서포트프래그먼트매니저(SupportFragmentManager), 차일드프래그먼트매니저(ChildFragmentManager)가 하는 역할을 네비게이션 아키텍처 컴포넌트에 위임할 수 있습니다.

#### 네비게이션 정의

```xml
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    app:startDestination="@id/mainFragment">

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.seroo.gyooha.navigationexample.ui.main.MainFragment"
        android:label="fragment_main"
        tools:layout="@layout/fragment_main" >
        <deepLink app:uri="test://main" />
        <argument
            android:name="test"
            android:defaultValue="0"
            app:type="integer" />
    </fragment>
</navigation>
```

#### 액티비티(Activity) 정의

```xml
<fragment
      android:id="@+id/fm_activity_main"
      android:name="androidx.navigation.fragment.NavHostFragment"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:defaultNavHost="true"
      app:navGraph="@navigation/nav_graph"
```

```kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        tb_activity_main.title = getString(R.string.app_name)

        setUpBottomNavigation((supportFragmentManager
            .findFragmentById(R.id.fm_activity_main) as NavHostFragment).navController)
    }

    private fun setUpBottomNavigation(navController: NavController) {
        NavigationUI.setupWithNavController(bn_activity_main, navController)
    }
}
```

#### 프래그먼트(Fragment) 이동

```kt
 // 이곳의 프래그먼트 Id는 네비게이션 XML에서 행동을 정의한 프래그먼트의 Id 입니다.
 button.setOnClickListener { Navigation.findNavController(it).navigate(R.id.mainFragment, null) }
```

* 엔드포인트(EndPoint)를 이용하여 프래그먼트(Fragment)에서 액티비티(Activity)로 지정할 수 있습니다.
* 네비게이션(Navigation) 안에서 액티비티(Activity)간 이동은 허용하지 않습니다.(아래 그림 참고)

<img src="/files/2018-06-11-google-io/error1.png" width="300" alt>

더 자세한 코드는 깃허브에 정리했습니다. [네비게이션 예제](https://github.com/gyooha/NavigationExample.git)를 참고해주세요.

### [슬라이스(Slices)](https://developer.android.com/guide/slices/)

<img src="http://img.youtube.com/vi/a7IVH5aNwwc/0.jpg" width="480" alt>

슬라이스(Slices)는 외부에 콘텐츠를 공유하거나, 공유받아 사용할 수 있는 라이브러리입니다. 슬라이스 콘텐츠(Slices Content)가 정의되어 있는 다른 앱의 콘텐츠를 슬라이스 프로바이더(Slices Provider)를 통해 가져올 수 있으며, 화면에 출력한 컨텐츠는 정의된 것에 한해 자유롭게 사용할 수 있습니다.

#### 슬라이스 URI 분류

```kt
override fun onBindSlice(sliceUri: Uri?): Slice {
        return when (sliceUri?.path) {
            "/temperature" -> createTemperatureSlice(sliceUri)
            else -> throw IllegalStateException("is Not exist")
        }
    }
```

#### 슬라이스 펜딩인텐트(PendingIntent) 제작

```kt
  private fun getChangeTempIntent(value: Int): PendingIntent =
        Intent(ACTION_CHANGE_TEMP).apply {
            setClass(context, MyBroadcastReceiver::class.java)
            putExtra(EXTRA_TEMP_VALUE, value)
        }.let {
            PendingIntent.getBroadcast(context, reqCode++, it, PendingIntent.FLAG_UPDATE_CURRENT)
        }
```
#### 슬라이스 UI

{'fraction_non_alphanumeric': 0.12551063530074658, 'fraction_numerical': 0.02253838568812509, 'mean_word_length': 3.9629500174764067, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 2, '>': 39, 'https://': 26, 'lorem ipsum': 0, 'www.': 0, 'xml': 12}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5038361', 'n_tokens_mistral': 8383, 'n_tokens_neox': 9972, 'n_words': 1330}