[go: up one dir, main page]

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

게시자: Jonathan Shen, Ruoming Pang(소프트웨어 엔지니어, Google 두뇌 및 기계 인지 팀을 대표하여 작성)

텍스트로부터 매우 자연스러운 음성을 생성하는 과제(텍스트-음성, TTS)는 수십 년 묵은 연구 목표였습니다. 지난 몇 년 동안 TTS 연구에서 많은 진전이 있었으며 완전한 TTS 시스템의 많은 개별적인 부분들이 크게 개선되었습니다. TacotronWaveNet 같은 이전 작업에서 얻은 아이디어를 통합하여 더 많은 개선 사항을 추가함으로써 새로운 시스템인 Tacotron 2가 탄생했습니다. 우리의 접근 방식에서는 복잡한 언어 및 음향 기능을 입력 수단으로 사용하지 않습니다. 대신, 음성 예시와 해당 텍스트 대화 내용만으로 교육받은 신경망을 사용하여 텍스트에서 인간과 유사한 음성을 생성합니다.

우리가 선보이는 새로운 시스템에 대한 자세한 설명은 'Natural TTS Synthesis by Conditioning WaveNet on Mel Spectrogram Predictions'라는 제목의 논문에서 찾아볼 수 있습니다. 간단히 말하자면 다음과 같이 작동합니다. TTS에 최적화된 시퀀스-시퀀스 모델을 사용하여 오디오를 인코딩하는 기능 시퀀스에 문자 시퀀스를 매핑합니다. 이 기능은 12.5밀리초마다 계산된 프레임을 포함하는 80차원 오디오 스펙트로그램으로, 단어의 발음뿐 아니라 음량, 속도 및 억양을 비롯한 사람의 음성이 지닌 다양하고 미묘한 부분을 포착합니다. 마지막으로 이러한 기능은 WaveNet과 유사한 아키텍처를 사용하여 24kHz 파형으로 변환됩니다.


Tacotron 2의 모델 아키텍처에 대해 자세히 알아보기. 이미지의 아래쪽 절반은 문자 시퀀스를 스펙트로그램에 매핑하는 시퀀스-시퀀스 모델을 나타냅니다. 기술적인 세부 사항은 논문을 참조하세요.


최첨단 TTS 시스템의 결과를 보여주는 Tacotron 2 오디오 샘플 몇 가지를 들을 수 있습니다. 인간 청취자에게 생성된 음성이 얼마나 자연스러운지 점수를 매겨달라고 요청한 평가에서 성우와 같은 전문가들이 녹음한 음성에 대해 매긴 점수와 비슷한 점수를 얻었습니다.

샘플이 훌륭한 것 같지만 아직 해결해야 할 어려운 문제가 몇 가지 남아 있습니다. 예를 들어, 우리의 시스템은 복잡한 단어(예: decorum, merlot)를 발음하는 데 어려움이 있으며 극단적인 경우에는 이상한 소리를 랜덤하게 생성할 수도 있습니다. 또한, 아직은 실시간으로 오디오를 생성할 수 없습니다. 게다가 아직은 생성된 음성을 제어할 수도 없습니다(예: 행복하거나 슬픈 음색을 내도록 지시). 이들 각각은 그 자체로 흥미로운 연구 과제입니다.

감사의 말

Jonathan Shen, Ruoming Pang, Ron J. Weiss, Mike Schuster, Navdeep Jaitly, Zongheng Yang, Zhifeng Chen, Yu Zhang, Yuxuan Wang, RJ Skerry-Ryan, Rif A. Saurous, Yannis Agiomyrgiannakis, Yonghui Wu, Sound Understanding 팀, TTS Research 팀 및 TensorFlow 팀에 감사의 마음을 전합니다.

<블로그 원문은 이곳에서 확인하실 수 있으며, 블로그 번역 리뷰는 양찬석(Google)님이 참여해 주셨습니다.>
게시자: Jason St. Pierre, 제품 관리자
Fabric과 Firebase 팀이 협력 관계를 체결한 후, 우리의 목표는 최고로 멋진 플랫폼을 만드는 것이었습니다. 이를 위한 첫 번째 이정표로 Firebase Crashlytics 베타 버전이 출시되었습니다.

Firebase Crashlytics는 앱 품질을 저해하는 안정성 문제를 추적하고 수정하는 데 도움을 줄 수 있는 실시간 오류 보고 도구(Crash Reporting Tool)입니다. 개발자는 기존에 사용하던 Firebase 콘솔을 통해 업계 최고의 오류 보고 솔루션을 사용할 수 있습니다. 이 시점 이후로는 Crashlytics가 Firebase용 오류 보고 도구로 권장되며, 기존 Firebase 오류 보고를 사용하고 계신 분은 대시보드의 배너를 클릭하여 업그레이드를 진행할 수 있습니다. 또한, 신규 Firebase 개발자는 g.co/firebase/optin을 방문하여 Crashlytics 사용을 시작하실 수 있습니다.

업그레이드함으로써 얻게 되는 기능과 혜택을 설명해드리겠습니다. Crashlytics가 모든 모바일 앱 개발자가 꼭 확보해야 할 도구라는 점을 알 수 있을 것입니다.

더욱 빠른 문제해결

Crashlytics는 스택 트레이스(Stack Trace)의 유사성을 기반으로 비정상 종료를 그룹화하고 그 영향력을 표시해줍니다. 따라서 실시간 비정상 종료 데이터를 통해 추세를 손쉽게 파악하고, 버전 필터링을 사용하여 가장 중요한 특정 릴리스에서 발행하는 문제에 집중할 수 있습니다. 문제 개요 및 문제 세부 정보 페이지는 문제해결을 위한 소요시간 단축할 수 있도록 디자인되었습니다.



개요 페이지에서는 비정상 종료가 발생하지 않은 사용자 비율이 두드러지게 표시되므로 어떤 빌드가 안정성 측면에서 향상되고 있는지를 측정할 수 있습니다.


또한 유의성 배지 도 확인할 수 있습니다. 이 배지가 강조 표시되어 있을 때는 앱 작동을 비정상적으로 만들 수 있는 두드러지는 요소가 있음을 나타냅니다. 예를 들어, 유의성 배지를 통해 특정 문제가 특정 기기, OS 또는 탈옥된 휴대폰에서만 발생하는지를 알 수 있습니다.


이러한 통찰력 있는 정보에 힘입어 문제를 효과적으로 분류하고, 긴급한 문제에 신속하게 대응할 수 있습니다. 탈옥된 기기에서만 일반적으로 발생하는 문제는 우선 순위를 낮출 수 있습니다. 아니면 최신 OS 릴리스로 인해 발생한 문제를 수정하는 데 더 집중할 수도 있습니다. 유의성 배지는 문제를 해결할 때 더욱 현명한 결정을 내리는 데 도움이 됩니다.


