[go: up one dir, main page]

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 곽동현(Machine Learning GDE)님이 참여해 주셨습니다.>

게시자: Reena Jana(Business Inclusion 크리에이티브 책임자), Josh Lovejoy(Google Research UX 디자이너)

기계 학습 시스템은 점점 더 일상 생활의 많은 측면에 영향을 미치고 있으며, 전 세계 사람들에게 서비스를 제공하는 하드웨어 및 소프트웨어 제품에서 모두 활용되고 있습니다. 따라서 모든 이에게 유용하고 접근성이 뛰어난 제품을 만들려고 애쓰는 연구자와 디자이너는 보통 전 세계 사용자의 다양성과 배경을 반영하는 데이터세트를 찾아야 하는 과제에 직면할 때가 많습니다. 이러한 기계 학습 시스템을 훈련시키기 위해서는 전 세계적으로 공개되어 있는데다, 점점 더 늘어나는 데이터세트가 필요합니다.

최근 6개월 동안 우리는 Quick, Draw!의 사용자를 통해 이러한 데이터세트가 생성되는 것을 지켜보았습니다. Quick, Draw!는 전 세계의 폭넓은 잠재고객들이 신경망의 작동 방식을 이해하는 데 도움을 주기 위해 Google이 택한 최신 접근 방식입니다. Google 직원으로 구성된 그룹이 누구나 나무와 머그잔 같이 흔히 볼 수 있는 물체를 그려서 재미있게 기계 학습 시스템과 상호작용할 수 있는 방법으로 Quick, Draw!를 설계했습니다. 이 시스템은 그림이 묘사하는 것이 무엇인지 20초 내에 알아맞히려고 시도합니다. Quick, Draw!의 목표는 단순히 기계 학습을 기반으로 실행되는 재미있는 게임을 만드는 것이었지만, 그 결과 브라질에서 일본, 그리고 미국을 거쳐 남아프리카에 이르기까지 100개국에서 2천만 명의 사람들로부터 8억 개의 그림을 확보했습니다.

이제 우리는 전 세계 사람들이 이러한 데이터를 활용하여 분석하고 제품 디자인에 기여할 수 있도록 광범위하게 확보한 그림을 기반으로 오픈 데이터세트를 선보이려고 합니다. 이 데이터세트에는 현재 Quick Draw! 게임 플레이어들이 생성한 5천만 개의 그림이 포함되어 있습니다(앞으로도 계속해서 일정 기간 동안 8억 개의 그림을 더 공개할 예정).

이는 상당한 양의 데이터이며, (1) 기술적 배경에 관계없이 기계 학습 시스템을 훈련시키고 (2) 폭넓은 범위의 문화와 관점을 반영하는 오픈 데이터세트를 구축하는 데 다양한 사람들이 참여하도록 유도한 방법을 볼 수 있는 절호의 기회이기도 합니다.


국가별 및 전 세계적 차원의 패턴을 한눈에 보기

이 데이터세트 내에서 시각적 패턴을 빠르고 효율적으로 파악하기 위해, 우리는 아티스트인 Kyle McDonald 씨와 협력하여 전 세계에서 확보한 수천 개의 그림을 오버레이했습니다. 이 작업은 우리가 합성 이미지를 만들고 국가별 추세는 물론 전 세계적인 추세를 파악하는 데에도 도움이 되었습니다. 우리는 이 데이터를 통해 시각적 추세를 찾아낸 방법을 보여 주기 위해 전 세계적으로 확보한 고양이와 의자 그림 1,000개를 각각 겹쳐서 애니메이션을 제작했습니다(아래 참조).

전 세계에서 확보한 1,000개의 그림으로 만든 고양이 모습:
전 세계에서 확보한 1,000개의 그림으로 만든 의자 모습:
고양이(또는 나무, 무지개, 해골 등)와 같이 원래 많이 그려지는 물체를 대강 그린 그림은 여러 문화권에서 대동소이하게 보이는 경우가 많았습니다.
하지만 특정 문화권에서만 친숙하고 다른 문화권에서는 그렇지 않은 물체는 눈에 띄는 차이를 보였습니다. 샌드위치는 윤곽이 뚜렷한 형태를 띠거나 선이 마구 뒤섞인 형태였으며, 머그잔 손잡이는 방향이 서로 반대로 그려지기도 했고, 의자는 정면 방향이나 측면 방향으로 그려져 있었습니다.

모든 상황에 맞는 해답이란 없음

우리는 이러한 합성 그림이 샌드위치에 사용된 빵의 종류부터 커피잔의 모양, 그리고 시각적으로 눈길을 끌도록 물체를 묘사하는 방법을 나타내는 미적 요소에 이르기까지 다양한 지역의 잠재고객 사이에서 관점과 선호 사항이 어떻게 다른지를 드러낼 수 있다는 사실을 깨달았습니다. 예를 들어, 일부 국가에서는 더 간단하게 표현되는 정면 모습을 그리는 일관된 경향이 나타난 반면에, 측면 모습을 그리는 일관된 경향성이 보이는 국가도 있었습니다.

이러한 이미지를 오버레이함으로써 데이터의 다양성이 부족할 때 신경망을 훈련시키는 방식을 개선할 방법도 알 수 있었습니다. 참고로, 데이터 다양성 부족 문제는 전 세계에서 확보한 대규모 오픈 데이터세트에서 조차 나타납니다. 예를 들면, Quick, Draw! 데이터세트에서 115,000개가 넘는 신발 그림을 분석한 결과, 스니커와 비슷한 형태의 단 한 가지 신발 스타일이 압도적으로 많이 표현된 것을 확인했습니다. 이 신발 스타일이 많이 그려졌기 때문에 신경망은 스타일만 '신발'로 인식하도록 학습되었습니다.

하지만 실제 세계에서와 마찬가지로, 데이터 훈련 영역에서도 모든 상황에 맞는 해답이란 건 없습니다. 우리는 '어떻게 하면 일관되면서도 효율적으로 데이터세트를 분석하여 잠재적 편향을 파악할 수 있는 단서를 찾을 수 있을까?' 라고 자문했습니다. 그리고 '팀이 다양성이 부족한 데이터세트를 기반으로 분류기를 만든다면 어떻게 될까?' 라는 질문에 대해서도 생각해 봤습니다.


데이터의 포괄성 진단

Google PAIR 이니셔티브의 일환으로 지난달에 발표한 오픈소스 도구인 Facets를 사용하면 대규모 데이터세트에서 패턴을 신속하게 파악할 수 있습니다. 이 도구의 목표는 Quick, Draw! 데이터세트와 같이 대규모 데이터세트의 대표성을 효율적이고 시각적으로 진단하는 것입니다.

다음은 Facets 도구 내의 Quick,Draw! 데이터세트를 보여 주는 스크린샷입니다. 이 도구는 수천 개의 그림을 국가(최대 100개국까지 지원)와 같은 특징 값을 기준으로 여러 차원에 'faceting' 하여 배치하는 데 도움이 되었습니다. 또한, 10개의 국가를 포함하는 뷰에서 '임의의 얼굴'과 같은 특징을 필터링한 후 100개의 국가로 확장할 수도 있습니다. 이에 따라 국가별 표현이 차지하는 비율을 한눈에 파악할 수 있습니다. 뿐만 아니라, 각각의 개별 그림을 확대하여 세부 사항을 확인함으로써 하나의 데이터 요소를 더욱 상세히 분석할 수도 있습니다. 이는 연구자가 미묘한 차이점 또는 이적인 부분을 찾아내거나 대규모 데이터세트 내에서 나중에 패턴으로 등장할 수 있는 아주 작은 시각적 추세에 대한 플래그 지정을 시작할 수 있도록 하므로, 특히 Quick, Draw!와 같은 대규모 시각적 데이터세트로 작업할 때 유용합니다.


다음은 '임의의 얼굴'에 대한 동일한 Quick, Draw! 데이터가 94개 국가에 대해 faceted되고 또 다른 뷰에 표시된 형태입니다. 아주 잠깐만 봐도 Facets이 그림을 로드한 이 새로운 시각화 형태에서 미국과 유럽 국가를 나타내는 데이터가 압도적으로 많다는 점이 분명히 드러납니다. 이는 Quick, Draw! 게임이 현재 영어로만 제공된다는 점을 간주하면 논리적으로 당연한 결과입니다. 우리는 차츰 언어를 더 추가할 계획입니다. 하지만 이 시각화에서는 데이터 내에서 영어 이외의 언어를 모국어로 사용하는 국가 중 브라질과 태국이 상대적으로 제대로 표현된 국가인 것처럼 보입니다. 이는 디자이너가 인터페이스 디자인의 어느 요소가 이러한 국가에서 제대로 작동했을지 분석할 여지가 있음을 시사했습니다. 그런 다음, 우리는 이 정보를 활용하여 전 세계에서 영어 이외의 언어를 모국어로 사용하는 다른 잠재고객에 대해 다음에 반복해서 이루어질 과정에서 Quick,Draw!를 향상시킬 수 있을 것입니다. 또한, 앞으로의 번역 작업에서 어떤 현지 언어를 우선적으로 처리할 지 결정하는데 도움이 되도록 이처럼 faceted된 데이터를 활용하고 있습니다.


Quick, Draw! 데이터의 포괄성을 진단하는 데 Facets을 사용하여 얻은 또 다른 성과는 누구나 데이터의 다양성을 향상시킬 수 있는 확실한 방법을 파악하고 잠재적인 편향을 확인하는 것이었습니다. 다음과 같은 개선 사항이 포함될 수 있습니다.
  • 데이터가 현지 또는 전 세계인을 더욱 정확하게 나타내도록 데이터 또는 콘텐츠 생성에 대한 인적 평가의 프로토콜 변경
  • 데이터의 하위 그룹을 분석하고 시각적 패턴 내에서 드러나는 '교차성'과 동일한 데이터베이스 식별
  • 더욱 포괄적일 수 있도록 데이터 증대 및 가중치 조정
우리는 이러한 데이터세트와 Facets 등의 도구를 발표함으로써 기계 학습에 더욱 포괄적인 접근 방식 탐구를 촉진하고 이러한 관찰을 혁신을 이룰 수 있는 기회로 바꿀 수 있기를 바랍니다. 우리는 Quick, Draw!와 Facets를 통해 이제 막 통찰력 있는 정보를 도출하기 시작했습니다. 여러분도 우리와 함께 더 많은 결과를 끌어내는 활동에 동참하시기 바랍니다.

감사의 말