사용자설정 키 및 로그

Crashlytics를 사용하면 비정상 종료가 발생한 이유와 어떠한 일이 발생하여 비정상 종료에까지 이르게 되었는지에 대한 추가 정보와 그에 대한 컨텍스트를 제공하는 로그와 키를 계측할 수 있습니다.

구체적으로 말하면, 로그를 사용하여 비정상 종료가 발생하기 바로 전에 사용자가 어떠한 작업을 하고 있었는지에 대한 세부 정보를 수집할 수 있습니다(예: 사용자가 다운로드 화면으로 이동하고 다운로드 버튼을 클릭함). 또한, 로그를 사용하여 사용자 작업에 대한 세부 정보를 얻을 수도 있습니다(예: 이미지 다운로드 크기). 로그는 비정상 종료 전에 발생한 이벤트의 타임라인을 보여 줍니다. 비정상 종료가 발생하면 더욱 신속하게 디버그하는 데 도움이 되도록 로그 내용을 취하여 이를 비정상 종료 보고에 추가합니다.

상황에 따라 사용자 앱의 마지막 상태를 아는 것이 작업 순서만큼 중요한 경우도 있습니다. 키는 사용자가 앱을 탐색함에 따라 덮어 쓰이는 항목에 대해 마지막으로 알려진 값을 기록하는 키 값 쌍입니다. 예를 들어, 키를 사용하면 게임 앱에서 사용자가 마지막으로 이룬 레벨이나 맞춤 설정의 최신 구성 등 디버그 작업에 유용할지 모르는 컨텍스트를 나타낼 수 있는 정보를 추적할 수 있습니다.

로그와 키는 세션 메타데이터에서 단서를 찾고 버그를 재현하기 위해 사용자가 수행한 단계를 되짚어 갈 수 있는 아주 훌륭한 방법입니다.


실시간 알림

안정성 문제는 워크스테이션을 사용하지 않을 때도 언제든지 나타날 수 있습니다. 새로운 문제가 발생하면 Crashlytics 대시보드에 실시간으로 우선순위에 따라 표시될 뿐만 아니라 새로운 문제가 발생할 때, 문제로 인해 성능이 저하되는 경우, 그리고 문제의 영향이 갑자기 커지는 경우 이메일 알림도 전송됩니다. 여러분 뒤에 Crashlytics가 있으므로 안심하시고 잠시 물러나 여유롭게 커피 한잔 드셔도 됩니다. Crashlytics는 최근 제공한 앱과 관련하여 문제가 발생하면 알림을 전송해주므로 중요한 비정상 종료를 절대로 놓치지 않을 것입니다.


Firebase Crashlytics와 Cloud Functions for Firebase의 통합

Crashlytics의 많은 강력한 기능을 Firebase에 도입한 것 외에, 우리는 플랫폼의 다른 부분에도 Crashlytics를 통합하는 작업도 진행하고 있습니다. 이제, Cloud Functions for Firebase를 트리거하기 위한 이벤트 소스로 Crashlytics 데이터를 활용할 수 있습니다. 이번 통합을 통해 중요한 앱 흐름(예: 구매 흐름)에 영향을 미치는 문제를 팀의 엔지니어나 Slack 채널에 직접 전달하는 워크플로를 자동화할 수 있습니다. 이런 식으로 긴급한 문제가 즉각적이고도 적절하게 모니터링되고 에스컬레이션되도록 할 수 있습니다.


또한, 안정성 데이터를 새로 디자인된 Firebase 콘솔의 다양한 영역에서 함께 노출합니다. 개발자 여러분은 최고 수준의 안정성을 유지하기 위해 여러 페이지 사이에서 탐색할 필요가 없습니다. 이제는 Crashlytics 데이터를 프로젝트 개요 페이지, Firebase용 Google 애널리틱스 대시보드는 물론, 최신 릴리스 섹션에서도 볼 수 있습니다.

앞으로 예정된 더욱 흥미로운 업데이트

Crashlytics의 이번 베타 출시는 최고의 Fabric과 Firebase의 기능을 결합하는 단계의 시작에 불과합니다. 고객은 이미 Google의 플랫폼을 함께 사용하여 놀라운 결과를 달성하고 있습니다. 일례로, 만남을 갖기에 최고의 날짜와 시간을 찾는 데 도움이 되는 앱인 Doodle을 살펴보도록 하겠습니다. Doodle은 Crashlytics 및 원격 구성을 사용해 앱을 새롭게 디자인하고 사용자 유지율과 참여율을 높였습니다.


이제부터 신규 및 기존 Firebase 고객은 Crashlytics를 사용해야 합니다. Crashlytics가 최고의 Firebase용 오류 보고 도구이기 때문입니다. 신규 Firebase 고객은 g.co/firebase/optin을 방문하여 Crashlytics 사용을 시작할 수 있으며, 기존 오류 보고 고객은 오류 보고 대시보드의 배너를 클릭하시면 됩니다. 우리는 계속해서 Crashlytics를 발전시켜 나갈 것이며 여러분의 피드백을 손꼽아 기다리고 있습니다!

이미 Fabric에서 Crashlytics를 사용하고 계시다면 현재 조건으로 충분하십니다. 따라서 아직은 마이그레이션할 필요가 없습니다. Fabric 앱에서 Firebase Crashlytics를 이용할 수 있는 방법에 대한 흥미로운 소식을 곧 알려드릴 예정입니다.

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 양찬석(Google)님이 참여해 주셨습니다.>
Google Play Services SDK 11.6.0에서는 API 구조가 변경되었습니다. GoogleApiClient 클래스 대신, 각 기능별로 별도의 클라이언트가 제공됩니다. 이에 따라 Play Games Services API를 사용하는데 필요한 상용구 코드의 양이 줄어들었습니다.

API는 사용하기 더욱 쉽고, 스레드 안전(thread-safe)하고 메모리를 효율적으로 사용할 수 있도록 변경되었습니다. 새로운 API는 Task 모델을 활용하여 activity와 API의 비동기 결과 처리 사이에 발생하는 문제를  효과적으로 분리합니다. 이 방식은 Firebase에서 처음 등장했으며 외부 개발자 커뮤니티에서 좋은 평가를 받았습니다. Task 모델은 장점에 대해 더욱 자세히 알아보려면 Task에 대한 블로그 시리즈Task API 개발자 가이드를 확인해 보시기 바랍니다.

개발자 문서는 새로운 API는 물론, 개발자를 위한 그 외 모든 Google 리소스에 대한 정보를 얻을 수 있는 신뢰할 수 있는 출처입니다. Play Games Services API 안드로이드 기본 샘플 프로젝트와 클라이언트 서버 골격 프로젝트 모두 새로운 API를 사용하도록 업데이트되었습니다. 샘플 프로젝트는 새로운 API를 사용하면서 발생하는 문제를 제보할 수 있는 최상의 장소이기도 합니다.

많은 변화가 이루어진 것 같지만, 두려워하지 마세요! Play Services API 클라이언트 사용법은 무척 간단하고 코드 상 불필요한 내용을 많이 줄일 수 있습니다. API 클라이언트 사용은 다음 세 부분으로 나뉩니다.
  1. 인증이 이제 Google 로그인 클라이언트를 사용하여 명시적으로 수행됩니다. 이로 인해 인증 프로세스 제어 방법과 Google 로그인 ID 및 Play Games Services ID 간의 차이가 더 명확해집니다.
  2. 모든 Games.category 정적 메서드 호출을 해당 API 클라이언트 메서드로 변환합니다. Task 클래스를 사용하도록 변환하는 것도 포함됩니다. Task 모델은 코드에 있는 문제의 분리에 큰 도움이 되며 작업 리스너가 UI 스레드에서 콜백되므로 멀티스레드 복잡성을 줄여줍니다.
  3. 멀티플레이어 invitation 처리는 턴 방식 및 실시간 멀티플레이어 API 클라이언트를 통해 명시적으로 이루어집니다. GoogleApiClient가 더 이상 사용되지 않으므로 멀티플레이어 invitation을 포함하는 '연결 힌트' 객체에 액세스할 수 없습니다. 이제는 명시적 메서드 호출을 통해 invitation에 액세스할 수 있습니다.

인증

인증 프로세스의 세부 정보는 Google Developers 웹사이트에서 확인할 수 있습니다.

가장 일반적인 인증 사용 사례는 DEFAULT_GAMES_SIGN_IN 옵션을 사용하는 것입니다. 이 옵션을 사용하면 게임에서 사용자의 게임 프로필을 사용할 수 있습니다. 사용자의 게임 프로필에는 이름, 이미지 아바타와 같이 게임이 표시할 수 있는 게이머 태그만 포함되므로 사용자의 실제 ID가 보호됩니다. 따라서 사용자가 추가적인 개인정보 공유에 동의할 필요가 없으므로 사용자와 게임 간의 마찰이 줄어듭니다.

참고: 게임 프로필만 사용하는 것으로 요청할 수 있는 Google 로그인 옵션은 requestServerAuthCode()뿐입니다. requestIDToken()과 같은 다른 모든 옵션의 경우 사용자가 추가 정보를 공유하는 것에 대해 동의해야 합니다. 또한, 이 옵션은 사용자에게 탭이 없는 로그인 환경이 제공되지 않도록 하는 효과도 있습니다.

한 가지 더 참고할 사항은 Snapshots API를 사용하여 게임 데이터를 저장하는 경우 로그인 옵션을 생성할 때 Drive.SCOPE_APPFOLDER 범위를 추가해야 한다는 점입니다.

private  GoogleSignInClient signInClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // other code here
   
   GoogleSignInOptions signInOption = new GoogleSignInOptions.Builder(
        GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
        // If you are using Snapshots add the Drive scope.
        .requestScopes(Drive.SCOPE_APPFOLDER)
        // If you need a server side auth code, request it here.
        .requestServerAuthCode(webClientId)
        .build();
    signInClient = GoogleSignIn.getClient(context, signInOption);
}

한 번에 하나의 사용자 계정으로만 로그인할 수 있으므로 activity가 재개될 때 자동 로그인을 시도하는 것이 좋습니다. 그렇게 해도 유효한 경우 사용자를 자동으로 로그인하는 효과가 있습니다. 또한, 사용자가 다른 activity에서 로그아웃하는 것처럼 변경 사항이 있는 경우 로그인된 계정이 업데이트되거나 무효화됩니다.

private void signInSilently() {
  GoogleSignInOptions signInOption =
    new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
                   .build();
  GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOption);
  signInClient.silentSignIn().addOnCompleteListener(this,
           new OnCompleteListener<GoogleSignInAccount>() {
               @Override
               public void onComplete(@NonNull Task<GoogleSignInAccount> task) {
                  // Handle UI updates based on being signed in or not.
                  enableUIButtons(task.isSuccessful());
                 // It is OK to cache the account for later use.
                 mSignInAccount  = task.getResult();
               }
           });
}
    @Override
    protected void onResume() {
        super.onResume();
        signInSilently();
    }

대화식 로그인은 별도의 인텐트를 실행하는 방법으로 이루어집니다. 대단하죠! 오류 해결책이 있는지 확인하고 올바른 API를 호출하여 오류를 해결하려고 시도할 필요가 더 이상 없습니다. 그저 간단히 activity를 시작하고 onActivityResult()에서 결과를 가져오기만 하면 됩니다.

  Intent intent = signInClient.getSignInIntent();
  startActivityForResult(intent, RC_SIGN_IN);
    @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
      super.onActivityResult(requestCode, resultCode, intent);
      if (requestCode == RC_SIGN_IN) {
        // The Task returned from this call is always completed, no need to attach
        // a listener.
        Task<GoogleSignInAccount> task = 
              GoogleSignIn.getSignedInAccountFromIntent(intent);

          try {
            GoogleSignInAccount account = task.getResult(ApiException.class);
            // Signed in successfully, show authenticated UI.
              enableUIButtons(true);
           } catch (ApiException apiException) {
                // The ApiException status code indicates the
                //  detailed failure reason.
                // Please refer to the GoogleSignInStatusCodes class reference
                //  for more information.
                Log.w(TAG, "signInResult:failed code= " +
                    apiException.getStatusCode());
                new AlertDialog.Builder(MainActivity.this)
                        .setMessage("Signin Failed")
                        .setNeutralButton(android.R.string.ok, null)
                        .show();
            }
    }
}

GoogleSignIn.getLastSignedInAccount() 메서드를 호출하여 사용자가 로그인되었는지 여부를 확인할 수 있습니다. 이 메서드는 로그인된 사용자에 대한 GoogleSignInAccount를 반환하고, 로그인된 사용자가 없는 경우에는 null을 반환합니다.

if (GoogleSignIn.getLastSignedInAccount(/*context*/ this) != null) {
  // There is a user signed in, handle updating the UI.
  enableUIButtons(true);
} else {
  // Not signed in; update the UI.
  enableUIButtons(false);
}

로그아웃은 GoogleSignInClient.signOut()을 호출하는 방식으로 수행됩니다. 따라서 더 이상 게임을 위한 특정한 로그아웃이 없습니다.

signInClient.signOut().addOnCompleteListener(MainActivity.this,
        new OnCompleteListener<Void>() {
            @Override
             public void onComplete(@NonNull Task<Void> task) {
                enableUIButtons(false);
             }
         });
);