Jonas Jongejan, Henry Rowley, Takashi Kawashima, 김종민, Nick Fox-Gieg 씨에게 Google Creative Lab 및 Google의 Data Arts Team과 협력하여 Quick, Draw!를 빌드해 주신 점에 대해 감사의 인사를 드립니다. 기계 학습의 공정성에 대한 동영상을 제작해 주신 Google Creative Lab의 Teo Soares, Alexander Chen, Bridget Prophet, Lisa Steinman 및 JR Schmidt 씨에게도 감사의 말을 전합니다. PAIR의 James Wexler, Jimbo Wilson 및 Mahima Pushkarna 씨에게는 Facets를 설계해 주신 점에 대해, Google Brain 팀의 선임 연구원인 Martin Wattenberg 및 Fernanda Viégas 씨와 UX 연구원인 Jess Holbrook 씨에게는 프로젝트를 이끌어 주신 점에 대해 감사의 인사를 드립니다. Google Cloud 팀의 Ian Johnson 씨에게는 오버레이된 그림에 대한 시각화 작업에 한몫을 해 주신 점에 대해 고맙다는 인사를 드립니다.

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 양찬석(Google)님이 참여해 주셨습니다.>
게시자: Edward Cunningham, Android Security 제품 관리자
눈치가 빠른 사용자라면 안드로이드 O에서 기존 "알 수 없는 소스" 허용 설정이 없어진 것을 알아차렸을 것입니다. 이를 대신에 Install unknown apps 권한이 추가되었습니다. 새로운 보안 모델이 어떤 이점이 있는지 살펴보겠습니다.

올해 초 구글은 안드로이드 디바이스가 항상 잠재적인 악성 앱으로부터 보호 받을 수 있도록, Google Play Protect를 선보였습니다. 일반적으로 Google Play를 통해 설치되는 앱은 안전하며, 잠재적으로 유해한 앱(PHA)은 대부분 다른 외부 소스를 통해 설치됩니다.

PHA 작성자는 일반적으로 적대적 다운로더(Hostile Downloader)를 통해 앱을 제공하는 것입니다. 예를 들어, 어떤 게임 앱이 자체적으로 악성 코드를 포함하고 있진 않지만, 중요 보안 업데이트로 가장한 PHA를 설치하라는 알림을 표시할 수 있습니다. (적대적 다운로더에 대한 자세한 내용은 안드로이드 보안 2016 연간 검토에서 확인할 수 있음). 알 수 없는 소스에서 제공되는 앱의 설치를 허용한 사용자는 이러한 기만적인 공격에 취약해집니다.

왼쪽(안드로이드 O 이전): 시스템 업데이트를 가장한 PHA 설치 화면입니다.
오른쪽(안드로이드  O): PHA가 설치되기 전에 먼저 사용자가 설치를 트리거한 앱에 권한을 부여해야 합니다.

Install unknown apps 권한을 통해, 어떤 앱이 앱 설치를 요청하는지 미리 확인하고, 잠재적인 위험을 줄일 수 있습니다. 이 권한은 다른 런타임 권한과 마찬가지로 설치를 요청하는 앱에 연결됩니다. 그리고 사용자가 해당 권한을 부여해야만, '앱 설치 메시지'를 표시할 수 있습니다. 다시말해, 안드로이드 O 이상 버전에서는 사용자에게 명시 권한을 받기 전에 사용자가 앱을 설치하도록 속일 수 없습니다.

이와 동시에, 사용자가 직접 신뢰할 수 있는 소스로부터 앱 설치를 허용할 수 있도록 간편하고 투명한 제어 기능이 제공됩니다. 설정에서 사용자가 앱 설치 권한을 승인한  앱 목록이 표시됩니다. 사용자는 원하는 경우 언제든지 부여한 권한을 취소할 수 있습니다.

사용자는 원하는 경우 언제든지 알 수 없는 앱 설치를 허용한 앱을 검토할 수 있습니다. 권한 부여 프로세스를 더욱 쉽게 하기 위해, 앱 개발자는 설치 흐름의 일부로 사용자에게 사용자 권한 화면을 표시할 수 있습니다.

개발자가 수행할 변경 작업

패키지 설치 프로그램을 통해 다른 앱을 다운로드하고 설치할 수 있는 기능이 필요한 앱 개발자는 다음 변경 사항을 확인해야 합니다. 앱이 26 이상의 targetSdkLevel을 사용하고 사용자에게 다른 앱을 설치하라는 메시지를 표시하는 경우 다음과 같이 매니페스트 파일에 REQUEST_INSTALL_PACKAGES 권한이 포함되어야 합니다.
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

이 권한을 선언하지 않은 앱은 다른 앱을 설치할 수 없습니다. 이는 다른 앱을 설치할 의도가 없는 앱을 보호할 수 있는 방법이기도 합니다. ACTION_MANAGE_UNKNOWN_APP_SOURCES 인텐트를 사용하여 사용자에게 Install unknown apps 권한 설정 화면을 표시할 수 있습니다. 또한, PackageManager canRequestPackageInstalls() API를 사용하여 이 권한의 상태를 쿼리할 수도 있습니다.

Google Play에서 배포되는 앱에는 Play 정책이 적용된다는 점에 유의하세요. 대부분의 경우 앱 내에서 다른 앱을 직접 다운로드하거나 설치하는 동작은 허용되지 않으며, 대신 Play Store의 앱 목록을 바로가는 딥 링크를 제공해야 합니다.

업데이트된 게시 가이드를 확인하시기 바랍니다. 여기에는 알 수 없는 앱 설치에 대한 자세한 내용이 나와 있습니다. 안드로이드 O에서 보안 강화에 관해 추가로 게시되는 글도 계속해서 살펴보시기 바랍니다.

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 양찬석(Google)님이 참여해 주셨습니다.>
게시자: Maru Ahues Bouza, Google Play 개발자 관계 파트너
안드로이드 인스턴트 앱은 더욱 풍부하고 자연스러운 사용자 경험을 제공합니다. 앱을 미리 설치하지 않아도 체험해 볼 수 있으므로 사용자 참여를 촉진할 수 있습니다. 하지만 모바일 웹페이지와 비슷한 속도로 앱이 실행되기 위해서는, 앱을 빠르게 다운로드하고 실행할 수 있어야 합니다. 이를 위해, 특정 URL에 대한 응답으로 로드되는 바이너리를 가급적 작게(4MB 이하로) 유지해야 합니다. 바이너리가 작을수록 인스턴트 앱은 더 신속하게 설치되고, 더 쾌적한 사용자 경험을 제공할 수 있습니다. 이 문서에서는 애플리케이션 구조와 바이너리 크기를 관리하는 데 참고할 수 있는 모범 사례를 공유합니다. 설명된 내용들은 설치 가능한 앱의 바이너리 크기를 최적화하는데도 적용될 수 있습니다.

코드베이스 리팩터링

앱 바이너리 크기를 효율적으로 관리하기 위해, 앱을 기능 모듈(Feature Module) 단위로 리팩터링 하는 것이 권장됩니다. 앱 바이너리 크기가 작고, 제공하는 기능이 많지 않은 경우도 그렇습니다. 새로운 기능을 추가해야할 때, 기존 앱 바이너리 크기에 영향을 주지 않고 더 많은 기능을 신속하게 추가할 수 있습니다. 인스턴트 앱을 위한 별도의 코드 베이스를 만드는 대신, 설치 가능한 애플리케이션과 인스턴트 애플리케이션을 모두 생성하는 통합된 모듈형 코드베이스를 구축할 수 있습니다. 개별 프로젝트와 코드를 유지해야 하는 부담이 줄어들고 두 애플리케이션에 걸쳐 깔끔하게 프로젝트 구조를 만들 수 있습니다.

인스턴트 앱을 미리 적용한 파트너의 경험을 바탕으로 생각해 볼 때, 코드베이스 리펙터링 작업이 다운로드 되는  바이너리 크기에 가장 큰 영향을 미칠 거라 생각합니다. 하지만 동시에 가장 큰 투자가 필요한 부분이기도 합니다. 성공적인 코드베이스 리팩터링을 위한 한 가지 팁은, 단일(기본) 모듈부터 시작한 후 관련 부분을 기능 모듈로 이전하는 방식으로 리팩터링을 진행하는 것 입니다.

참고로, 인스턴트 앱의 크기 제한은 로컬로 빌드된 바이너리에 적용되지 않으므로 인스턴트 앱을 개발하는 동안 바이너리 크기에 대해 염려할 필요는 없습니다. Play Developers Console을 통해 바이너리를 개발 트랙(개발 과정에서 인스턴트 앱을 신속히 배포할 수 있는 특별 트랙)에 게시할 수도 있습니다. 개발 트랙의 크기 제한은 10MB이고, [1, 2] 바이너리가 개발 트랙을 거치고 나면 4MB 제한이 적용됩니다.

각 기능 모듈에는 주어진 URL에 대응하는 진입점(즉, Activity)이 하나 이상 있을 수 있습니다. 단일 코드베이스를 다중 모듈로 분할할 때 기능마다 각기 다른 진입점을 구성할 수 있으며, 필요에 따라 관련 기능을 추가로 로드할 수 있습니다. 특정 진입점에 다운로드해야 하는 총 바이너리는 4MB 미만이어야 하므로, 기능 모듈과 기본 모듈을 합친 크기가 4MB 미만이어야 한다는 점을 유의하시기 바랍니다.


각각의 기능과 기능을 수행하기 위한 Activity, 및 해당 기능에 진입하기 위한 URL 매핑을 먼저 정의한 후각 진입점에 대한 바이너리 크기를 줄이는 방향으로 리팩터링 작업을 구성하는 것이 좋습니다.

라이브러리를 어떻게 포함할지도 고려해야합니다. 특정 기능 모듈에만 필요한 라이브러리의 경우 기본 기능 모듈에 추가하는 대신, 해당 기능 모듈에만 라이브러리를 포함시킬 수 있습니다. 예를 들어 라이브러리 X, Y, Z에 종속되는 애플리케이션이 있다고 가정해 봅니다. 그러면 모든 종속 사항을 기본 모듈의 gradle.build 파일에 정의하여, 기본 모듈에 모든 라이브러리를 패키징할 수 있습니다. 하지만 기능 모듈의 코드에 라이브러리 Z만 필요한 경우 기본 모듈에서 해당 종속 사항만 기능 모듈로 이동하는 것이 합리적입니다. 여러 기능 모듈이 같은 라이브러리를 사용하는 경우에는 기본 모듈에 라이브러리를 유지하는 것이 좋습니다.



Lint 검사

많은 앱이 앱 내에 정의된 리소스 중 일부만을 사용합니다. 안드로이드 스튜디오에서는 사용되지 않는 리소스에 대한 Lint 검사가 기본적으로 제공됩니다. Alt+Ctrl+Shift+I(Mac OS의 경우 Cmd+Alt+Shift+I)를 누르고, 'unused resources'를 입력한 후 'Unused resources Android|Lint|Performance' 검사를 시작합니다. 이 검사는 설치 가능한 APK의 크기를 줄이는 데도 도움이 됩니다.



문자열 리소스

리소스와 유사하게, 문자열도 주의해야 합니다. 문자열 중에는 사용되고 있지 않은 문자열도 있을 수 있습니다. 일반적으로, 사용되지 않는 문자열 리소스를 제거하면 애플리케이션 크기를 상당히 줄일 수 있습니다. 애플리케이션이 다중 언어를 지원하는 경우 현지화된 리소스의 수를 줄이고자 할 수 있습니다. 그러면 일반적으로 리소스 자산에서 상당히 많은 양이 제거됩니다. 이는 앱이 몇 개의 언어만 지원하는데 여러 언어로 된 메시지를 포함하는 AppCompat 라이브러리를 사용하는 경우 특히 중요합니다. resConfig를 사용하여 특정 리소스 구성만 선택할 수 있습니다.

힌트: 일반적으로 'auto'를 사용하여 타사 라이브러리에서 가져오는 구성을 제한할 수 있습니다.