Games Services API 클라이언트 사용

이전 버전의 Play Games Services에서는 API를 호출하는 일반적인 패턴이 다음과 같았습니다.
    PendingResult<Stats.LoadPlayerStatsResult> result =
            Games.Stats.loadPlayerStats(
            mGoogleApiClient, false /* forceReload */);
    result.setResultCallback(new
            ResultCallback<Stats.LoadPlayerStatsResult>() {
        public void onResult(Stats.LoadPlayerStatsResult result) {
            Status status = result.getStatus();
            if (status.isSuccess()) {
                PlayerStats stats = result.getPlayerStats();
                if (stats != null) {
                    Log.d(TAG, "Player stats loaded");
                    if (stats.getDaysSinceLastPlayed() > 7) {
                        Log.d(TAG, "It's been longer than a week");
                    }
                    if (stats.getNumberOfSessions() > 1000) {
                        Log.d(TAG, "Veteran player");
                    }
                    if (stats.getChurnProbability() == 1) {
                        Log.d(TAG, "Player is at high risk of churn");
                    }
                }
            } else {
                Log.d(TAG, "Failed to fetch Stats Data status: "
                        + status.getStatusMessage());
            }
        }
    });

이 API는 Games 클래스의 정적 필드에서 액세스가 이루어지고 결과를 얻기 위해 개발자가 리스너에 추가한 PendingResult를 반환했습니다.

그런데 이제는 여기에 약간 변화가 생겼습니다. Games 클래스에서 API 클라이언트를 가져오는 정적 메서드가 있으며 PendingResult 클래스가 Task 클래스로 바뀌었습니다.

그 결과, 새로운 코드는 다음과 같습니다.
GoogleSignInAccount mSignInAccount = null;
Games.getPlayerStatsClient(this, mSignInAccount).loadPlayerStats(true)
        .addOnCompleteListener(
            new OnCompleteListener<AnnotatedData<PlayerStats>>() {
              @Override
              public void onComplete(Task<AnnotatedData<PlayerStats>> task) {
                try {
                    AnnotatedData<PlayerStats> statsData =
                        task.getResult(ApiException.class);
                    if (statsData.isStale()) {
                        Log.d(TAG,"using cached data");
                    }
                    PlayerStats stats = statsData.get();
                    if (stats != null) {
                        Log.d(TAG, "Player stats loaded");
                        if (stats.getDaysSinceLastPlayed() > 7) {
                            Log.d(TAG, "It's been longer than a week");
                        }
                        if (stats.getNumberOfSessions() > 1000) {
                            Log.d(TAG, "Veteran player");
                        }
                        if (stats.getChurnProbability() == 1) {
                            Log.d(TAG, "Player is at high risk of churn");
                        }
                    }
                } catch (ApiException apiException) {
                    int status = apiException.getStatusCode();
                    Log.d(TAG, "Failed to fetch Stats Data status: "
                            + status + ": " + task.getException());
                }
            }
        });

여기서 볼 수 있듯이, 크게 변한 것은 아니지만 Task API의 이점을 모두 활용할 수 있으므로 GoogleApiClient 수명 주기 관리에 대해 염려할 필요가 없습니다.

이러한 변경 패턴은 모든 API에서 동일합니다. 추가 정보가 필요한 경우 개발자 웹사이트에서 확인할 수 있습니다. 예를 들어, 예전에 Games.Achievements를 사용했다면 이제는 Games.getAchievementClient()를 사용해야 합니다.

Play Games Services API에 대한 마지막 주요 변경 사항은 새로운 API 클래스인 GamesClient가 추가되었다는 점입니다. 이 클래스는 setGravityForPopups(), getSettingsIntent()와 같은 지원 메서드를 처리하며 게임이 알림에서 실행된 경우 멀티플레이어 invitation 객체에 대한 액세스도 제공합니다.

이전에는 연결 힌트와 함께 onConnected() 메서드가 호출되었습니다. 이 힌트는 시작 시 activity로 전달된 invitation을 포함할 수 있는 Bundle 객체입니다.

이제는 GamesClient API를 사용하는 경우 invitation이 있으면 게임에서 signInSilently()를 호출해야 합니다. 이 호출은 사용자가 invitation에서 확인되었기 때문에 성공할 것입니다. 그런 후 GamesClient.getActivationHint()를 호출하여 활성화 힌트를 가져오고 invitation이 있는 경우 이를 처리합니다.

Games.getGamesClient(MainActivity.this,  mSignInAccount)
        .getActivationHint().addOnCompleteListener(
        new OnCompleteListener<Bundle>() {
            @Override
            public void onComplete(@NonNull Task<Bundle> task) {
                try {
                    Bundle hint = task.getResult(ApiException.class);
                    if (hint != null) {
                        Invitation inv = 
                           hint.getParcelable(Multiplayer.EXTRA_INVITATION);
                        if (inv != null && inv.getInvitationId() != null) {
                            // retrieve and cache the invitation ID
                            acceptInviteToRoom(inv.getInvitationId());
                            return;
                        }
                    }
                } catch (ApiException apiException) {
                    Log.w(TAG, "getActivationHint failed: " +
                        apiException.getMessage());
                }
            }
        });

오류 처리

메서드 호출이 실패하면 Task.isSuccessful()이 false가 되고 이 오류에 대한 정보는 Task.getException()을 호출하여 액세스할 수 있습니다. 경우에 따라서는 이러한 예외가 API 호출에서 성공 이외의 값이 반환되는 단순한 형태로 나타나기도 합니다. 다음과 같이 ApiException로 캐스트하여 이를 확인할 수 있습니다.
if (task.getException() instanceof ApiException) {
                    ApiException apiException = (ApiException) task.getException();
                    status = apiException.getStatusCode();
}

다른 경우, MatchApiException이 반환될 수 있으며 여기에는 업데이트된 일치 데이터 구조가 포함됩니다. 이러한 예외도 비슷한 방법으로 검색할 수 있습니다.
if (task.getException() instanceof MatchApiException) {
                    MatchApiException matchApiException =
                        (MatchApiException) task.getException();
                    status = matchApiException.getStatusCode();
                    match = matchApiException.getMatch();
} else if (task.getException() instanceof ApiException) {
                    ApiException apiException = (ApiException) task.getException();
                    status = apiException.getStatusCode();
}

상태 코드가 SIGN_IN_REQUIRED이면 플레이어를 다시 인증해야 함을 나타냅니다. 이를 위해 GoogleSignInClient.getSignInIntent()를 호출하여 플레이어를 대화식으로 로그인합니다.

요약