WebP로 전환

PNG 대신 WebP 이미지로 전환하면 Drawable Resource 크기를 상당히 줄일 수 있습니다. 안드로이드 인스턴트 앱은 WebP 형식의 모든 기능(투명성, 무손실 등)을 지원합니다. 다만, 애플리케이션 런처 아이콘은 PNG 형식을 사용해야 합니다. 일반적으로 앱 아이콘은 mipmap- 디렉토리에 저장됨으로 큰 문제는 없을 것 입니다. 이전 버전과 호환 가능한 솔루션이 필요한 경우, APK 모듈에 원래 PNG 이미지를 포함해야 하며 그러면 WebP 리소스가 자동으로 재정의됩니다(기본 소스 집합이 AAR/기능 모듈의 모든 리소스를 재정의함). [4]




물론, VectorDrawable을 사용하면 훨씬 더 많은 공간을 절약할 수 있지만 VectorDrawable을 사용하는 데는 코드 변경이 필요합니다. 반면, 위에 언급한 인스턴트 앱에는 WebP 이미지를 사용하고 설치 가능한 APK에는 PNG 이미지를 사용하는 트릭의 경우 코드를 수정할 필요가 없습니다.

런타임에 Asset 다운로드

인스턴트 앱 APK에 모든 리소스를 패키징할 필요는 없습니다. 애플리케이션이 실행 중에 추가 Asset을 다운로드할 수 있기 때문입니다. 이 접근 방법을 통해 앱은 필요한 Asset을 다운로드할 수 있습니다. 코드베이스를 상당히 변경해야 할 수 있지만, APK의 크기 감소에 큰 도움이 됩니다. 리소스를 축소해도 앱 기능 모듈 크기가 제한보다 낮게 줄어들지 않는다면, 이러한 방법을 검토해볼 수 있습니다.

네이티브 라이브러리 검토

사용중인 라이브러리에는 인스턴트 앱에서 전혀 사용되지 않는 네이티브 코드가 포함되어 있을 수 있습니다. 따라서 첫 번째 단계로 APK 내에 패키징된 네이티브 라이브러리를 검토하여 인스턴트 앱에 실제로 사용되는 라이브러리만 포함되어 있는지 확인해야 합니다. APK Analyzer(Build -> APK Analyzer…)를 사용하여 컴파일된 APK를 살펴봐야 합니다. [5]



외부 라이브러리 검토

다음으로, 앱의 코드와 연결된 모든 외부 라이브러리의 목록을 검토합니다. 의존성 전이 (transitive dependencies)에 의해 몇몇 예기치 않은 항목이 포함되어 있을 수 있습니다. 의존성 전이는 프로젝트가 참조하는 라이브러리가 다른 라이브러리를 참조하고 있는데, 그 다른 라이브러리가 또 다른 라이브러리에 종속될 수 있을 때 발생합니다. 때로는 이러한 의존성 전이 과정에서 전혀 필요하지 않은 라이브러리(예: 코드에서 절대 사용하지 않는 JSON 처리 라이브러리) 같은 예기치 않은 항목이 포함될 수 있습니다. 자세한 내용은 Gradle 사용자 가이드의 '의존성 전이 항목 제외' 섹션을 참조하세요.
안드로이드 스튜디오에는 프로젝트의 외부 종속 항목 분석에 사용할 수 있는 여러 가지 유용한 도구가 포함되어 있습니다. 어떠한 경우든 Project 뷰부터 살펴보면 도움이 됩니다.



'Project' 뷰에는 'External libraries'라는 섹션이 표시됩니다. 여기서 의존성 전이 항목을 포함하여 프로젝트에서 사용되는 모든 라이브러리를 볼 수 있습니다.


기본 기능 모듈의 크기를 더 줄이려면 코드 종속 항목과 외부 라이브러리에 유의해야 합니다. 'Project' 뷰를 확인하고 프로젝트에 필요하지 라이브러리를 찾습니다. 또한, 같은 기능을 제공하는 라이브러리도 찾습니다(예: 이미지 로드/캐싱을 지원하는 여러 라이브러리). [4]

APK Analyzer 도구를 사용하여 여러 빌드를 비교할 수도 있습니다. 이는 인스턴트 APK에도 효과가 있습니다.



마지막으로, 의존성 전이 항목을 검토하고 필요하지 않은 항목을 제외합니다. gradle -q :MODULE:dependencies --configuration compile 명령어를 사용하여 종속 항목 그래프를 검토합니다. 자세한 내용은 Gradle 문서에서 확인할 수 있습니다.

기타 팁

안드로이드 스튜디오 3.0에는 App Links Assistant 도구가 포함되어 있습니다. 이 도구는 필요한 인텐트 필터를 생성하는 데 도움이 될 수 있으며 프로젝트를 여러 모듈로 분할하는 데도 도움이 됩니다. [3]





크기 제한을 초과하지 않는 크기의 인스턴트 앱 번들을 구축했으면 이제는 빌드 프로세스가 최신 상태인지 확인하세요. 애플리케이션 패키지와 인스턴트 앱 APK가 'APK Signature Scheme v2'를 사용하여 서명되었는지 확인합니다. 최신 버전의 SDK 도구를 사용하여 APK를 서명하면 모든 작업이 자동으로 수행됩니다. 하지만 빌드 아티팩트를 수동으로 서명하는 경우에는 jarsigner를 사용하지 말고 그 대신 apksigner로 전환해야 합니다.

또한, 인스턴트 런타임 환경에 맞게 앱 코드를 변경하는 데 활용할 수 있는 유용한 팁이 몇 가지 있습니다. InstantApps.isInstantApp(...)을 기반으로 인스턴트/설치 가능한 애플리케이션에 대해 작은 코드 분기를 구성할 수 있습니다. 또한, 공유 인텐트를 사용할 때는 코드가 기기에 설치된 애플리케이션을 명시적으로 열거하지 않는지 확인하세요. 인스턴트 앱 보안 모델에서 이를 허용하지 않습니다. 간단히 일반 Intent.createChooser()를 사용하여 가능한 모든 작업 목록을 사용자에게 표시하면 됩니다.

기존 안드로이드 애플리케이션용 인스턴트 앱을 개발하는 데 필요한 작업은 개발자에 따라 다르며, 애플리케이션이 현재 구성된 방식에 따라 상당한 영향을 받습니다. 몇몇 경우, 프로젝트가 이미 다중 모듈로 구성되어 있으므로 쉬울 것입니다.

다른 개발자의 안드로이드 인스턴트 앱 사용 사례

끝으로, 인스턴트 앱을 이미 적용한 개발자들이 공유한 다음 정보를 참고해보시기 바랍니다.
안드로이드 개발자 웹사이트를 방문하여 안드로이드 인스턴트 앱 작업을 시작해 보고 다른 개발자가 들려주는 인스턴트 앱 성공 사례를 더 확인해 보시기 바랍니다.

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 도창욱(Web Technologies GDE)님이 참여해 주셨습니다.>


Firebase Admin SDK for Go가 정식 출시되었습니다. 기존에 지원 중인 자바, Python 및 Node.js외에 Admin SDK 제품군에 추가되는 네 번째 프로그래밍 언어입니다. 애플리케이션 개발자는 Firebase Admin SDK를 통해 신뢰할 수 있는 환경에서 프로그래밍을 통해 Firebase 서비스에 액세스할 수 있습니다. Firebase Admin SDK는 Firebase client SDK를 보완하여 최종 사용자가 자신의 웹브라우저와 휴대기기에서 Firebase에 액세스할 수 있도록 지원합니다. Firebase Admin SDK for Go의 초기 릴리스에서는 맞춤 토큰(Custom Token) 작성 및 ID 토큰 인증과 같은 몇 가지 Firebase 인증 기능이 함께 제공됩니다.


Admin SDK for Go 초기화

다른 Firebase Admin SDK와 유사하게 Go Admin SDK는 다양한 인증 자격 증명과 클라이언트 옵션을 사용하여 초기화할 수 있습니다. 다음 코드 스니펫은 Firebase 콘솔 또는 Google Cloud 콘솔에서 얻은 서비스 계정 자격 증명을 사용하여 SDK를 초기화하는 방법을 보여 줍니다.

import (
  "golang.org/x/net/context"

  firebase "firebase.google.com/go"
  "google.golang.org/api/option"
)

opt := option.WithCredentialsFile("path/to/key.json")
app, err := firebase.NewApp(context.Background(), nil, opt)

Google App Engine 또는 Google Compute Engine과 같은 Google 인프라에서 코드를 실행하는 경우에는 SDK가 해당 환경에서 애플리케이션 기본 자격 증명을 자동으로 검색할 수 있습니다. 이 경우에는 Go Admin SDK를 초기화할 때 자격 증명의 명시적인 지정이 필요 없습니다.
import (
  "golang.org/x/net/context"

  firebase "firebase.google.com/go"
)

app, err := firebase.NewApp(context.Background(), nil)


맞춤 토큰 작성 및 ID 토큰 인증

Firebase Admin SDK for Go의 초기 릴리스에서는 맞춤 토큰 작성Firebase ID 토큰 인증이 지원됩니다. 맞춤 토큰 작성 기능을 통해 자체적인 사용자 저장소 또는 인증 메커니즘을 사용하여 사용자를 인증할 수 있습니다.

client, err := app.Auth()
if err != nil {
  return err
}

claims := map[string]interface{}{
  "premium": true,
  "package": "gold",
}
token, err := client.CustomToken("some-uid", claims)

그 결과로 생성되는 맞춤 토큰은 클라이언트 기기로 전송될 수 있으며, 그러면 클라이언트 기기에서 Firebase client SDK를 사용하여 인증 흐름을 초기화하는 데 이 토큰을 활용할 수 있습니다. 반면에 ID 토큰 인증은 서버에서 현재 로그인된 사용자를 보안 차원에서 식별하는 데 도움이 됩니다.

client, err := app.Auth()
if err != nil {
  return err
}

decoded, err := client.VerifyIDToken(idToken)
uid := decoded.UID

Firebase Admin SDK for Go를 사용하는 방법에 대한 자세한 내용은 Admin SDK 설정 가이드를 참조하세요.

다음 단계

사용자 관리 및 Firebase 클라우드 메시징과 같은 기타 유용한 API를 구현하여 Go Admin SDK의 기능을 더 확장할 계획입니다. 또한, 이 SDK는 오픈소스로 제공됩니다. 따라서 Github 리포지토리를 살펴보고, 문제를 보고하고 끌어오기 요청을 보내 개발 프로세스에 참여해 보시기 바랍니다. 모든 Golang 열혈 개발자 여러분들, Firebase로 즐겁게 코딩하시길 바랄게요!

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 박재훈(Google)님이 참여해 주셨습니다.>
게시자: TensorFlow 팀
TensorFlow 1.3에는 꼭 사용해봐야 할 다음 두 가지 중요한 기능이 도입되었습니다.
  • Datasets: 입력 파이프라인을 만드는(즉, 데이터를 프로그램으로 읽어오는) 완전히 새로운 방식입니다.
  • Estimators: TensorFlow 모델을 만드는 상위 수준(high-level)의 방식입니다. Estimators에는 일반 기계 학습 작업을 위해 미리 만들어둔 모델이 포함되어 있지만, 이런 모델을 사용하여 자신만의 맞춤 모델을 만들 수도 있습니다.