기존 GoogleApiClient 방식 대신, 더욱 느슨하게 결합된 API 클라이언트 사용으로 변경됨에 따라 상용구 코드가 줄어들고 사용 패턴이 더욱 명확해지고 스레드 안전성이 확보되는 이점이 있습니다. 현재 게임을 API 클라이언트로 마이그레이션하는 경우 다음 자료를 참고하시기 바랍니다.

게임에 대한 로그인 모범 사례:
https://developers.google.com/games/services/checklist

Play Games Services 샘플:
Android 기본 샘플
클라이언트 서버 골격

StackOverflow:
https://stackoverflow.com/questions/tagged/google-play-games

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

게시자: John Shriver-Blake, 제품 관리자


올해 초 Fabric 구성원들이 Firebase와 함께 하기로 했을 때, 우리는 앱을 개발하는 과정에서 일반적으로 발생하는 문제를 해결하는 플랫폼을 제공함으로써 여러분과 같은 개발자들이 멋진 사용자 환경을 만드는데 집중하게 하자는 공통된 목표를 달성하는 것에 뜻을 모았습니다.

많은 영역 중에서도 Fabric이 뛰어난 한 가지는 바로 콘솔과 대시보드였습니다. 우리는 지난 몇 달 동안 Fabric과 협력하여 Fabric과 Firebase에서 가장 뛰어난 부분을 하나로 합치려는 노력을 해왔습니다. 오늘, 우리는 Firebase 콘솔에 대한 몇 가지 개선 사항을 알려드리고자 합니다.


새롭게 설계된 탐색 기능

우리는 먼저 개발팀이 작업하는 방식을 더욱 정확히 반영하기 위해 탐색 기능을 새로 설계하는 작업부터 시작했습니다. 그래서 Firebase 제품을 네 개 그룹, 즉 개발, 안정성, 분석 및 성장으로 묶었습니다. 기존에 Firebase 콘솔에 표시되었던 제품들은 모두 그대로 표시되며, Firebase 플랫폼에서 제공하는 여러 제품들을 더욱 간단히 탐색할 수 있게끔 각 항목들을 재구성했습니다.

새로운 프로젝트 홈

몇 가지 중요 측정항목을 전면과 중심에 표시하도록 Firebase 콘솔의 프로젝트 홈 화면도 다시 설계했습니다. 이제는 Firebase에서 프로젝트를 처음 열 때 네 개의 주요 측정항목, 즉 30일간 비정상 종료가 발생하지 않은 사용자 비율, 30일간 비정상 종료 발생 횟수, 일일 활성 사용자 수 및 매월 활성 사용자 수와 함께 시간 경과에 따라 이러한 추세를 표시하는 그래프가 표시됩니다. 연구 조사를 수행한 결과 개발자는 이 네 가지 측정항목 중 하나를 찾는 데 대부분의 시간을 쓰고 있다는 사실을 확인했으므로 프로젝트 홈 방문 페이지에서 이러한 측정항목에 손쉽게 액세스할 수 있게 했습니다.

Latest Release

많은 사랑을 받은 또 다른 Fabric 콘솔 기능은 Latest Release 섹션입니다. 이 대시보드에서는 최신 앱 출시에서 가장 중요한 통계 정보 일체를 제공하므로 무엇이 잘 진행되고 있는지, 무엇을 롤백해야 하는지 빠르게 파악할 수 있습니다. Latest Release 섹션은 새로 설계된 Firebase 콘솔의 Analytics 섹션 하위에서 찾아볼 수 있습니다. 

업데이트된 Analytics 대시보드

오늘부터 Analytics 대시보드가 궁금한 사항을 쉽게 이해할 수 있도록 단순한 카드로 구성된 것을 볼 수 있을 것입니다. 'DAU' 또는 '사용자 유지 집단(코호트)'과 같은 용어를 기준으로 데이터를 구성하면 탐색하기 어렵기 때문에 "내 사용자가 어디에 참여하는가?" 또는 "사용자를 얼마나 잘 유지하고 있는가?"와 같이 앱과 관련하여 궁금해하는 사항을 기준으로 대시보드를 다시 구성했습니다. 연구 조사 결과 사용자 중 90%가 이 설계를 선호하는 것으로 확인되었으며 여러분도 이 설계가 유용하다는 점을 확인하시게 되기를 바랍니다!


실시간 정보

Fabric의 동료들과 여러 개발자들로부터 들은 의견을 통해 실시간 정보 확보가 중요하다는 점을 알게 되었습니다. 새로운 앱 출시 여부를 추적하거나 버그 수정 상태를 모니터링하는 것과 관계없이 앱에서 어떤 일이 일어나고 있는지 실시간으로 파악할 수 있어야 하며,  이에 따라 변경사항을 반영하거나 작업의 우선 순위를 지정할 수 있어야 합니다.

이를 위해, 새로운 Analytics 대시보드에 표시되는 카드와 콘솔의 Latest Release 섹션에 비정상 종료 및 활성 사용자에 대한 실시간 데이터를 추가되었습니다. 이는 단지 첫 시작일 뿐입니다. 앞으로 계속해서 Firebase 콘솔의 나머지 부분에서도 실시간 데이터를 더 많이 확인할 수 있도록 지원할 계획입니다.

늘 그렇듯이 https://firebase.google.com/support/를 방문하여 피드백을 남기고 궁금한 사항을 질문하실 수 있습니다.

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 곽동현(Machine Learning GDE)님이 참여해 주셨습니다.>
게시자: Sujith Ravi, Google Expander 팀 연구원
올해 초, 우리는 스마트 메시징을 위한 '온디바이스' 기계 학습 기술을 최초로 적용한 Android Wear 2.0을 출시했습니다. 이를 통해 이전에는 Gmail, InboxAllo에서 사용할 수 있었던 Smart Reply 같은 클라우드 기반 기술을 클라우드에 연결할 필요 없이 타사 메시징 앱을 비롯한 애플리케이션 내에서 최초로 직접 사용할 수 있게 되었습니다. 이에 따라 이동 중에 스마트워치에서 바로 수신되는 채팅 메시지에 응답할 수 있습니다.

저희는 오늘 모바일 및 내장형 기기용 TensorFlow 경량 솔루션인 TensorFlow Lite를 발표합니다. 이 프레임워크는 작은 메모리 사용 공간 및 신속한 성능에 중점을 두고 기계 학습 모델의 짧은 시간 내 추론에 맞게 최적화되었습니다. 우리는 개발자와 연구자들이 온디바이스 추론으로 구동되는 새로운 머신 인텔리전스 기능을 더욱 쉽게 빌드할 수 있도록 하기 위해 온디바이스 대화형 모델과 함께, TensorFlow Lite로 구동되는 자연어 애플리케이션의 사례를 제공하는 데모 앱을 라이브러리의 일부로 출시했습니다. 이 모델에서는 채팅 애플리케이션에 쉽게 플러그인할 수 있는 효율적인 추론 기능을 통해 대화형 채팅 메시지 입력에 대한 회신 제안을 생성함으로써 온디바이스 대화형 인텔리전스를 구동합니다.

우리가 출시한 온디바이스 대화형 모델에서는 ProjectionNet: 신경 프로젝션 기술을 사용한 효율적인 온디바이스 딥 네트워크 학습(Learning Efficient On-Device Deep Networks Using Neural Projections)에서 처음 제시된 결합 최적화 프레임워크를 기반으로 컴팩트 신경망(및 기타 기계 학습 모델)을 훈련하는 데 새로운 ML 아키텍처를 사용합니다. 이 아키텍처는 컴팩트 비트 벡터 표현으로 입력을 변환하는 효율적인 '프로젝션' 작업을 사용하여 컴퓨팅 성능과 메모리가 제한적인 상황에서도 휴대기기에서 효율적으로 실행될 수 있습니다. 유사한 입력은 프로젝션 유형에 따라 조밀하거나 희소성을 띠는 가까운 벡터로 프로젝션됩니다. 예를 들어, "안녕, 어떻게 지내?""친구야, 어떻게 지내니?"라는 메시지는 동일한 벡터 표현으로 프로젝션될 수 있습니다.

대화형 모델은 이 아이디어를 바탕으로 적은 계산 및 메모리 사용 공간에서 이러한 효율적인 작업을 결합합니다. 우리는 두 가지 모델 유형을 결합으로 훈련하는 ML 프레임워크(즉, 컴팩트 프로젝션 모델(위 설명)과 트레이너 모델 결합)를 사용하여 이러한 온디바이스 모델을 완벽하게 훈련했습니다. 이 두 모델은 결합 방식으로 훈련되며, 여기서 프로젝션 모델은 트레이너 모델로부터 학습합니다. 트레이너는 전문가라는 특징을 띠고 더욱 크고 복잡한 ML 아키텍처를 사용하여 모델링되는 반면, 프로젝션 모델은 전문가로부터 학습하는 학생과 유사합니다. 훈련 중에 양자화 또는 증류와 같은 다른 기법을 추가로 적용하여 더욱 밀도 높은 압축을 구현하거나 선택적으로 목적 함수의 특정 부분을 최적화할 수도 있습니다. 훈련을 마치고 나면 기기에서 추론을 위해 더 작은 프로젝션 모델을 직접 사용할 수 있습니다.

추론을 위해, 모바일 플랫폼에서 신속하게 실행할 수 있도록 최적화된 TensorFlow Lite 작업 세트로 훈련된 프로젝션 모델이 컴파일된 후 기기에서 바로 실행됩니다. 온디바이스 대화형 모델에 대한 TensorFlow Lite 추론 그래프는 다음과 같습니다.
온디바이스 대화형 모델에 대한 TensorFlow Lite 실행.
오늘 출시되는 오픈소스 대화형 모델(코드와 함께 출시)은 위에서 설명한 결합 ML 아키텍처를 사용하여 완벽히 훈련된 모델입니다. 오늘 출시에는 데모 앱도 포함되어 있으므로 휴대기기에서 원터치 스마트 회신 기능을 쉽게 다운로드해 사용해 보실 수 있습니다. 이 아키텍처를 통해 애플리케이션 요구 사항을 기준으로 모델 크기와 예측 품질을 손쉽게 구성할 수 있습니다. 여기서 이 모델이 올바른 효과를 발휘하는 샘플 메시지 목록을 확인할 수 있습니다. 시스템에서는 채팅 대화에서 관찰된 인기 있는 응답 인텐트에서 학습되고 컴파일된 고정된 세트를 통해 회신 제안을 폴백할 수도 있습니다. 기본 모델은 Google이 해당 앱에서 Smart Reply 응답에 사용하는 모델과 다릅니다1.

대화형 모델 이외의 옵션

흥미롭게도, 위에서 설명한 ML 아키텍처에서는 기본 모델을 유연하게 선택할 수 있습니다. 우리는 이 아키텍처를 여러 기계 학습 접근 방식과도 호환되도록 설계했습니다. 예를 들어, TensorFlow 딥 러닝에 사용하는 경우 기본 모델에 대해 경량 신경망(ProjectionNet)을 학습하는 반면, 다른 아키텍처(ProjectionGraph)는 신경망 대신 그래프 프레임워크를 사용하는 모델을 나타냅니다.

결합 프레임워크는 여러 가지 ML 모델링 아키텍처를 사용하는 작업에 대해 경량의 온디바이스 모델을 훈련하는 데 사용할 수도 있습니다. 일례로서, 우리는 동적 프로젝션 작업으로 구성된 단순한 프로젝션 아키텍처 및 완전히 연결된 몇 가지 좁은 계층이 결합된 트레이너 모델에 대해 복잡한 피드 전달 또는 반복 아키텍처(예: LSTM)를 사용하는 ProjectionNet 아키텍처를 도출했습니다. 전체 아키텍처는 TensorFlow에서 역전파를 사용하여 완벽하게 훈련되며 훈련을 마치고 나면 간결한 ProjectionNet이 추론에 직접 사용됩니다. 우리는 이 방법을 사용하여 모델 크기를 상당히 축소시키고(최대 몇 자릿수 이상 축소) 여러 시각적 및 언어 분류 작업(몇 가지 예는 여기를 참조)에 대한 정확성과 관련하여 높은 성능을 실현하는 소형 ProjectionNet 모델을 성공적으로 훈련했습니다. 마찬가지로 반지도학습 설정에서도 그래프 학습 프레임워크를 사용하여 다른 경량 모델을 훈련했습니다.
온디바이스 모델 훈련을 위한 ML 아키텍처: 딥 러닝을 사용하여 훈련된 ProjectionNet(왼쪽)과 그래프 학습을 사용하여 훈련된 ProjectionGraph(오른쪽).
우리는 앞으로도 계속해서 TensorFlow Lite 모델을 향상하고 업데이트된 모델을 오픈소스로 출시할 예정입니다. 이러한 ML 아키텍처를 사용하여 학습된 출시 모델(및 향후 모델)은 많은 자연어 및 컴퓨터 버전 애플리케이션에 재사용하거나 머신 인텔리전스 실현을 위해 기존 앱에 연결할 수 있을 것입니다.  기계 학습 및 자연어 처리 커뮤니티에서 이를 바탕으로 우리가 아직 생각하지 못한 새로운 문제 및 활용 사례를 처리할 수 있게 되기를 바랍니다.