아래에서 이러한 모델이 TensorFlow 아키텍처에 어떻게 적합한지 확인할 수 있습니다. 이들을 함께 결합하면 손쉽게 TensorFlow 모델을 만들고 데이터를 피드할 수 있습니다.



예제 모델

이러한 기능을 살펴보기 위해 모델을 빌드하고 관련 코드 스니펫을 보여드리겠습니다. 훈련 및 테스트 파일을 얻기 위한 지침을 비롯하여, 전체 코드는 여기서 확인할 수 있습니다. 참고로, 이 코드는 Datasets와 Estimators가 기능적으로 작동하는 방식을 보여 주려고 작성한 것일 뿐, 최대의 성능을 고려하여 최적화한 코드는 아닙니다.

이 훈련된 모델은 네 가지 식물적 특징(꽃받침 길이, 꽃받침 너비, 꽃잎 길이, 꽃잎 너비)을 기준으로 붓꽃을 분류합니다. 추론 과정 중에 위의 네 가지 특징에 대한 값을 제공할 수 있으며, 모델에서는 꽃이 다음 세 가지 아름다운 변종 중 하나라고 예측하게 됩니다.
왼쪽에서 오른쪽으로: Iris setosa(제공: Radomil, CC BY-SA 3.0), Iris versicolor (제공: Dlanglois, CC BY-SA 3.0) 및 Iris virginica(제공: Frank Mayfield, CC BY-SA 2.0).

아래와 같은 구조로 심층 신경망 분류자를 훈련시킬 것입니다. 모든 입력 값과 출력 값은 float32이며, 여기서는 각 개별 붓꽃 종류의 확률을 예측하려는 것이므로 출력 값의 합계는 1이 됩니다.

예를 들어, Iris Setosa, Iris Versicolor, Iris Virginica에 대한 출력 결과가 각각 0.05, 0.9, 0.05일 수 있을 것입니다. 이는 Iris Versicolor일 확률이 90%임을 나타냅니다.

좋습니다! 이제 모델을 정의했으므로 Datasets와 Estimators를 사용하여 모델을 훈련시키고 예측하는 방법을 살펴봅시다.


Datasets 소개

Datasets는 TensorFlow 모델에 대한 입력 파이프라인을 만드는 새로운 방식입니다. 이 API는 feed_dict 또는 대기열 기반 파이프라인을 사용하는 것보다 훨씬 더 성능이 좋고 더욱 깔끔하며 사용하기 쉽습니다. Datasets는 종전과 같이 1.3에서도 tf.contrib.data에 있지만 1.4에서는 이 API를 코어로 옮길 예정입니다. 따라서 지금이 바로 이것을 시험해볼 최적의 시점입니다.

개략적으로 설명하자면 Datasets는 다음 클래스로 구성됩니다.

클래스 설명:
  • Datasets: 데이터세트를 생성하고 변환하는 메서드를 포함한 기본 클래스입니다. 이 클래스를 사용하여 메모리 내 데이터 또는 Python 생성기에서 데이터세트를 초기화할 수도 있습니다.
  • TextLineDataset: 텍스트 파일에서 줄을 읽어옵니다.
  • TFRecordDataset: TFRecord 파일에서 레코드를 읽어옵니다.
  • FixedLengthRecordDataset: 바이너리 파일에서 고정 크기 레코드를 읽어옵니다.
  • Iterator: 한 번에 하나의 데이터세트 요소에 액세스하는 방식을 제공합니다.

사용할 데이터세트

시작 단계로서, 먼저 모델을 피드하는 데 사용할 데이터세트를 살펴보도록 하겠습니다. CSV 파일에서 데이터를 읽어올 것이며, 행마다 5개의 값과 4개의 입력 값, 그리고 레이블을 포함하게 됩니다.

레이블은 다음과 같이 지정됩니다.
  • 0 - Iris Setosa
  • 1 - Versicolor
  • 2 - Virginica

데이터세트 표현

데이터세트를 설명하기 위해, 먼저 특징 목록을 생성합니다.
feature_names = [
    'SepalLength',
    'SepalWidth',
    'PetalLength',
    'PetalWidth']

모델을 훈련시킬 때는 입력 파일을 읽어와서 특징 및 레이블 데이터를 반환하는 함수가 필요합니다. Estimators를 사용하려면 다음 형식의 함수를 만들어야 합니다.
def input_fn():
    ...<code>...
    return ({ 'SepalLength':[values], ..<etc>.., 'PetalWidth':[values] },
            [IrisFlowerType])

반환 값은 다음과 같이 두 요소로 구성된 튜플로 구성되어야 합니다.
  • 첫 번째 요소는 각 입력 특징이 키이고 그 다음이 훈련 배치에 대한 값의 목록인 dict여야 합니다.
  • 두 번째 요소는 훈련 배치에 대한 레이블 목록입니다.

여기서는 입력 특징과 훈련 레이블로 구성된 배치를 반환할 것이므로 이는 반환문에 포함되는 모든 목록의 길이가 같을 것이라는 의미입니다. 기술적으로 설명하자면, 여기서 '목록'이라고 지칭한 것은 실제로는 1차원 TensorFlow 텐서를 의미합니다.

input_fn을 간단히 재사용할 수 있도록 몇 가지 인수를 추가하겠습니다. 이를 통해 각각 설정이 다른 입력 함수를 만들 수 있습니다. 이러한 인수는 꽤 간단합니다.
  • file_path: 읽어올 데이터 파일입니다.
  • perform_shuffle: 레코드 순서를 무작위로 할지 여부입니다.
  • repeat_count: 데이터세트에서 레코드에 대해 반복할 횟수입니다. 예를 들어, 1을 지정하면 각 레코드를 한 번만 읽어옵니다. None을 지정하면 영구적으로 계속 반복됩니다.

다음은 Dataset API를 사용하여 이 함수를 구현하는 방법입니다. 이후에 Estimator 모델을 피드할 때 적합한 '입력 함수'에 이 함수를 래핑합니다.
def my_input_fn(file_path, perform_shuffle=False, repeat_count=1):
   def decode_csv(line):
       parsed_line = tf.decode_csv(line, [[0.], [0.], [0.], [0.], [0]])
       label = parsed_line[-1:] # Last element is the label
       del parsed_line[-1] # Delete last element
       features = parsed_line # Everything (but last element) are the features
       d = dict(zip(feature_names, features)), label
       return d

   dataset = (tf.contrib.data.TextLineDataset(file_path) # Read text file
       .skip(1) # Skip header row
       .map(decode_csv)) # Transform each elem by applying decode_csv fn
   if perform_shuffle:
       # Randomizes input using a window of 256 elements (read into memory)
       dataset = dataset.shuffle(buffer_size=256)
   dataset = dataset.repeat(repeat_count) # Repeats dataset this # times
   dataset = dataset.batch(32)  # Batch size to use
   iterator = dataset.make_one_shot_iterator()
   batch_features, batch_labels = iterator.get_next()
   return batch_features, batch_labels

다음 사항을 참고하세요.
  • TextLineDataset: Dataset API는 파일 기반 데이터세트를 사용할 경우 많은 메모리 관리 작업을 자동으로 수행합니다. 예를 들어, 메모리보다 훨씬 큰 데이터세트 파일을 읽어오거나 목록을 인수로 지정하여 여러 파일을 읽어올 수 있습니다.
  • shuffle: buffer_size 레코드를 읽은 후 순서를 셔플(무작위 배정)합니다.
  • map: 데이터세트의 각 요소를 인수로 삼아 decode_csv 함수를 호출합니다(TextLineDataset를 사용하므로 각 요소가 CSV 텍스트의 한 줄이 됨). 그런 다음, 각 줄에 decode_csv 를 적용합니다.
  • decode_csv: 각 줄을 필드로 분할하고 필요한 경우 기본값을 제공합니다. 그런 다음, 필드 키 및 필드 값과 함께 dict를 반환합니다. 그러면 map 함수가 dict를 사용하여 데이터세트의 각 elem(줄)을 업데이트합니다.

지금까지 Datasets를 소개해 드렸습니다. 이제 재미 삼아 이 함수를 사용하여 첫 번째 배치를 인쇄 출력해 볼 수 있습니다.
next_batch = my_input_fn(FILE, True) # Will return 32 random elements

# Now let's try it out, retrieving and printing one batch of data.
# Although this code looks strange, you don't need to understand
# the details.
with tf.Session() as sess:
    first_batch = sess.run(next_batch)
print(first_batch)