감사의 말
Yicheng Fan 씨와 Gaurav Nemade 씨가 이 작업에 막대하게 기여했습니다. Rajat Monga, Andre Hentz, Andrew Selle, Sarah Sirajuddin과 TensorFlow 팀의 Anitha Vijayakumar, 그리고 Robin Dua, Patrick McGregor, Andrei Broder, Andrew Tomkins과 같은 분들은 물론 Google Expander 팀에게도 감사의 인사를 전합니다.



1 출시된 온디바이스 모델은 휴대폰 및 웨어러블 기기에서 지연 시간이 짧은 소규모 애플리케이션에 최적화할 목적으로 훈련되었습니다. 하지만 Google 앱의 Smart Reply 예측은 그보다 크고 복잡한 모델을 사용하여 생성되었습니다. 또한, 프로덕션 시스템에서는 부적절한 콘텐츠를 감지하도록 훈련된 여러 분류자를 사용하며 추가 필터링 및 조정을 적용하여 사용자 환경 및 품질 수준을 최적화하고 있습니다. 오픈소스 TensorFlow Lite 버전을 사용하는 개발자는 최종 애플리케이션에 이와 같은 방법도 따를 것을 권장합니다.

<블로그 원문은 여기에서 확인하실 수 있으며, 블로그 번역 리뷰는 최성준(Machine Learning GDE)님이 참여해 주셨습니다.>
게시자: Chris Olston(TensorFlow Serving 연구원) 및 Noah Fiedel(TensorFlow Serving 소프트웨어 엔지니어)

2016년 2월 TensorFlow Serving이 처음으로 오픈소스로 제공된 이후 우리는 몇 가지 주요 기능을 대폭 개선했습니다. 우리가 처음 시작한 때를 되돌아보고, 그동안의 진행 상황을 다시 짚어보고, 앞으로 나아갈 방향에 대해 얘기해 보도록 하겠습니다.

TensorFlow Serving이 출시되기 전, Google 내 TensorFlow 사용자는 자신만의 서비스 제공 시스템을 처음부터 새로 생성해야 했습니다. 서비스 제공은 얼핏보면 쉬운 것처럼 보이지만, 일회성 서비스 제공 솔루션은 빠르게 그 복잡성이 증가합니다. 기계 학습(ML) 서비스 제공 시스템은 모델 버전 관리(롤백 옵션을 포함한 모델 업데이트용) 및 다중 모델(A/B 테스트를 통한 실험용)을 지원해야 하면서, 동시에 동작하는 모델들이 하드웨어 액셀러레이터(GPU 및 TPU)를 통해 짧은 지연 시간으로 높은 처리량을 달성하도록 보장해야 합니다. 따라서 우리는 범용적인 단일 TensorFlow Serving 소프트웨어 스택을 만들기로 했습니다.

우리는 이를 처음부터 오픈소스로 제공 가능하도록 만들기로 결정했으며 2015년 9월에 개발을 시작했습니다. 몇 달 후 우리는 완벽하게 작동하는 초기 시스템을 제작했으며 2016년 2월에 오픈소스 릴리스를 했습니다.

지난 1년 반 동안 우리 회사 내외부의 사용자와 파트너의 도움 덕분에 TensorFlow Serving은 성능, 모범 사례 및 표준 측면에서 다음과 같은 발전을 이루었습니다.
  • 최적화된 서비스 제공 및 사용자설정 기능 기본 제공: 우리는 이제 AVX 지원 최신 CPU에 맞게 최적화되어 미리 빌드된 표준 서비스 제공 바이너리를 제공하므로 개발자가 특별한 요구 사항이 없는 한 Google 라이브러리에서 자체적인 바이너리를 어셈블할 필요가 없습니다. 그와 동시에, 레지스트리 기반 프레임워크를 추가하여 라이브러리를 사용자설정(또는 TensorFlow 이외) 서비스 제공 시나리오에 사용할 수 있도록 했습니다.
  • 다중 모델 서비스 제공: 한 모델에서 동시에 서비스가 제공되는 여러 모델로 전환하면 성능과 관련하여 여러 가지 장애물이 발생합니다. 우리는 (1) 격리된 스레드 풀에 로드하여 트래픽이 발생시키는 다른 모델에서 지연 시간의 급증이 발생하지 않도록 하고, (2) 서버 시작 시 모든 모델의 초기 병렬 로드를 가속화하며, (3) 다중 모델 배치 인터리빙을 통해 하드웨어 액셀러레이터(GPU/TPU)를 다중화함으로써 다중 모델을 원활하게 제공합니다.
  • 모델 형식 표준화: 우리는 SavedModel을 TensorFlow 1.0에 추가하여 훈련 및 서비스 제공 간에 제대로 작동하는 단일의 표준 모델 형식을 커뮤니티에 제공했습니다.
  • 사용이 간편한 추론 API: 우리는 일반적인 추론 작업(분류, 회귀)에 사용할 수 있는 사용이 간편한 API를 출시했으며, 이는 광범위한 Google 애플리케이션에서 올바르게 작동하는 것으로 확인되었습니다. 더욱 발전된 사용을 지원하기 위해 더 low-level tensor 기반 API(predict)와 멀티태스킹 모델링을 사용하는 새로운 다중 추론 API를 지원합니다.
이 모든 작업은 (a) 우리가 내실을 기하고 내부 SLA를 충족하도록 하는 데 도움을 주는 Google의 ML SRE 팀, (b) 광고 서비스 제공 및 TFX를 포함한 기타 Google 기계 학습 인프라 팀, (c) Google Play 등의 애플리케이션 팀, (d) Clipper 서비스 제공 시스템과 관련한 상호 보완적인 연구 문제를 탐구하는 UC 버클리 RISE Lab 파트너, (e) Google 오픈소스 사용자 기반 및 기고자와의 긴밀한 협업을 바탕으로 이루어졌습니다.

TensorFlow Serving은 현재 Google의 Cloud ML Prediction을 비롯하여 1,100개 이상의 Google 자체 프로젝트에 대해 초당 수천만 개의 추론을 처리하고 있습니다. Google의 핵심 서비스 제공 코드는 오픈소스 릴리스를 통해 모두에게 제공됩니다.

앞으로 계속해서 우리가 하는 작업은 무궁무진할 것이며 혁신을 꾀할 수 있는 여러 방안을 모색 중입니다. 오늘 우리는 두 가지 실험 영역에서 초기 진행 상황을 알려드리고자 합니다.
  • 세분화된 일괄 처리: 특수화된 하드웨어(GPU 및 TPU)를 통한 높은 처리량을 달성하기 위해 우리가 택한 핵심 기술은 여러 사례를 공동으로 처리하여 효율성을 높이는 기술인 '일괄 처리'입니다. 우리는 (a) 효율성을 극대화하기 위해 일괄 처리가 계산에서 GPU/TPU 부분만 대상으로 삼을 수 있도록 하고, (b) 텍스트 및 이벤트 시퀀스와 같은 시퀀스 데이터를 처리하는 데 사용되는 순환적 신경망 내에서 일괄 처리가 가능하도록 하는 것을 목표로 일괄 처리를 향상할 수 있는 기술과 모범 사례를 개발하고 있습니다. 우리는 일괄 처리/일괄 처리 해제 작업 쌍을 사용하여 임의의 부분 그래프를 일괄 처리하는 것을 실험하고 있습니다.
  • 분산 모델 서비스 제공: 우리는 하나의 서버 노드에 맞추기에는 너무 큰 모델을 처리하거나 메모리 효율적인 방식으로 하위 모델을 공유하는 수단으로서 모델 분할 기술을 연구하고 있습니다. 최근에 프로덕션 환경에서 1TB 이상의 모델을 출시하고 좋은 결과를 내고 있으며, 이 기능을 곧 오픈소스로 제공하기를 바라고 있습니다.
다시 한 번 피드백, 코드, 그리고 아이디어를 주신 모든 사용자와 파트너 여러분께 감사 말씀을 올립니다. github.com/tensorflow/serving에서 프로젝트에 참여해 주시기 바랍니다.

구글코리아가 글로벌 혁신 제품 개발에 참여할 소프트웨어 엔지니어를 채용합니다. 이번 채용 모집분야는 검색, 안드로이드, 사물인터넷(IoT), 구글 어시스턴트 등 현재 개발 중인 구글 서비스 전 분야에 걸쳐 신입 및 경력, 인턴 등 다양한 개발자를 모집합니다.

구글코리아 엔지니어링팀은 그동안 글로벌 혁신 제품 개발에 참여해 왔으며, 특히 검색 서비스 중 금융 및 엔터테인먼트 분야, 안드로이드 부문 멀티미디어 및 시스템 분야, 사물인터넷(IoT) 플랫폼 및 구글 어시스턴트의 검색 연동 기능 개발 등에 집중해왔습니다.

특히 구글의 소프트웨어 엔지니어는 한국 뿐 아니라 전세계 수십억 명의 사용자가 정보를 연결하고, 탐색하며, 상호작용하는 방식을 바꿀 수 있는 차세대 테크놀로지를 개발하게 됩니다. 따라서 이번 채용에서는 해결해야 하는 문제를 탐색하여 잘 정의하고 이를 주도적으로 풀어나가는 적극적 자세와 새로운 기술에 대한 지속적인 관심과 더불어 빠른 학습 능력을 가진 역량있는 지원자를 눈여겨 볼 계획입니다.

구글은 포춘(Fortune)에서 6년 연속 ‘일하기 좋은 100대 기업’ 1위를 기록하고 있습니다. 특히 한국에서는 ‘2017 대한민국 일하기 좋은 100대 기업’에서 국가 간 우호 교류 및 신뢰 경영 문화 조성에서 괄목할 성과를 낸 기업 및 기관, 개인에 시상하는 특별상을 수상하는 등 기업 문화 발전에 노력하고 있습니다. 또한, 엔지니어링 업계 다양성 활성화를 위해 여성 소프트웨어 캠프 및 장학금 제도를 비롯하여 컴퓨터 전공 여학생을 대상으로 다양한 프로그램을 진행하는 등 국내 여성 개발자 육성에도 힘쓰고 있습니다.

각 분야별 구체적인 모집 분야와 자격 요건 등에 대한 상세한 내용은 아래 표와 구글 채용 페이지를 통해 확인하실 수 있습니다. 구글의 차세대 기술을 이끌 국내 엔지니어들의 많은 관심과 지원을 기대하겠습니다!
모집 직군
모집 분야
인원
소프트웨어 엔지니어 경력
(00명)
Engineering Manager, Android Media
(안드로이드 미디어, 엔지니어링 매니저)
0명
Software Engineer, Pixel Camera
(카메라 분야 소프트웨어 엔지니어)
00명
Software Engineer, Android OS
(안드로이드 OS, 소프트웨어 엔지니어)
0명
Software Engineer, Tools and Infrastructure
(툴과 인프라스트럭처, 소프트웨어 엔지니어)
0명
Software Engineer - Seoul (소프트웨어 엔지니어)
00명
소프트웨어 엔지니어 신입
(00명)
Software Engineer, University Graduate (소프트웨어 엔지니어)
00명
소프트웨어 엔지니어 인턴
(00명)
2018 소프트웨어 엔지니어 인턴(공지 예정)
00명

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

게시자: Marc Stogaitis 및 Tajinder Gadh, 소프트웨어 엔지니어


운전은 우리의 일상 활동에 있어 필수적인 부분입니다. 따라서 Google에서는 어떻게 하면 Android 기기를 Google 사용자가 사용하기에 더 적합하고 안전하게 만들 수 있을지 고심하는 데 많은 시간을 할애합니다. 운전에 방해가 되지 않도록 하고 개방적인 에코시스템을 빌드하여 안전이 최우선인 스마트폰 환경을 구현할 수 있을까 하는 고심 말입니다.

우리는 최근에 새로 발표한 Pixel 2세대 기기에서 운전 중 알림 일시중지 기능을 선보였습니다. 운전 중 알림 일시중지 기능을 사용하면 운전할 때 기기가 자동으로 알림 일시중지 모드로 전환됩니다. 이 모드에서는 수신 메시지와 알림이 무음 처리되지만 수신 전화, 내비게이션 안내 및 음성 상호작용은 연결된 차량 블루투스를 이용해 계속 받을 수 있습니다. 이 제품은 운전 중 주의를 산만하게 할 요소를 최대한 줄이는 동시에 사용자가 계속해서 원활하게 내비게이션 또는 이와 유사한 다른 앱은 방해받지 않고 사용할 수 있도록 설계되었습니다.

이면을 살펴보면, 이 제품은 여러 센서, 블루투스 및 와이파이에서 저출력 신호를 사용하여 사용자가 운전 중일 때를 감지하는 AI 기반 온디바이스 동작 인식을 사용합니다. 동작 인식 기능은 Android 센서 허브를 사용하여 짧은 지연 시간, 낮은 전력 및 정확한 운전 감지를 보장합니다.

이것이 바로 우리가 나아가야 할 다음 단계이지만 앞으로도 갈 길이 멉니다. 내년 초에는 산만한 요소가 없는 운전 환경을 빌드하기 위해 운전 중 알림 일시중지 기능에서 사용되는 동일한 API인 Activity Recognition Transition API를 출시할 예정입니다.

보내주신 피드백에 감사드리며, 제품의 진화에 따라 계속 여러분의 의견을 경청할 것입니다.

운전 중 알림 일시중지 기능 설정에 관해 궁금한 사항이 있으시면 고객센터를 통해 확인하시기 바랍니다.