# Output
({'SepalLength': array([ 5.4000001, ...<repeat to 32 elems>], dtype=float32),
  'PetalWidth': array([ 0.40000001, ...<repeat to 32 elems>], dtype=float32),
  ...
 },
 [array([[2], ...<repeat to 32 elems>], dtype=int32) # Labels
)

실제로 모델 구현을 위해 Dataset API에서 필요한 건 이게 전부입니다. 하지만 Datasets에는 많은 기능이 있습니다. 이 게시물의 끝부분에 추가 리소스를 모아 두었으므로 확인해 보세요.


Estimators 소개

Estimators는 이전에 TensorFlow 모델을 훈련시킬 때 작성해야 했던 상용구 코드를 상당히 줄여주는 상위 수준 API입니다. Estimators는 유연성도 매우 뛰어나므로, 이를 통해 모델에 특정한 요구 사항이 있을 경우 기본 동작을 재정의할 수 있습니다.

Estimators를 사용하여 모델을 빌드할 수 있는 방법으로는 다음 두 가지가 있습니다.
  • 미리 만든 Estimators - 미리 정의된 Estimators로, 특정 유형의 모델을 생성하려고 만든 것입니다. 이 블로그 게시물에서는 미리 만든 Estimators로서 DNNClassifier라는 것을 사용하겠습니다.
  • Estimator(기본 클래스) - model_fn 함수를 사용하여 모델 생성 방법을 완벽히 제어할 수 있습니다. 이 작업을 수행하는 방법은 별도의 블로그 게시물에서 설명해드릴 예정입니다.

다음은 Estimators의 클래스 다이어그램입니다.

향후 릴리스에서는 미리 정의된 Estimators를 더 많이 추가하려고 합니다.

여러분도 아실 수 있겠지만, 모든 Estimators가 Estimators에 입력 데이터를 제공하는 input_fn을 사용합니다. 여기서는 이런 목적으로 정의한 my_input_fn을 재사용하도록 하겠습니다.

다음은 붓꽃 종류를 예측하는 Estimator를 인스턴스화하는 코드입니다.
# Create the feature_columns, which specifies the input to our model.
# All our input features are numeric, so use numeric_column for each one.
feature_columns = [tf.feature_column.numeric_column(k) for k in feature_names]

# Create a deep neural network regression classifier.
# Use the DNNClassifier pre-made estimator
classifier = tf.estimator.DNNClassifier(
   feature_columns=feature_columns, # The input features to our model
   hidden_units=[10, 10], # Two layers, each with 10 neurons
   n_classes=3,
   model_dir=PATH) # Path to where checkpoints etc are stored

이제 훈련을 시작할 수 있는 Estimator가 생성되었습니다.


모델 훈련

다음과 같이 TensorFlow 코드 한 줄로 훈련을 수행할 수 있습니다.
# Train our model, use the previously function my_input_fn
# Input to training is a file with training example
# Stop training after 8 iterations of train data (epochs)
classifier.train(
   input_fn=lambda: my_input_fn(FILE_TRAIN, True, 8))

여기서 잠깐, 위의 "lambda: my_input_fn(FILE_TRAIN, True, 8)"은 도대체 무엇일까요? 바로 Datasets를 Estimators와 연결한 부분입니다! Estimators가 훈련, 평가 및 예측 작업을 수행하려면 데이터가 필요하며, input_fn을 사용하여 데이터를 가져옵니다. Estimators는 인수 없이 input_fn만 필요로 하므로, lambda를 사용하여 인수 없이 함수를 생성합니다. 이는 원하는 인수 file_path, shuffle setting,repeat_count를 사용하여 input_fn을 호출합니다. 여기서는 my_input_fn,을 사용하여 이를 전달합니다.
  • FILE_TRAIN - 훈련 데이터 파일입니다.
  • True - Estimators에 데이터를 셔플하도록 지시합니다.
  • 8 - Estimators에 데이터세트를 8회 반복하도록 지시합니다.

훈련된 모델 평가

좋습니다. 이제 훈련된 모델이 생성되었습니다. 이 모델이 얼마나 잘 작동하는지 어떻게 평가할 수 있을까요? 다행히도, 모든 Estimator에 evaluate 메서드가 포함되어 있습니다.
# Evaluate our model using the examples contained in FILE_TEST
# Return value will contain evaluation_metrics such as: loss & average_loss
evaluate_result = estimator.evaluate(
   input_fn=lambda: my_input_fn(FILE_TEST, False, 4)
print("Evaluation results")
for key in evaluate_result:
   print("   {}, was: {}".format(key, evaluate_result[key]))

여기서는 약 93%의 정확도를 달성했습니다. 물론, 이 정확도를 높일 수 있는 다양한 방법이 있습니다. 한 가지 방법은 프로그램을 단순히 계속 반복해서 실행하는 것입니다. 모델 상태는 위에서 다룬 model_dir=PATH 내에서 유지되므로 안정화될 때까지 더 많이 반복 훈련할수록 모델이 개선됩니다. 또 다른 방법은 숨겨진 계층의 수나 각각의 숨겨진 계층에 포함된 노드 수를 조정하는 것입니다. 이 방법을 마음대로 실험해 보시기 바랍니다. 단, 변경할 때 model_dir=PATH에 지정된 디렉토리도 제거해야 한다는 점에 유의하세요. DNNClassifier의 구조가 변경되기 때문입니다.

훈련된 모델을 이용한 예측

그게 전부입니다! 이제 훈련된 모델이 있으므로, 평가 결과에 만족한다면 이를 사용하여 몇 가지 입력 값을 기준으로 붓꽃을 예측할 수 있습니다. 훈련 및 평가와 마찬가지로, 단일 함수 호출을 사용하여 예측합니다.
# Predict the type of some Iris flowers.
# Let's predict the examples in FILE_TEST, repeat only once.
predict_results = classifier.predict(
    input_fn=lambda: my_input_fn(FILE_TEST, False, 1))
print("Predictions on test file")
for prediction in predict_results:
   # Will print the predicted class, i.e: 0, 1, or 2 if the prediction
   # is Iris Sentosa, Vericolor, Virginica, respectively.
   print prediction["class_ids"][0] 

메모리 내 데이터를 기반으로 하는 예측

위에 나와 있는 코드에서는 파일에 저장된 데이터를 기반으로 예측을 수행하도록 FILE_TEST를 지정했지만, 다른 소스, 예를 들어 메모리에 있는 데이터를 기반으로 예측하려면 어떻게 해야 할까요? 짐작하실 수 있겠지만, 이를 위해 실제로 predict 호출을 변경할 필요는 없습니다. 대신, 다음과 같이 메모리 구조를 사용하도록 Dataset API를 구성하면 됩니다.
# Let create a memory dataset for prediction.
# We've taken the first 3 examples in FILE_TEST.
prediction_input = [[5.9, 3.0, 4.2, 1.5],  # -> 1, Iris Versicolor
                    [6.9, 3.1, 5.4, 2.1],  # -> 2, Iris Virginica
                    [5.1, 3.3, 1.7, 0.5]]  # -> 0, Iris Sentosa
def new_input_fn():
   def decode(x):
       x = tf.split(x, 4) # Need to split into our 4 features
       # When predicting, we don't need (or have) any labels
       return dict(zip(feature_names, x)) # Then build a dict from them

   # The from_tensor_slices function will use a memory structure as input
   dataset = tf.contrib.data.Dataset.from_tensor_slices(prediction_input)
   dataset = dataset.map(decode)
   iterator = dataset.make_one_shot_iterator()
   next_feature_batch = iterator.get_next()
   return next_feature_batch, None # In prediction, we have no labels

# Predict all our prediction_input
predict_results = classifier.predict(input_fn=new_input_fn)

# Print results
print("Predictions on memory data")
for idx, prediction in enumerate(predict_results):
   type = prediction["class_ids"][0] # Get the predicted class (index)
   if type == 0:
       print("I think: {}, is Iris Sentosa".format(prediction_input[idx]))
   elif type == 1:
       print("I think: {}, is Iris Versicolor".format(prediction_input[idx]))
   else:
       print("I think: {}, is Iris Virginica".format(prediction_input[idx])

Dataset.from_tensor_slides()는 메모리에 적합한 작은 데이터세트용으로 설계되었습니다. 훈련 및 평가를 위해 그랬듯이 TextLineDataset를 사용하는 경우 메모리가 셔플 버퍼와 배치 크기를 감당할 수 있는 한 원하는 만큼 큰 파일을 사용할 수 있습니다.

덤으로 주어지는 이점

DNNClassifier와 같이 미리 만든 Estimator를 사용하면 많은 이점을 누릴 수 있습니다. 미리 만든 Estimators는 사용하기 쉬울 뿐 아니라 기본 제공 평가 측정항목도 제공하고, TensorBoard에서 확인할 수 있는 요약 정보도 생성합니다. 이러한 보고 내용을 보려면 다음과 같이 명령줄에서 TensorBoard를 시작하세요.
# Replace PATH with the actual path passed as model_dir argument when the
# DNNRegressor estimator was created.
tensorboard --logdir=PATH 

다음 다이어그램에 TensorBoard에서 제공하는 일부 데이터가 나와 있습니다.


요약

이 블로그 게시물에서는 Datasets와 Estimators에 대해 살펴봤습니다. 이들은 입력 데이터 스트림을 정의하고 모델을 만들기 위한 중요한 API이므로 시간을 투자하여 배워둘 만한 가치가 분명히 있습니다!

자세한 내용을 보려면 다음을 확인하시기 바랍니다.

하지만 이게 끝이 아닙니다. 곧 이러한 API의 작동 방식을 설명하는 글을 추가로 게시할 예정이오니 계속 관심을 가지고 지켜봐 주세요!

그때까지 TensorFlow 코딩을 즐기시기 바랍니다!

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 정승욱(Android GDE)님이 참여해 주셨습니다.>
게시자: Dave Burke, 안드로이드 엔지니어링 부사장
현재 20억 개 이상의 기기에서 사용 중인 안드로이드는 세계 최대 규모를 자랑하는 모바일 플랫폼입니다. 지난 9년 동안 우리는 개발자의 창작물을 전 세계 곳곳의 사용자들에게 제공하는 풍부한 도구, 프레임워크 및 API 세트를 만드는 작업을 해왔습니다. 구글은 ARCore라고 하는 새로운 SDK(소프트웨어 개발 키트)의 Preview 버전을 출시했습니다. 이를 통해 기존 및 향후의 안드로이드 휴대폰에 증강 현실 기능을 제공할 것입니다. 개발자는 지금 즉시 이를 실험해 볼 수 있습니다.


우리는 지난 3년 동안 Tango와 협력하여 모바일 AR을 강화하는 기본 기술을 개발해 왔으며 ARCore는 이러한 작업을 바탕으로 탄생했습니다. 하지만 ARCore는 추가 하드웨어 없이 작동하므로, 안드로이드 에코시스템 전체로 확장할 수 있습니다. ARCore는 7.0 Nougat 이상을 실행하는 Pixel 및 삼성 S8을 시작으로 앞으로 수백만 개의 기기에서 실행될 것입니다. 우리는 Preview 종료 시점까지 1억 개의 기기에서 ARCore 실행을 목표로 하고 있습니다. 현재 일관된 표시줄을 사용하여 높은 수준의 품질과 성능을 제공함으로써 이 목표를 실현하기 위해 삼성, 화웨이, LG, ASUS 등 여러 제조업체와 협력하고 있습니다.


ARCore는 자바/OpenGL, Unity 및 Unreal과 연동되며 다음 세 가지 사항에 중점을 둡니다.
  • 모션 추적: ARCore는 휴대폰의 카메라를 사용하여 실내의 특징 점을 관찰하고 IMU 센서 데이터를 활용함으로써 휴대폰의 움직임에 따른 휴대폰의 위치와 방향(포즈)을 결정합니다. 이에 따라 가상 물체가 계속 정확하게 배치됩니다.
  • 환경 이해: 일반적으로 AR 물체는 바닥이나 탁자 위에 놓입니다. ARCore는 모션 추적에 사용하는 것과 동일한 특징 점을 활용하여 수평면을 감지할 수 있습니다.
  • 조명 추정: ARCore는 환경에서 주변 조명을 관찰하고 개발자들이 주변 환경에 맞추는 방식으로 가상 물체에 빛을 비추어 가상 물체의 모습을 훨씬 더 사실적으로 구현합니다.

ARCore와 더불어, 우리는 개발자들이 뛰어난 AR 환경을 구축하는 데 더 많은 지원을 제공할 앱과 서비스에도 투자하고 있습니다. 우리는 BlocksTilt Brush를 빌드하여 누구나 쉽게 AR 앱에 사용할 수 있는 뛰어난 3D 콘텐츠를 신속하게 만들 수 있도록 했습니다. I/O에서 언급한 것처럼, 우리는 단순히 개발 플랫폼 상에서 이루어지는 환경을 훨씬 뛰어넘어 실제 생활 환경에서 AR을 경험할 수 있도록 해주는 서비스인 VPS(가상 위치 지정 서비스)에 대한 작업도 수행하고 있습니다. 또한, 웹이 AR의 미래에 중요한 구성요소가 될 것으로 생각하여 웹 개발자를 위한 프로토타입 브라우저도 출시할 예정입니다. 따라서 웹 개발자도 AR 관련 실험을 시작할 수 있습니다. 개발자는 이러한 맞춤형 브라우저를 사용해 AR로 향상된 웹사이트를 만들어 안드로이드/ARCore 및 iOS/ARKit에서 실행할 수 있습니다.

ARCore는 Google이 AR을 모든 사람에게 제공하기 위해 내딛는 다음 발걸음이며, 올해 말에 더 많은 정보를 공유하겠습니다. 의견이 있으시면 GitHub를 통해 알려주시고 새롭게 선보이는 AR 실험 쇼케이스에서 무엇이 가능한지 보여 주는 몇 가지 재미있는 예시들을 확인해 보시기 바랍니다. 직접 빌드한 AR 제작물이 있으시면 소셜 미디어에 #ARCore를 해시태그로 사용하여 올려주세요. 그중에 훌륭한 것을 골라 다시 공유하도록 하겠습니다.

Google Developers 팀에서는 구글 기술을 사용한 다양한 프로젝트를 전시하고, 많은 분들이 체험해볼 수 있도록 Google HackFair 를 매년 개최해오고 있습니다. 2012년을 시작으로 올해로 5회째를 맞이하는 Google HackFair 2017에 여러분을 초대합니다!!





  • 일시: 2017년 10월 21일(토) 11:00 - 18:00/ 10월 22일(일) 11:00 - 18:00
  • 장소: 서울혁신파크 (서울 은평구 녹번동 통일로 684/ 3, 6호선 불광역 2번 출구에서 도보로 7분) 
  • 가격: 청소년 및 성인 8,000원 - 온라인으로 사전 등록한 경우 (Maker Faire Seoul 2017 입장을 위해 관람료가 발생됩니다. ▶자세한 내용 보기)

1. 구글의 최신 기술을 사용한 프로젝트 전시

Google HackFair 2017에서 구글의 최신 기술을 우리의 실생활에서 직접 사용할 수 있도록 적용한 다양한 프로젝트들을 경험해 보세요. 사용된 기술 목록 및 간단한 프로젝트 소개는 아래를 확인해 주시기 바랍니다.

  • Android Things
    Android Things를 활용한 스마트 홈 컨트롤러와 스마트 환경 측정 시스템, 음성으로 명령하는 차량용 안내 메시지 LED, 모션 센서를 이용한 비어있는 화장실 알림 서비스, 하루의 감정 상태를 색으로 보여주는 탁상 달력 등
  • TensorFlow/Cloud Machine Learning
    음악 오토태깅 알고리즘을 이용한 음악 검색 서비스, 딥 러닝 학습을 통한 기계의 맞춤 연주 및 연주의 시각화, 얼굴을 인식하는 출퇴근 기록 시스템, 시각장애인을 의한 텍스트 리더기, 자신만의 음성 명령으로 동작시키는 로봇 등
  • Tango(AR)/Daydream(VR)
    3D 애니메이션 캐릭터와 함께하는 AR 영상 촬영 서비스, Daydream으로 플레이하는 모바일 VR 격투 게임, 가상의 공간에 자유롭게 그려나가는 VR 마인드맵, 제주도의 치유의 숲 ‘곶자왈'을 담은 VR 힐링 체험 등
  • Android TV
    사용자 정보를 기반으로 맞춤 컨텐츠 추천, 음성 인식 기능으로 작동 및 검색, Cast 기능을 사용해 모바일 디바이스 컨텐츠를 Android TV에서 플레이, 블록버스터 영화와 스포츠 게임 생중계 등의 다양한 스마트 TV의 기능 체험

2. 국내 최대 규모의 메이커 페어 서울과의 콜라보

직접 만든 프로젝트를 서로 공개하고 체험해볼 수 있는 국내 최대의 메이커 축제 메이커 페어 서울 2017과 함께 합니다. Google HackFair 전시팀 뿐만 아니라 약 100개 팀이 직접 만든 흥미로운 프로젝트를 한 곳에서 체험해 보시기 바랍니다. (Maker Faire Seoul 2017 입장을 위해 관람료가 발생됩니다. ▶자세한 내용 보기)


페이스북 게시글 공유 이벤트!

GDG Korea 페이스북의 Google HackFair 2017 게시글을 여러분의 타임라인에 공유해 주세요. 총 20분을 선정해 Google HackFair 2017 초대권을 2매씩 발송해 드립니다.


[소개글]

Google Play는 한국의 인디 게임 개발자 여러분들이 열정과 창의력으로 제작한 게임을 한국뿐 아니라 전세계 플레이어 및 업계 전문가들에게 널리 알리고, 나아가 비즈니스의 성공을 지원하기 위해 이번 대회를 개최하게 되었습니다.

오는 10월21일(토), Indie Games Festival 2018의 성공적인 참여를 위한 인디 게임 개발사 대상 킥오프 이벤트 겸 대회 설명회를 개최하오니, 아래 웹사이트를 통해 참가신청도 하시고 Indie Games Festival 2018의 일정을 확인해 보시기 바랍니다.


킥오프 이벤트 참가신청 / Indie Games Festival 2018 상세 보기

[주요 일정]

  • 2017년
    • 10월 21일: 킥오프 이벤트 개최 (자세한 사항은 여기를 참조)
  • 2018년
    • 2월 1일: 게임 참가 접수 시작. 상품, 심사위원, 파이널 이벤트 개최 일정 및 장소 등 발표. 일반 참가자 접수 시작
    • 3월 25일: 게임 참가 접수 마감
    • 4월초: Top 20 파이널 리스트 발표
    • 4월 21일: Indie Games Festival 2018 파이널 이벤트 개최
* 상기 일정은 변경될 수 있습니다.
* 상세 참가 자격조건 / 수상자에게 주어지는 다양한 혜택 / 결승행사 관람 및 세부 진행과정은 홈페이지를 통해 확인해 주시기 바라며, 인디 게임 개발사들의 많은 관심과 참여 바랍니다.

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 정승욱(Android GDE)님이 참여해 주셨습니다.>
게시자: Dan Albert, 안드로이드 NDK 기술 책임자
이제 Android Native Development Kit(NDK)의 최신 버전인 Android NDK r16 베타 1을 다운로드할 수 있습니다. 안드로이드 스튜디오를 통해 SDK Manager에서도 이 버전을 사용할 수 있습니다.

NDK r16은 libc++로의 마이그레이션을 권장하기 위해 구글에서 준비한 최초의 릴리스이므로 구글로서는 이 버전이 중요한 이정표인 셈입니다. 이에 대해서는 뒷부분에서 더 자세히 다루도록 하겠습니다.

우리는 또한 libc++ 및 관련 프로젝트를 업데이트했으므로 이 릴리스에서는 C++1z의 지원 기능이 향상되었습니다. C++1z가 C++17이 될 때까지는 포함된 모든 항목이 변경될 수 있다는 점을 유의하시기 바랍니다.

이 릴리스에 대한 출시 노트는 여기서 확인하실 수 있습니다.

libc++ 및 libandroid_support

NDK에는 libc++가 의존하는 libc API(이전 릴리스에서는 제공되지 않았음)를 백포트하는 libandroid_support라는 라이브러리가 있습니다. 지금까지 (NDK에 구현된 것처럼) libc++를 제대로 지원하지 못한 이유는 이 라이브러리에 대한 확신이 없었기 때문입니다. r16에서는 안정성 향상을 위해 이 라이브러리를 다시 작성하는 데 중점을 두었습니다.

libandroid_support 라이브러리는 이제 크기가 더 작아졌으므로 앱의 동작이 시스템 동작에 더욱 가까워야 합니다. 한 예로, 이전에는 libandroid_support에 stdio의 일부에 대한 대체 구현이 포함되어 있었습니다. 일부 기능이 ICS로 백포트되었지만 이는 대체 구현의 버그도 모든 OS 릴리스에 나타날 수 있다는 것을 의미하기도 합니다. 그 이유는 이러한 버그가 앱에 구현되었기 때문입니다. 새 버전의 libandroid_support에서는 이를 제거했으므로 이전 기기에는 있던 일부 기능(거의 대부분이 서식 문자열에서의 %a 지원과 같이 아무도 사용하지 않는 기능임)이 없을 것입니다. 하지만 libc++를 사용하는 앱은 이런 기능이 없으므로 더 작고 안정성도 더 높습니다.

libc++로 전환

그러면 libc++로 전환해야 하는 이유는 무엇일까요? 무엇보다도 먼저, 다른 STL이 앞으로 지원되지 않습니다(꽤 오랫동안 구글 로드맵에 명시된 사항임). 우리는 Lollipop부터 안드로이드 플랫폼에 libc++를 사용하고 있으며, 구글의 엔지니어들은 이러한 변화에 무척 만족하고 있습니다. 우리는 NDK에서 할 수 있는 것보다 더 빨리 플랫폼에서 이러한 전환을 이룰 수 있었습니다. 그 이유는 libandroid_support가 필요하지 않았으며 그 대신 libc만 업데이트할 수 있었기 때문입니다.

NDK에서 현재 제공되는 다른 STL과는 다르게, libc++는 C++11, C++14, 그리고 C++1z의 기능 대부분을 완벽히 지원합니다! Stlport의 경우 2008년 이후로 업데이트가 없었으며 gnustl(STL이 아닌 바이오닉의 libstdc++와 혼동되지 않도록 GNU의 libstdc++에 대해 부르는 이름)은 이전부터 계속해서 Clang과 효과적으로 연동되지 않았습니다. 특히, 같은 컴파일러 기본 제공 요소에 밀접하게 연결된 헤더에서 그랬습니다.

다음 NDK 릴리스에 libc++가 기본 기능으로 제공될 가능성이 매우 크지만, 현재는 libc++를 아직 사용하고 있지 않은 경우 아래의 안내에 따라 libc++를 옵트인할 수 있습니다.

다른 STL과 마찬가지로, libc++는 정적 및 공유 라이브러리로 사용할 수 있습니다. 어떤 걸 사용해야 할지는 특정 상황에 따라 다르며, 이에 대한 설명은 구글 문서에서 확인할 수 있습니다. 하지만 간단히 설명하자면 애플리케이션에 공유 라이브러리 하나만 포함하는 경우 정적 버전을 사용하고 그 밖의 경우에는 공유 버전을 사용하세요.
ndk-build
Application.mk 파일에 다음을 추가합니다.
APP_STL := c++_shared
CMake
CMake를 호출할 때 다음을 전달합니다.
-DANDROID_STL=c++_shared

Gradle을 통해 CMake를 사용하는 경우 build.gradle에 다음을 추가합니다.
externalNativeBuild {
    cmake {
        arguments "-DANDROID_STL=c++_shared"
    }
}
독립 실행형 툴체인
독립 실행형 툴체인을 생성할 때는 --stl=libc++를 전달합니다.

libandroid_support의 미래

구글 로드맵을 본 적이 있으시다면 libandroid_support를 확장하여 libc/libm을 가능한 한 많이 백포트할 계획이었다는 것을 알아차리셨을 것입니다. 하지만 이에 대해 사람들과 얘기를 나눌 때마다 항상 기껏 잘해야 미적지근한 반응만 나왔습니다. 이 계획이 사람들의 관심을 끌지 못하는 것처럼 보이고, 오히려 라이브러리 크기(그리고 이에 따라 모든 사람 이 많은 관심을 가지는 것처럼 보이는 APK 크기)를 늘리는 원인이 된다는 점을 고려하여 더 이상 이 계획을 추진하지 않기로 했습니다.

우리가 여러분의 반응을 잘못 이해했거나 여러분이 의견을 주신 적이 없고 이것이 바로 여러분이 원하는 것이라면 저희에게 알려주시기 바랍니다!


_FILE_OFFSET_BITS=64


간단히 설명하자면, 이전 NDK의 동작을 그대로 유지하려면 _FILE_OFFSET_BITS=64를 설정하지 마세요.

이전에는 NDK에 _FILE_OFFSET_BITS=64를 설정해도 아무런 영향이 없었습니다. 이는 지원 중단된 헤더에서는 전혀 제공되지 않았던 기능입니다. 통합 헤더와 함께 NDK에는 이제 이 기능에 대한 지원이 포함된 최신 헤더가 있습니다.

_FILE_OFFSET_BITS=64는 32비트 코드에서 64비트 off_t에 대한 지원을 받기 위해 애플리케이션에서 정의할 수 있는 매크로입니다. 이는 off_t를 64비트(기본적으로 32비트 코드에서는 32비트임)로 설정하고 lseek와 같은 API에 대한 호출을 lseek64에 대한 호출로 암시적으로 대체하는 방식으로 작동합니다.

단일 릴리스에서는 _FILE_OFFSET_BITS=64에 대한 지원이 안드로이드에 추가되지 않았습니다. 바이오닉에는 항상 lseek64 API 하나만 있었습니다. 대부분의 API는 Lollipop에서 추가되었으며, 이후 릴리스까지는 몇 개의 API도 더 추가된 것이 없었습니다.

현재 사용 중이며 _FILE_OFFSET_BITS=64를 설정한 함수의 64비트 off_t 변형을 지원하지 않는 릴리스를 대상으로 하는 경우 이 함수를 사용할 수 없게 됩니다. 이는 함수가 자동으로 삭제되는 32비트 off_t로 잘못 노출되는 r15 및 r15b의 동작과는 상반되는 동작입니다(단, r15c와는 일치함).

참고로, 64비트 off_t API는 다른 이름으로 _FILE_OFFSET_BITS=64를 설정하지 않고도 계속해서 사용할 수 있습니다. 예를 들어, lseek 대신 lseek64를 호출합니다. off_t 대신 off64_t를 사용합니다.

마지막으로, 이 기능은 통합 헤더와 함께 NDK에 새로 추가된 기능이므로 단지 통합 헤더 이전의 동작으로 돌아가려면 _FILE_OFFSET_BITS=64 설정을 그만두기만 하면 됩니다.

바이오닉에 포함된 off_t ABI 세부 사항에 대한 자세한 내용은 바이오닉 32비트 ABI 버그 문서를 참조하세요.

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 정승욱(Android GDE)님이 참여해 주셨습니다.>

게시자: Steven Tepper, Google Play 앱 품질 컨설턴트

지난 2월, 안드로이드 웨어 2.0이 출시되었습니다. 이 버전에서는 새로운 머티리얼 디자인 테마, 가이드라인 도입과 함께 새로운 하드웨어 기능에 대한 지원이 추가되었으며 세로 UI 패턴이 더 단순해졌습니다. 또한, Complications API가 새로 추가되어 앱이 시계 모드에 데이터를 제공하고 시계 모드의 외부 데이터 통합이 더욱 쉬워졌습니다. 최종적으로 크게 업데이트된 사항은 안드로이드 웨어 2.0을 대상으로 하는 앱이 이제는 휴대폰의 도우미 앱에 연결할 필요 없이 독립 실행형 모드에서 작동할 수 있게 되었다는 점입니다.

안드로이드 웨어 2.0 기기에 맞게 더욱 효과적으로 최적화하는 데 도움이 되도록 탐색, 알림, Complications API 및 독립 실행형 기능과 관련하여 설계 시 고려해야 할 몇 가지 사항이 있습니다.

탐색

  1. 단순하고 가끔 이루어지는 탐색에는 WearableDrawerLayout 탐색 창을 사용합니다. 단순한 탐색으로는 앱 설정 액세스, 사용자 전환, 로그아웃 등의 작업이 포함됩니다. 안드로이드 웨어 2.0에 이를 구현하여 화면 맨 위에서 아래로 스와이프하여 앱의 서로 다른 뷰 또는 섹션 간을 전환하거나, 화면 맨 아래에서 위로 스와이프할 때 상황에 맞는 작업을 실행할 수 있도록 작업 창을 설정할 수도 있습니다.
  2. 사용자가 뷰를 신속하게 탐색할 수 있도록 단일 페이지 창으로 탐색 창을 제공합니다. 탐색 창은 다중 페이지 또는 단일 페이지 창으로 제공될 수 있습니다. 단일 페이지 레이아웃은 사용자가 7개 이하의 앱 뷰 사이에서 신속하게 탐색해야 하는 경우 유용합니다. 앱에서 단일 페이지 창을 사용할 경우 아이콘 체계가 명확하고 이해하기 쉬워야 합니다. 그 이유는 이 레이아웃에 어떠한 종류의 텍스트 레이블도 없기 때문입니다. 탐색해야 하는 뷰의 수가 7개를 넘거나 이러한 뷰를 아이콘으로 쉽게 나타낼 수 없는 경우 다중 페이지 창 레이아웃을 대신 사용해야 합니다.
  3. 앱에 두세 개의 개별 기능이 있는 경우 여러 앱 런처를 사용합니다. 예를 들어, 앱이 다양한 옵션, 작업 및 뷰를 포함한 활동 추적과 추적된 활동에 대한 기간별 분석 및 관리를 모두 지원하는 경우, 이러한 작업을 처리하는 데 여러 앱 런처를 사용할 수 있습니다. 또한, 앱에 단순한 홈 화면이 있는 경우 이러한 기능을 홈 화면 맨 아래에 일렬로 배치할 수 있습니다.
  4. 작업 창 맨 위에 피킹을 사용하여 기본 작업에 신속하게 액세스할 수 있도록 합니다. 뷰와 연결된 기본 작업이 없는 경우 기본 동작을 재정의하고 그 대신에 오버플로 버튼 피킹을 강제 적용하여 오버플로 버튼을 탭할 때 뷰 맨 아래에 모든 작업이 노출되도록 합니다.

안드로이드 웨어 2.0을 사용하는 기기의 경우, 앱이 이러한 새로운 UI 패턴을 활용하여 일관된 사용자 환경을 제공하도록 하세요. 안드로이드 웨어 탐색 및 작업에 대한 추가 교육 리소스와 탐색작업 창에 대한 머티리얼 디자인 사양을 확인해 보세요.

알림

안드로이드 웨어 2.0에서는 알림 작업을 표시하는 데 가로 스와이프 동작을 사용하지 않고 더욱 단순한 세로 탐색 패턴을 사용합니다. 알림 작업은 이제 알림 맨 아래에 단일 기본 작업(해당하는 경우)으로 표시됩니다. 기본 작업이 없는 경우 알림을 확장하면 세로로 스크롤 가능한 단일 뷰에 옵션이 표시됩니다.

알림은 1.x 및 2.0 기기에서 모두 많은 내용을 변경할 필요 없이 제대로 작동하지만, 표시되는 형태는 꽤 다릅니다.

안드로이드 웨어 2.0 기기용 앱을 만들 때 다음 모범 사례를 적용하여 알림과 관련한 사용자 환경을 개선해보세요.
  1. 확장 가능한 알림 지원: BigTextStyle을 사용하면 사용자가 시계에서 더 많은 콘텐츠를 볼 수 있습니다.
  2. 축소된 형태의 알림 뷰 사용(해당하는 경우): 해당하는 경우 setContentIntent()를 사용하여 알림에 대한 기본 작업을 축소된 형태의 알림 뷰에 추가합니다.
  3. 메시지 앱의 경우 MessagingStyle 사용: 이 스타일을 사용하면 확장된 알림에서 기능이 풍부한 채팅 앱과 같은 환경을 제공할 수 있습니다.
  4. 안드로이드 웨어 1.0과 관련한 사용자 지침 업데이트: 사용자가 가로로 스와이프하여 카드 작업을 수행하도록 지시하는 텍스트를 모두 제거합니다(안드로이드 웨어 1.x 패턴).
  5. 인라인 작업을 사용하도록 알림 개선: 이 작업을 구현하면 사용자가 탭할 필요 없이 확장된 알림 세부 사항을 볼 수 있게 됩니다. 메시지 알림에 대한 작업은 스마트 회신 사전 설정, 음성 및 키보드 입력을 포함하여 여러 다양한 입력 방법을 사용할 수 있습니다. 이러한 기능을 활용하여 추가 기능을 제공하고 사용자에게 쾌적한 사용 환경을 제공해 보세요.

웨어러블 기능을 알림에 추가하는 방법에 대한 자세한 내용을 확인해 보시기 바랍니다.

정보 표시

안드로이드 웨어 2.0의 Complications API는 시계 모드 개발자 및 타사 데이터 제공자가 사용자가 원하는 중요한 정보를 한눈에 파악할 수 있도록 제공하기 더욱 쉽게 해줍니다. 이 API를 지원하는 시계 모드는 시계에 설치된 데이터 제공자를 임의로 사용하도록 구성하는 동시에 그 모습을 계속 완벽하게 제어할 수 있습니다. Complication API를 지원하는 앱을 통해 정보 표시를 지원하는 모든 시계 모드에서 앱의 데이터에 액세스할 수 있습니다. 이러한 정보 표시는 데이터 제공자가 구성한 내용과 시계 모드에 할당된 공간의 양에 따라 다양한 형태(짧은 텍스트, 아이콘, 범위 지정 값, 긴 텍스트, 작은 이미지 및 큰 이미지)로 구현될 수 있습니다.

정보 표시가 시계 모드의 전체 디자인에 적합하고 해당 데이터 형식을 제대로 처리하도록 하려면 정보 표시 지원 기능을 추가할 때 시계 모드 작성자가 다음을 수행하는 것이 좋습니다.
  1. 안드로이드 웨어 2.0 SDK에서 제공되는 TextRenderer 클래스를 사용합니다. 이 클래스는 텍스트를 축소하거나, 줄바꿈을 동적으로 지원하거나, 문자열이 텍스트 기반 정보 표시의 경계를 벗어날 때 문자열에 줄임표를 추가하여 줄이는 방법으로 정보 표시 내 텍스트가 경계에 맞게 조정되도록 합니다.
  2. ComplicationDrawable 클래스를 사용하여 정보 표시를 위한 배경 색상, 모양, 테두리 및 글꼴 옵션을 설정합니다. 이 클래스를 사용해 정보 표시가 시계 모드에 대해 렌더링되는 방식을 완벽히 제어할 수 있습니다.
  3. 사용자가 설정 메뉴를 통해 시계 모드에서 정보 표시를 구성하거나 조정할 수 있는 방법을 제공하도록 시계 모드를 디자인합니다. 이러한 설정을 생성하는 자세한 방법은 GitHub에 있는 시계 모드 샘플을 참조하세요.
  4. 데이터 제공자 테스트 모음 앱을 사용하여 더미 데이터를 시계 모드 정보 표시 기능에 피드합니다. 그러면 모든 정보 표시가 제대로 렌더링되고 해당 글꼴이 경계에 맞게 서식 지정되어 있는지 확인할 수 있습니다.
  5. 정보 표시 데이터 제공자로서, ComplicationProviderService를 사용하여 관련 데이터를 노출합니다. 앱이 정보 표시를 위해 제공할 수 있는 ComplicationData의 유형을 간단히 정의하고 구성하기만 하면 됩니다.

안드로이드 웨어 기기의 독립 실행형 기능

  1. 앱이 android.hardware.type.watch 하드웨어 기능 플래그를 사용할 때 도우미 앱이 설치되어 있지 않은 경우 자체적으로 처리 가능하도록 합니다. 이 기능을 사용하면 도우미 휴대폰 앱을 설치할 필요 없이 안드로이드 웨어 기기에서 바로 앱을 검색하고 설치할 수 있게 됩니다. 따라서 앱이 혼동을 주거나 부실한 사용자 환경을 제공하지 않도록 자체적으로 처리 가능하도록 해야 합니다.
  2. 웨어러블 앱이 로그인/인증 또는 기본 기능을 제공하는 데 휴대폰 앱에 의존하지 않도록 합니다. 웨어러블 앱에서 인증을 위해 복잡한 입력(예: 비밀번호 입력)을 요구할 때 도우미 휴대폰을 이용하도록 가리킬 수 있지만, 앱보다는 계정/비밀번호 입력을 위한 웹 UI를 사용해야 합니다.
  3. 도우미 앱이 몇몇 다른 이유로 앱을 지원하기 위해 휴대폰에서 제공되어야 하는 경우 앱은 CapabilityApi를 사용해야 합니다. 누락된 앱을 설치하도록 도우미 기기에서 사용자를 Play Store 목록 페이지로 올바로 안내하기 위해 이를 사용해야 합니다. 그렇지 않은 경우, 이 앱은 안드로이드 웨어에 내장된 Wi-Fi, GPS 또는 기타 연결 기능을 사용하여 자체적으로 작동해야 합니다.
  4. Play Store 목록 설명 내에 도우미 앱 요구 사항과 관련한 문구를 포함하거나 안드로이드 웨어 앱이 작동해야 하는 방식을 간단히 설명합니다. 그러면 기대치를 정하고 사용자에게 가능한 한 최상의 환경을 이용할 수 있도록 올바른 앱 설치를 안내하는 데 도움이 됩니다.
  5. 웨어러블 앱이 어떠한 휴대폰 도우미 상호작용 없이도 작동할 수 있는 경우 com.google.android.wearable.standalone 플래그를 매니페스트에 포함합니다. 이 플래그는 웨어러블 앱이 설치 가능하며 Android 또는 iOS 도우미 휴대폰에 페어링되지 않은 경우에도 완벽하게 작동함을 나타냅니다.

여기서 많은 사항을 다루었지만 앱 또는 게임이 최적화되어 있고 안드로이드 웨어에서 최신 패턴 및 기능을 사용하는지 확인하는 데 참고할 수 있는 추가 자료가 있습니다. 안드로이드 웨어용으로 뛰어난 앱을 빌드하려면 품질 가이드라인을 검토하고 개발자 교육 문서를 확인하여 웨어러블 앱 개발웨어러블 앱 디자인 관련 모범 사례를 자세히 살펴보세요.

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 장정식(Google)님이 참여해 주셨습니다.>
지난 포스트에서, 웹페이지에서 광고가 동작하는 방식을 이해하는 것은 웹을 개선하는데 중요한 부분임을 강조했었습니다. 이미 지난 Google I/O에서 AMP 광고 세션이 있었습니다. 그 세션에서 AMP 페이지에서의 기본적인 광고 지원 기능과 사용자, 게시자 그리고 광고주에게 최고의 AMP페이지 기반의 광고를 위한 전반적인 내용을 다루었습니다. 그때 설명한 것처럼, 이를 실현하려는 우리의 비전에는 다음 세 가지 단계가 포함됩니다.



제1단계는 이미 2년 전 AMP 프로젝트 시작단계에서, 2단계는 지난 달에 완료하였습니다. 이 게시물의 나머지 부분에서는 바로 이 2단계의 성과를 설명드리겠습니다.

AdZerk, DoubleClick, AdSense, TripleLift 등과 같은 주요 광고 네트워크에서 이미 AMP 광고를 지원하고 있으며, 제2단계에서 빌드한 인프라를 활용하고 있습니다. 이번 출시 덕분에 AMP 광고를 더욱 신속하게 렌더링할 수 있을 뿐 아니라 AMP 페이지에서 일반적인 광고의 렌더링 속도도 더욱 빨라지게 되었습니다.


Fast Fetch 출시

제2단계에서 가장 주된 추가 기능은 'Fast Fetch'입니다. 우리는 Fast Fetch를 사용하여 광고 요청이 생성되는 시점을 광고 응답이 렌더링되는 시점으로부터 분리합니다. 이를 통해 페이지 생명 주기의 매우 이른 시점에 모든 광고 슬롯의 광고 요청을 생성하고, 사용자에게 모든 광고가 한꺼번에 렌더링 됩니다. 

이는 광고 요청의 기존 메커니즘인 'Delayed Fetch'와 대조되는 방식입니다. Delayed Fetch에서는 광고 요청과 렌더링이 한 동작으로 수행되므로, 광고 로드를 기다리는 동안 사용자에게는 '로드 중 상태'임이 표시됩니다. Delayed Fetch에는 추가적인 제약 조건도 있습니다. 런타임은 다른 컨텐츠 로드와 충돌을 방지하기 위해 1초 이상 페이지에서 다음 광고 슬롯을 요청하지 않습니다.


Fast Fetch에서는 페이지의 수명 주기에서 훨씬 초기에 광고가 요청됩니다. 따라서 광고 서버에서 페이지 렌더링과 광고 선택이 동시에 이루어질 수 있습니다.
Fast Fetch는 Delayed Fetch에 비해 50 백분위수에서 850밀리초 더 빠르고 90 백분위수에서는 2.7초 더 빠릅니다.

AMP 광고에 대한 협업적 렌더링 

광고 응답이 AMP 형식(AMP 광고)이면 AMP 런타임이 광고를 즉시 렌더링합니다. 응답이 일반 광고인 경우 페이지에서 나머지 콘텐츠가 로드될 때까지 런타임이 대기해야 합니다. 이는 AMP 광고 성능을 자신할 수 있게에 가능한 방식입니다. 그러나 비 AMP 광고에서는 그런 보장이 없습니다.


AMP 광고는 DoubleClick 및 AdSense 시험을 기반으로 50 백분위수에서 최대 1.6초, 90 백분위수에서 최대 5초 더 빠르게 로드됩니다.

광고가 화면에 더 빠르게 나타날수록 광고의 노출도가 더 높아집니다. 이는 브랜드를 더욱 폭넓은 잠재고객에게 노출시켜 주므로 브랜드 광고주에게 유리합니다. 노출도가 더욱 높아지면 사용자가 광고와 상호작용할 가능성도 증가하게 되므로 실적을 중시하는 광고주에게도 이익이 됩니다.

Fast Fetch를 위한 새로운 기능 출시 

다수의 게시자는 자신의 운영 웹사이트에 콘텐츠를 제공하는 데 사용할 형식으로 AMP를 실험 중입니다. 이러한 작업을 수행하는 게시자를 지원하기 위해 Fast Fetch에서는 향후 AMP에 다음과 같은 고급 광고 기능을 추가로 제공할 예정입니다.
  • AMP 페이지를 위한 경쟁력 있는 제외 사항 및 차단 기능
  • 광고 새로 고침 빈도를 조정할 수 있는 기능
  • 광고 타겟에 대한 실시간 광고 요청 확장 기능 지원

게시자(또는 광고주)인 경우: 

DoubleClick 및 AdSense 덕분에 AMP 페이지에서 광고 요청이 발생할 때 적합한 광고가 AMP로 자동 변환됩니다. 더 많은 형식을 AMP로 변환할 수 있게 됨에 따라 이러한 광고 물량이 늘어날 것으로 기대할 수 있으며, 결과적으로 어떠한 변경 작업도 수행할 필요 없이 페이지에 제공되는 광고의 노출도와 클릭률이 더 높아지는 이점을 누릴 수 있습니다.


광고를 개발하는 광고주(또는 게시자)인 경우: 

(게시자든 광고주든 상관없이) 광고를 개발하는 경우 AMP 광고로 전환하여 높은 노출도와 뛰어난 사용자 환경을 갖춘 더욱 신속한 광고의 이점을 누리시기 바랍니다. 먼저, 사내 광고 개발자에게 이 AMP 광고 개발자 FAQ를 살펴보도록 하세요.

광고 자산의 개발 작업을 아웃소싱하는 경우 AMP 광고 제작을 전문으로 하는 JoyStick Interactive와 같은 업체를 이용할 수 있습니다. 광고 개발 도구를 사용하여 자산을 빌드하는 데 익숙하다면, Celtra의 광고 제작 프로그램을 이용하여 AMP 광고를 제작해 보시기 바랍니다. Google Web Designer와 같은 다른 도구를 위한 AMP 광고 지원도 곧 제공할 예정입니다.

광고 기술 플랫폼인 경우: 

DoubleClick 및 Adsense 광고 태그는 Fast Fetch를 사용하며 지연 시간을 대폭 단축하는 효과를 보고 있습니다. 모든 광고 네트워크가 Fast Fetch로 전환하기를 기대합니다. 자세한 내용은 가이드를 참조하시기 바랍니다. AMP 광고 서명의 경우, Cloudflare와 협력하여 Cloudflare에서 제공하는 Firebolt 서비스를 사용할 수 있습니다. 또는 AMP 광고를 직접 서명하고 싶다면 Github에서 제공하는 콘텐츠를 참조하시기 바랍니다.

Cloudflare의 제품 전략 책임자인 Dane Knecht 씨는 "Cloudflare Firebolt는 광고 네트워크가 추가로 개발해야 할 작업이 거의 없이 전역적으로 광고에 서명하고 쉽게 광고를 제공할 수 있게 해줍니다. 우리의 사명인 더 나은 인터넷 환경의 빌드에 도움을 드리기 위한 노력의 일환으로, Firebolt는 글로벌 AMP 광고 환경을 더욱 향상시켜 광고 환경을 더욱 신속하고 안전하게 만들고 결과적으로 더 나은 전환율을 실현합니다"라고 말합니다.

AMP 광고는 이제 DoubleClick Ad Exchange에서도 지원되며(Real Time Bidding을 통해), DSP는 RTB를 통한 AMP 광고 제공을 지원하는 작업을 시작할 수 있습니다.

우리는 AMP 광고 부문에서 먼 여정을 거쳐왔으며, 이제 제3단계를 앞두고 큰 기대에 부풀어 있습니다. 여기에는 다음 작업이 포함됩니다.
  • 광고 네트워크가 AMP 광고를 자동 변환하고 제공할 수 있도록 지원
  • 광고 서버가 사용자 맞춤 AMP 광고를 업로드하고 제공하는 작업을 지원하도록 함
  • 광고 개발자의 AMP 광고 제작에 도움이 되는 기능 빌드
  • 기본적으로 AMP 광고 제작에 활용할 수 있는 더 많은 광고 제작 도구를 제공하도록 제휴 체결

늘 그렇듯이, 함께 더 나은 웹 환경을 구축할 수 있도록 위 사항과 관련하여 좋은 의견이나 이를 구현할 기회가 있으시면 꼭 알려주시기 바랍니다.