한국의 개발자들을 위한 Google for Developers 국문 블로그입니다.
안드로이드 Q 베타를 소개합니다
2019년 3월 28일 목요일
<블로그 원문은
이곳
에서 확인하실 수 있으며 블로그 번역 및 리뷰는 양찬석(Google)님이 참여해 주셨습니다>
게시자: Dave Burke, 엔지니어링 부사장
그 어느 때보다 모바일 혁신이 활발합니다. 5G, 에지-투-에지(Edge-to-Edge) 디스플레이, 폴더블 디스플레이 같은 신기술이 등장했고,
안드로이드는 바로 그 혁신의 중심에 있습니다.
수십 억 대의 기기를 아우르는 광범위한 파트너 생태계를 구축하고, 하드웨어와 소프트웨어의 한계를 시험하며, 새로운 경험과 기능을 사용자에게 제공하도록 돕고 있습니다.
안드로이드는 사용자에게 혁신적인 기술을 제공하면서 동시에 사용자 개인정보를 최우선 순위로 보호하는 데 초점을 맞춰 왔습니다. 안드로이드 Q는 이 연장선상에서 특히나 더 많은 노력과 변화를 담고 있습니다. Google Play 프로텍트와 런타임 권한을 기반으로 개인정보 보호 및 보안 기능을 제공하며, 폴더블 폰을 위한 개선, 연결성을 위한 새로운 API, 새로운 미디어 코덱과 카메라 기능, NNAPI 확장 프로그램, Vulkan 1.1 지원, 앱 시작 속도 개선 등 다양한 기능이 추가되었습니다.
3월 14일 얼리 어답터를 위한 안드로이드 Q 베타 1과 개발자를 위한 Preview SDK가 공개되었습니다. 안드로이드 Q에 어떤 기능이 추가되었는지 간단히 살펴보겠습니다. 더욱 자세한 내용은
5월에 개최될 Google I/O
에서 말씀드리겠습니다.
안드로이드에서 개인정보 보호 강화
안드로이드는 보안과 개인정보 보호를 중심에 두고 설계 되었고, 사용자를 보호하기 위한 다양한 기술이 추가되었습니다. 예를 들어
파일 기반 암호화
, 앱이
민감한 리소스에 액세스 하기 전에 권한을 요청하도록 하는
OS 컨트롤,
카메라/마이크 백그라운드 액세스
잠금,
잠금 모드
,
암호화된 백업
,
Google Play 프로텍트
(하루에 500억 개 이상의 앱을 스캔하여 잠재적으로 위험한 앱을 식별하고 제거) 등이 있습니다. 안드로이드 Q에서는 사용자를 보호하기 위한 조치를 더욱 강화했습니다. 이와 관련된 개선 사항은 대부분
프로젝트 스트로브
작업에서 파생되었습니다.
사용자의 위치 정보 제어 기능 강화
사용자가 앱이 위치 정보를 얻을 수 있는 시점을 제어하는 기능이 강화되었습니다. 기본적으로 앱이 사용자에게 권한을 요청하고 사용자가 이를 허락해야만 기기 위치 정보를 얻을 수 있습니다.
앱을 사용하지 않을 때(백그라운드에 있을 때) 위치 정보에 액세스 하는 문제는 보다 민감합니다. 안드로이드 Q에서 사용자는 아래의 옵션 중 한 가지를 선택 할 수 있습니다.
앱에 위치 정보를 제공하지 않음.
사용 중일 때(실행 중일 때)만 위치 정보를 제공
항상 위치 정보를 제공(앱이 백그라운드에 있을 때도)
예를 들어, 음식 배달을 위해 사용자의 위치를 요청하는 것은 타당하고, 사용자는 편하게 해당 권한을 부여할 수 있습니다. 하지만 앱을 사용하지 않을 때는 위치 정보가 필요하지 않을 수 있고, 사용자는 그럴 경우에는 액세스 권한을 부여하고 싶지 않을 수 있습니다. 새로운 제어 기능을 앱에 도입하는 자세한 방법은
개발자 가이드
를 참조하시기 바랍니다.
안드로이드 Q에서 개인정보 보호 강화
위치 정보에 대한 변경 외에도 투명성을 보장하고, 사용자에게 더 많은 제어 권한을 제공하고, 개인 데이터를 보호하기 위한 추가 업데이트를 진행 중입니다. 안드로이드 Q에서는 사용자가 공유된 파일에 대한 액세스를 보다 정교하게 제어할 수 있습니다. 새로운 런타임 권한을 통해, 앱이 사진과 동영상 혹은 오디오 컬렉션에 액세스 하는 권한을 제어할 수 있게 됩니다. 다운로드 컬렉션의 경우에는 반드시 시스템 파일 선택기를 사용해야 하며, 사용자는 앱이 접근 할 다운로드 파일을 직접 선택해야합니다. 개발자에게 해당하는 사항도 있습니다. 앱이 외부 저장소에 공유된 영역을 사용하는 방식이 변경되었습니다. 자세한 정보는
범위 지정 저장소 변경 사항
을 참조하세요.
앱이 갑자기 포그라운드로 나와서 포커스를 차지하면 짜증스럽습니다. 안드로이드 Q에서는 앱이 백그라운드에 있을 때 Activity를 시작하지 못하게 됩니다. 앱이 백그라운드에 있는데, 즉시 사용자의 주의를 끌어야 할 필요가 있을 경우(예: 전화 또는 알람 수신) 우선순위가 높은 알림과 전체 화면 인텐트(FullScreenIntent)를 대신 사용 할 수 있습니다. 자세한 정보는
문서
를 참조하세요.
추가로, 기기 IMEI, 일련번호 및 기타 유사한 식별자를 포함하여 재설정이 불가능한 기기 식별자에 대한 액세스를 제한할 것입니다. 자신의 사용 사례에 알맞은 식별자를 선택하는 데 도움이 필요하다면
모범 사례
를 읽어보세요. 자세한 정보는
여기
를 참조하세요.
또한 다른 Wi-Fi 네트워크에 연결되면 기기의 MAC 주소를 무작위 설정하도록 기본 설정됩니다. 안드로이드 9 Pie에서는 이 기능이 선택 항목이었습니다.
개발자분들이 가능한 한 빨리 동작 변경 사항을 테스트할 수 있도록, 첫 번째 베타 버전에 많은 사항을 미리 적용했습니다. 또한 가능한 상세한 정보를 알려드리고자 많은 노력을 기울였습니다. 개인정보 보호정책의 변경 사항을
상세 문서
에서 확인하시고 바로 테스트를 시작하시는 것이 좋습니다.
새로운 사용자 경험
안드로이드 Q에서는 사용자가 앱과 상호작용하는 새로운 방법이 도입되고, 한 앱에서 다른 앱으로 전환하는 사용자 경험이 간소화됩니다.
폴더블 폰과 혁신적인 새로운 스크린
폴더블 기기 덕분에 혁신적인 사용자 경험의 문이 열렸습니다. 폴더블 기기와 다른 대형 화면 기기를 더 잘 활용할 수 있도록 여러 사항이 개선되었습니다. 예를 들어 하나 이상의 앱이
onResume
상태에 머무를 수 있도록 지원하고, 포커스를 가져왔을 때 앱이 이를 알 수 있도록 변경되었습니다. 또한 폴더블 폰과 대형 화면에서 앱이 표시되는 방식을 관리할 수 있도록
resizeableActivity
매니페스트 속성의 작동 방식을 변경했습니다. 개발자 여러분이 이런 동작을 테스트 할 수 있도록 안드로이드 Emulator를 업데이트할 계획입니다. 자세한 정보는 곧 알려드리겠습니다!
공유 바로가기 (Share Shortcut)
사진과 같은 콘텐츠를 다른 앱에 있는 사람과 쉽게 공유할 수 있어야 합니다. 안드로이드 Q에서는 공유 바로가기를 통해 다른 앱으로 바로 넘어가 콘텐츠를 공유할 수 있게 됩니다. 개발자는 공유할 콘텐츠와 대상을 지정해 바로 Activity를 시작할 수 있는 공유 대상(Share Targer)을 게시할 수 있고, 이 정보는 공유 UI에서 사용자에게 표시됩니다. 공유 대상은 미리 게시되어 있기 때문에 공유 UI가 시작하는 순간 바로 로드됩니다.
공유 바로가기 메커니즘은 앱 바로가기의 작동 원리와 비슷합니다. 그래서
ShortcutInfo API
를 확장해 두 기능을 더욱 간편하게 통합할 수 있게 했습니다. 이 새로운 API는 새로운 ShareTarget AndroidX 라이브러리에서도 지원됩니다. 이렇게 하면 안드로이드 Q 이전 버전을 사용하는 기기에서는 직접 공유(Direct Share)로 동작하고, Q 이상 버전에서는 공유 대상 형태로 동작하도록 앱을 구현할 수 있습니다.
이 소스 코드
에서 기본적인 샘플 앱을 확인할 수 있습니다.
설정 패널
이제 새로운
Settings Panel API
를 통해 앱 내에서 주요 시스템 설정을 직접 표시할 수 있습니다. 안드로이드 9 Pie에서 도입한 Slices 기능이 활용되었습니다. 설정 패널은 플로팅 UI로, 앱에서 사용자에게 필요할 만한 시스템 설정(예: 인터넷 연결, NFC, 오디오 볼륨)을 표시할 때 사용할 수 있습니다. 예를 들어 브라우저는 비행기 모드, Wi-Fi(근처 네트워크 포함), 모바일 데이터 등의 연결 설정이 있는 패널을 표시할 수 있습니다. 사용자는 앱을 떠날 필요 없이 패널에서 바로 설정을 관리할 수 있습니다. 설정 패널을 표시하려면 새로운
설정 패널 액션
중 하나를 사용하여 인텐트를 실행하세요.
연결
안드로이드 Q에서는 앱이 안드로이드의 Connectivity 스택을 활용할 수 있는 범위를 확대하였고, 새로운 API를 추가했습니다.
연결성 권한, 개인정보 보호정책 및 보안
대부분의 네트워크를 스캔하는 API를 사용하기 위해서는 이미 COARSE 위치 권한이 필요합니다. 안드로이드 Q에서는 블루투스, 셀룰러, Wi-Fi에 대해서는 추가적으로 FINE 수준의 위치 권한을 요구합니다. 앱이 P2P 연결을 사용하거나 네트워크를 추천할 뿐이라면 아래의 개선된 Wi-Fi API를 확인하세요. 이 API는 연결을 단순화하고 위치 권한을 요구하지 않습니다.
안드로이드 Q는 다른 Wi-Fi 네트워크에 연결되었을 때 무작위 설정된 MAC 주소를 제공하는 외에도, 새로운 Wi-Fi 표준 지원, WPA3, Enhanced Open을 추가해 개방/공개 네트워크와 자택 및 직장 네트워크에서의 보안을 개선하고 있습니다.
P2P 및 인터넷 연결 개선
안드로이드 Q에서는 Wi-Fi 스택을 리팩터링 하여 개인정보 보호와 성능을 개선했을 뿐만 아니라 위치 권한을 요구하지 않고 IoT 기기 관리, 인터넷 연결 추천 등의 일반적 사용 사례를 구현할 수 있도록 기능을 확장하였습니다.
로컬 네트워크 상에서 IoT 기기를 활용하고자 할 때, 위치 권한 없이 디바이스 네트워크 연결 API를 통해 설정, 다운로드, 인쇄 등의 P2P 기능을 구현할 수 있습니다. 앱은 선호하는 SSID와 BSSID를
WiFiNetworkSpecifiers
로 지정하여 간접적으로 연결 요청을 시작합니다. 플랫폼은 Wi-Fi 스캐닝 자체를 처리하고 Wi-Fi 선택기에서 매칭 되는 네트워크를 표시합니다. 사용자가 선택하면 플랫폼이 연결을 자동으로 설정합니다.
네트워크 추천 API를 사용해, 사용자가 인터넷에 연결할 때 선호하는 Wi-Fi 네트워크를 고르는 UI를 표시할 수 있습니다. 앱은 순위가 지정된 네트워크 목록과 사용자 인증 정보를
WifiNetworkSuggestions
로 제공해 간접적으로 연결을 시작합니다. 플랫폼은 디바이스가 네트워크들의 범위에 들어갔을 때 과거의 성능에 기반해 자동으로 인터넷에 연결합니다.
Wi-Fi 성능 모드
안드로이드 Q에서 고성능 및 저지연 모드를 활성화하여, 적응형 Wi-Fi를 요청할 수 있습니다. 실시간 게임, 액티브 음성 통화 및 그와 유사한 사용 사례 등과 같이 사용자 환경에 낮은 지연이 중요할 경우에 매우 큰 장점이 될 것입니다.
새로운 성능 모드를 사용하려면 WIFI_MODE_FULL_LOW_LATENCY 또는 WIFI_MODE_FULL_HIGH_PERF를 포함해
WifiManager.WifiLock.createWifiLock()
을 호출하세요. 플랫폼은 기기 펌웨어와 상호작용하여, 전력을 최소한으로 소모하면서도 요구 사항을 충족하기 위해 노력할 것 입니다.
카메라, 미디어, 그래픽
사진의 동적 깊이 형식
많은 휴대폰 카메라들이 피사체의 상대적인 배경 혹은 전경을 흐리게 해서 좁은 피사계 심도를 시뮬레이션할 수 있습니다. 이 카메라들은 이미지의 여러 지점에서 깊이 메타데이터를 수집하고 정적 블러를 적용합니다. 그러나 그 이후에 수집한 깊이 메타데이터를 폐기합니다.
안드로이드 Q에서부터는 동적 깊이 이미지를 요청할 수 있습니다. 동적 깊이 이미지는 JPEG 이미지, 깊이 관련 요소와 관련된 XMP 메타데이터, 동일한 파일에 삽입된 깊이 및 신뢰도 맵 (기기가 이 기능을 지원하는 경우)으로 구성됩니다.
JPEG + 동적 깊이 이미지를 요청하면 앱에서 전문적인 블러 및 보케 옵션을 제공할 수 있습니다. 심지어 이 데이터를 사용해 3D 이미지를 만들거나 나중에 AR 사진 사용 사례를 지원할 수 있습니다. 동적 깊이는 전체 생태계를 위해 개방적 형식이 될 것입니다. 기기 제조사 파트너와 협력하여 안드로이드 Q 이상을 실행하는 기기에서 이 기능을 제공하고자 합니다.
동적 깊이 이미지를 사용하면 앱에서 전문적인 블러 및 보케 옵션을 제공할 수 있습니다.
새로운 오디오 및 동영상 코덱
안드로이드 Q에서는 오픈소스 동영상 코덱
AV1
에 대한 지원이 도입됩니다. 이제 미디어 제공자들이
대역폭은 더 적게 사용하면서도
안드로이드 기기에 고화질 동영상 콘텐츠를 스트리밍 할 수 있습니다. 또한 안드로이드 Q는 음성과 음악 스트리밍에 최적화된 코덱인
Opus
를 사용한 오디오 인코딩을 지원합니다. 지원하는 기기에서는 HDR 동영상에 대해
HDR10+
이 지원됩니다.
MediaCodecInfo API
는 안드로이드 기기의 동영상 렌더링 기능을 보다 쉽게 결정할 수 있는 수단을 제공합니다. 어떤 코덱에 대해서든 VideoCodecCapabilities.getSupportedPerformancePoints()를 사용하여 지원되는 크기 및 프레임 레이트 목록을 얻을 수 있습니다. 이제 어떤 기기에서든 렌더링 하기에 가장 좋은 화질의 동영상 콘텐츠를 선택할 수 있게 됩니다.
네이티브 MIDI API
C++에서 오디오를 처리하는 앱을 위해 안드로이드 Q에서는 NDK를 통해 MIDI 기기와 통신하는
네이티브 MIDI API
가 도입됩니다. 이 API를 사용하면 non-blocking 읽기를 사용하여 오디오 콜백 내에서 MIDI 데이터를 검색하고, MIDI 메시지를 적은 지연으로 처리할 수 있습니다.
여기
에서 샘플 앱과 소스 코드를 확인해보세요.
Vulkan에서 ANGLE 지원
게임 개발자와 그래픽 개발자에게 더 높은 일관성을 제공하기 위해 Vulkan을 기반으로 한 모든 기기에 업데이트 가능한 표준 OpenGL 드라이버를 제공하고자 노력하고 있습니다. 안드로이드 Q에서는 안드로이드 기기에 설치된 Vulkan에 대해
ANGLE
을 실험적으로 지원하고자 합니다. ANGLE은 모든 구현에서 고성능 OpenGL 호환성을 보장하도록 설계된 그래픽 추상화 계층입니다. OpenGL ES를 사용하는 여러 앱과 게임이 ANGLE을 통해 Vulkan의 성능과 안정성을 활용하고 안드로이드 기기에서 벤더와 관계없이 ES를 일관적으로 구현하는 장점을 누릴 수 있습니다. 안드로이드 Q에서는 기본적으로 OpenGL ES 2.0를 지원하고 이 후 ES 3.0을 지원할 예정입니다.
더 많은 OpenGL 기능, 버그 수정, 성능 최적화를 통해 구현을 확장할 것입니다. 안드로이드에서 지원되는 최신 ANGLE, 사용 방법, 향후 계획에 대한 자세한 정보는
이 문서
를 참조하세요. 설정에서 개발자 옵션을 옵트 인하면 첫 지원을 테스트하기 시작할 수 있습니다. 지금 시험해보세요!
Vulkan의 보편화
저희는 안드로이드의
Vulkan
이 고성능 3D 그래픽을 위한 낮은 오버헤드 교차 플랫폼 API
구현
에 미치는 영향력을 지속적으로 확장하고 있습니다. Vulkan을 더 잘 지원해, 대표적인 그래픽 API로 만드는 것이 목표입니다. 기기 제조사 파트너와 협력하여 안드로이드 Q 이상을 실행하는 모든 64비트 기기에서 Vulkan 1.1을 요구 사항으로 지정하고, 모든 32비트 기기에서는 권장 사항으로 지정하고자 노력하고 있습니다. 이는 앞으로 앱과 게임이 사용할 수 있는 균일한 고성능 그래픽 API를 제공하는 데 도움이 될 것입니다.
Neural Networks API 1.2
2017년에 Neural Networks API(NNAPI)를 도입한 이후로 지원되는 오퍼레이션의 수를 꾸준히 늘리고 기존 기능을 개선하고 있습니다. 안드로이드 Q에서는 ARGMAX, ARGMIN, 양자화 LSTM을 포함한 60가지 새로운 오퍼레이션과 다양한 성능 최적화를 추가했습니다. 이는 개체 탐지 모델, 이미지 분할 모델 등의 훨씬 다양한 모델을 가속할 수 있는 기반이 됩니다. 현재 하드웨어 벤더 및 인기 머신러닝 프레임워크(예:
Tensor Flow)와
협력하여 NNAPI 1.2를 최적화하고 이에 대한 지원을 출시하고자 노력하고 있습니다.
안드로이드 기반 강화
ART 성능 향상
안드로이드 Q는 ART 런타임에 새로운 개선 사항이 여러 가지 도입됩니다. 이는 개발자의 노력 없이도 앱을 더욱 빠르게 시작하고 메모리 사용량을 줄이는 데 도움이 됩니다.
안드로이드 Nougat 이후로 ART는
프로필 가이드 최적화
(PGO)를 제공했습니다. 이 기능은 코드에서 자주 실행되는 부분을 식별하여 미리 컴파일함으로써 시간이 지남에 따라 앱 시작 속도를 향상합니다. 이제 Google Play는 최초의 앱 시작을 돕고자 APK와 함께 클라우드 기반 프로필을 제공합니다. 이들은 익명상태로 집계된 ART 프로필로, 앱을 실행하기 전부터 미리 컴파일할 수 있어서 전체적인 최적화 프로세스가 상당히 빨리 실행됩니다. 클라우드 기반 프로필은 모든 앱에 도움을 주며, 이미 안드로이드 P 이상을 실행하는 기기에 제공되고 있습니다.
또한 ART 자체도 꾸준히 개선 중입니다. 예를 들어 안드로이드 Q에서는 앱 프로세스를 조기에 시작하고 보안 컨테이너에 옮겨서 즉시 시작할 수 있도록 준비하는 방식으로 Zygote 프로세스를 최적화했습니다. 더 많은 정보(예: 클래스)를 앱의 힙 이미지에 저장하고 스레딩을 사용하여 이미지를 빠르게 로드합니다. Generational 가비지 컬렉션을 ART의 동시 복사(CC) 가비지 컬렉터에 추가했습니다. Generational CC는 아래 세대의 개체를 따로 수집하기 때문에 더욱 효율적이고, 완전한 힙 가비지 컬렉션에 비해 비용이 훨씬 절감되면서도, 효율적으로 넓은 공간을 확보할 수 있습니다. 시간과 CPU 측면에서 가비지 컬렉션이 전체적으로 효율화되어, 앱 끊김이 감소하고 낮은 성능의 기기에서 앱이 원활하게 실행되는 데 도움이 됩니다.
앱의 보안
BiometricPrompt
는 시스템 수준에서 생체 정보 인식을 지원하기 위한 통합 인증 프레임워크입니다. 안드로이드 Q에서는 수동적 인증 방식(예: 얼굴 인식)에 대한 지원을 확대하고 묵시적, 명시적 인증 UX를 추가합니다. 명시적 인증 UX에서 사용자는 인증 과정에서 TEE 내에서의 트랜잭션을 명시적으로 확인해야 합니다. 묵시적 UX는 수동적 인증을 사용한 트랜잭션의 가벼운 대체 방식으로 설계되었습니다. 또한 필요할 때 사용자 인증 정보를 다시 요청하는 UX도 개선했습니다.
안드로이드 Q에서는 성능이 더 좋고, 보안이 개선된
TLS 1.3
에 대한 지원이 추가됩니다. 벤치마크에 따르면, TLS 1.2보다 TLS 1.3을 사용했을 때 40% 빠르게 안전한 연결을 설정할 수 있습니다. TLS 1.3는 모든 TLS 연결에서 기본적으로 활성화됩니다. 자세한 내용은
문서
를 참조하세요.
SDK API를 통한 호환성
안드로이드는 OS가 변경되고 발전하더라도 앱이 원활하게 실행되도록 하는 것을 중요하게 생각합니다. SDK가 아닌 API를 사용하는 앱은 플랫폼 변경 시 앱이 동작하지 않을 수 있고, 개발자가 긴급 업데이트를 해야 할 위험이 있습니다.
안드로이드 P에서 시작된
장기적 노력의 일환으로 앱은 공개된 SDK API만 사용할 수 있습니다. SDK가 아닌 API의 사용을 중단하는 것은 시간이 걸리므로
미리
여러분께
알려드립니다
.
안드로이드 Q에서는 P에서 추가적으로
SDK가 아닌 인터페이스
에 접근하지 못하도록 제한하고, 그 대신 공개 API를 사용하도록 요청할 것입니다. 앱 수정을 위해 충분한 시간을 드리기 위해 앱이 안드로이드 Q를 타게팅할 때만 이러한 제한을 적용합니다. 여러분의 요청을 받아서 대체할 공개 API를 추가하고 있습니다. 만일 앱 동작에 필요한 기능인데 이를 위한 공개 API가 없을 경우 저희에게
알려주세요
.
SDK가 아닌 인터페이스를 사용할 때는
앱 테스트
가 중요합니다. StrictMode 메서드인
detectNonSdkApiUsage()
를 사용하여, 앱이 리플렉션이나 JNI를 통해 SDK가 아닌 API에 액세스 할 때 경고를 받을 수 있습니다. 현재 API가 면제 목록(그레이리스트)에 들어 있더라도 미래에 대비해 사용을 삼가고 호환성 문제를 줄이시기 바랍니다. 안드로이드 Q에서의 제한 사항에 대한 자세한 정보는
개발자 가이드
를 참조하세요.
최신 안드로이드
모든 앱이 최신 버전 안드로이드에서 보안 및 성능, 기능을 최대한 활용하도록 지원하는 노력을 확대하고 있습니다. 올해 후반에는 Google Play에서 새 앱과 업데이트를 등록할 때 의무적으로
앱의 targetSdkVersion을 28(안드로이드 9 Pie)로 설정
해야 합니다. 이러한 변화에 발맞추어 안드로이드 Q는 사용자가 API 레벨 23(안드로이드 Marshmallow) 이전의 플랫폼을 타게팅하는 앱을 처음 실행할 때 대화 상자로 경고할 것입니다.
리소스 체크리스트
를 참조하면 앱을 마이그레이션 하는 데 도움이 될 것입니다.
또한 64비트 기기의 출시에 대비한 생태계를 준비하고 있습니다. 올해 후반에는 Google Play에 있는
모든 앱이 64비트를 지원
해야 합니다. 앱이 네이티브 SDK나 라이브러리를 사용할 경우 64비트를 지원하는 SDK 또는 라이브러리 버전을 제공해야 함을 기억하세요. 준비에 대한 자세한 정보는
개발자 가이드
를 참조하세요.
안드로이드 Q 베타 시작하기
앱에 영향을 미칠 가능성이 있는 중요한 개인정보 보호 기능이 있기 때문에 지금부터 테스트를 시작하는 것이 좋습니다. 특히 안드로이드 Q 저장소 변경 사항, 새로운 위치 정보 권한 상태, 백그라운드 Activity 실행에 대한 제한, 기기 식별자에 대한 제한 사항을 테스트하는 것이 좋습니다. 자세한 정보는
개인정보 보호 문서
를 참조하세요.
Google Play에서 앱을 안드로이드 Q 베타를 실행하는 기기 또는
안드로이드 에뮬레이터
에 설치하고 사용해보시기 바랍니다. 앱이 올바르게 실행되고 아무런 문제가 없어 보여야 하며 모든 앱에서 안드로이드 Q의
변경된 동작
이 제대로 처리되어야 합니다. 문제를 발견하면 우선 타게팅 레벨을 변경하지 않고 현재 앱에서 수정하는 것이 좋습니다. 절차와 권장 일정에 대해서는
마이그레이션 가이드
를 참조하세요.
그다음에는 최대한 빨리 앱의 targetSdkVersion을 'Q'로 변경하세요. 이렇게 하면 안드로이드 Q의 모든 개인정보 보호 및 보안 기능과
Q를 타게팅하는 앱을 위한 다른 동작 변경 사항
을 앱에서 테스트할 수 있습니다.
새 기능 및 API 둘러보기
준비되셨으면 안드로이드 Q로 전환하고 앱에서 사용할 수 있는
새로운 기능과 API
에 대해 알아보세요. 처음에는
API 변경 보고서
, 안드로이드 Q 베타
API 참고 사항
, 개발자 가이드를 참조하세요. 또한
안드로이드 Q 베타 개발자 사이트
에서는
출시 노트
와 문제 보고를 위한
지원 리소스
를 확인할 수 있습니다.
안드로이드 Q로 빌드하려면 안드로이드 Q 베타 SDK와 도구를 안드로이드 Studio 3.3 이상에 다운로드하고
이 지침
에 따라 환경을 구성하세요. 안드로이드 Q 관련 변경 사항에 대한 최신 수정 사항을 적용하고 싶다면
안드로이드 Studio 3.5
이상을 사용하시는 것이 좋습니다.
안드로이드 Q 베타를 받는 방법
방법은 간단합니다.
여기에 등록
하면 안드로이드 Q 베타를 무선으로 Pixel 기기에 업데이트할 수 있습니다(올해부터는 세 가지 세대의 Pixel -- Pixel 3, Pixel 2, Pixel)을 모두 지원합니다. 이 기기에서 다운로드할 수 있는 시스템 이미지가
제공됩니다
. Pixel 기기가 없을 경우 안드로이드 에뮬레이터를 사용할 수 있습니다. 안드로이드 Studio의 SDK Manager를 통해 최신 에뮬레이터 시스템 이미지를 다운로드하면 됩니다.
언제나 그렇듯이 여러분의 의견은 중요합니다.
어떻게 생각하시는지 알려주세요.
빨리 알려주실수록 더 많은 피드백을 반영할 수 있습니다. 문제가 발견되면
여기로 신고해주세요
.
플랫폼 문제
,
앱 호환성 문제
및
타사 SDK 문제
를 제출하기 위한 별도의 핫 리스트가 있습니다.
Google I/O를 위한 Google 어시스턴트 액션 제작기 (2)
2019년 3월 28일 목요일
Google I/O를 위한 Google 어시스턴트 액션 제작기 (2)
요약 정리
Dialogflow
여기
서 Dialogflow 에이전트를 살펴보세요 (디렉토리를 압축해 Dialogflow에서 임포트 할 수 있습니다).
찾아보기 흐름과 같이 하위 메뉴에 대한 후속 인텐트(Followup Intent)와 컨텍스트를 사용하세요. 자세한 내용은
여기
를 참조하세요.
이 작업을 수행할 때 컨텍스트가 뒤섞여 예기치 않은 동작이 발생하지 않도록 주의하세요. 안전을 보장하려면 하위 메뉴로 들어갈 때 관계없는 컨텍스트는 비활성화하세요.
Dialogflow 에이전트의 압축을 해제한 후 버전 관리 시스템에 푸시합니다. 이를 통해 코드 검토와 책임 문제를 개선할 수 있습니다.
웹훅(Webhook)
프롬프트용으로 재사용 가능한 데이터 구조를 만들고 인텐트 기반으로 이를 구조화 합니다 (예:
예제 디렉토리
, 인텐트를
라우팅
한 방식).
Cloud Functions를 사용할 때는
전역 범위 캐싱
에 대해 충분히 파악해두세요. 이 기능을 원할 때는 더없이 유용하지만 그렇지 않으면 고통의 원인이 될 수도 있기 때문입니다.
액션은 다른 소프트웨어와 유사합니다. 꿈은 크게 가지시더라도 작게 시작하고 계속 반복하세요.
이 게시물의
1부
에서는 Google I/O ’18 액션의 설계 과정을 다루었습니다. 1부에는 사용 사례에 대한 브레인스토밍 그리고 샘플 대화 및 상위 레벨 흐름을 만들어내는 페르소나에 대한 내용이 포함되었습니다.
남
은 문제는 Dialogflow에서 이를 구현하는 방법입니다.
Dialogflow 에이전트 구현
과제는 전체 대화 설계(즉, 서로 주고받을 가능성이 있는 모든 대화와 이런 대화 사이의 전환)를 Dialogflow 에이전트로 구현하는 문제였습니다. 이 시점에는 대화가 가장 일반적이고 공통된 경로에서 벗어날 수 있는
수없이 많은 방식
을 포괄할 뿐 아니라
오류
그리고 발생 가능성이 거의 없거나 흔치 않은 다른 상황을 처리하는 문제까지 포함하는 자세한 설계 사양이 있었습니다. 이를 위해 간단한 흐름도 이상의 것이 필요했습니다. 흐름도에서 화살표가 모든 경로를 반영할 필요는 없습니다. 흐름도는 특정 대화 인스턴스에서 자주 발생하는 경로를 나타냅니다. 해당 대화에서 말할 차례는 특정 순서에 따라 진행되겠지만 사용자마다 대화할 때 따라가는 경로가 제각기 다를 수 있고, 이는 흐름도에는 표시되지 않습니다. 게다가 컨텍스트가 여러 개의 대화 경로를 생성하는 방식이 흐름도에 항상 명확히 드러나는 것은 아닙니다.
이 사양을 Dialogflow에 포팅할 때는 Dialogflow '
인텐트
'가 실제로는 무엇인지 잘 생각해보는 것이 중요합니다. 인텐트는 사용자가 트리거한 ‘특정 상태’입니다. 사용자의 입력이
훈련 문구와 매치
되었고 에이전트에서 응답을 반환해야합니다. 각각의 인텐트는 한 번의 대화 차례를 나타냅니다. Dialogflow 에이전트에 있는 인텐트의 모음이 유한 상태 기계(Finite State Machine)를 형성하는데, 여기서 몇몇 상태의 모음이 결합하여 완전한 대화를 형성합니다. 특정 인텐트에서 이어질 수 있는 가능한 후속 인텐트는 이전 인텐트에서 활성화된 컨텍스트가
입력 컨텍스트
로 지정되어 있거나, 아니면 아예 입력 컨텍스트가 없는 인텐트입니다. 가능한 상태 전환 방식 중에서, Dialogflow는 사용자의 입력이특정 임계값 이상으로 훈련 문구와 매치되는 전환을 고릅니다.
인텐트 식별
그렇다면, 이 모든게 어떤 의미였을까요? 먼저, 전체 대화 흐름을 상위 레벨의 인텐트 또는 중첩된(즉, 후속) 인텐트로 분류하는 걸 의미했습니다. 상위 레벨 인텐트는 대화의 어느 시점에서든 매치될 수 있습니다. 예를 들어 사용자는 대화 중 아무 시점에서나 특정 세션 장소로 가능 방법을 물어볼 수 있습니다. 세션 장소까지 가는 방향을 제시하기 위해 추가로 필요한 입력 컨텍스트가 없습니다. 대부분의 인텐트가 상위 레벨의 인텐트일 수 있고, 사용자는 좀 더 유연한 방법으로 에이전트와 대화할 수 있습니다.
큰 체계 내에서 다양한 하위 대화에 대해
후속 인텐트
가 필요했습니다. 더 자세히 들어보고 싶은 세션 주제를 찾는 사용 사례를 예로 들어보겠습니다. 이 상호 작용은 사용자가 다음과 같은 내용을 말하기를 기다리는 찾아보기-주제(browse-topics) 인텐트로 시작됩니다.
“세션을 찾아줘”
“주제”
“올해 I/O에선 어떤 강좌가 열리지?”
이런 문구가 나올 경우 우리는 사용자가 결국은 같은 기본적인 목표(인텐트)를 표현하는 것으로 간주합니다. 즉, 사용자는 이벤트에서 열리는 세션의 범주를 알고 싶어합니다. 하지만 사용자에게 이 목록을 제공하면 오히려 더 복잡해질 뿐입니다. 스피커 기기에서는 사용자가 질려버리지 않도록 하기 위해 주제 목록을 몇 부분으로 나누어서 제시합니다. 이 때문에, 우리는 사용자가 다음 옵션 집합을 원한다는 의사를 밝히도록 하기 위한 인텐트가 필요했습니다. 사용자는 또한 설계상 필요에 따라 주어지는 옵션 집합을 반복해달라고 요청할 방법이 필요합니다. 이런 상황에서는 찾아보기-주제 인텐트에 대해 적어도 두 개 이상의 후속 인텐트가 필요합니다(다음 옵션 집합을 요청하기 위한 인텐트와 현재 옵션 집합을 반복하기 위한 인텐트).
찾아보기 흐름 만들기
액션에 여러 개의 찾아보기 흐름이 있는 경우(예: 주제 찾아보기, 한 주제 내에서 세션 찾아보기 등), 한 가지 해결책은 이러한 흐름이 공유할 상위 레벨의 '다음 옵션' 인텐트를 만드는 것이었을 겁니다. 우리는 다음과 같은 몇 가지 이유로 이에 반하는 결정을 내렸습니다. 첫째, 이러한 흐름을 여러 개의 후속 인텐트로 나누면 더욱 개념적으로 구분됩니다. 둘째, '다음 옵션' 인텐트 하나를 처리하려면 찾아보기 흐름 내에서 올바른 '다음' 옵션 집합을 가져오기 위해 Dialogflow에서 특수한 컨텍스트의 사용과 추가적인 로직이 필요했을 것입니다. 그 대신, 우리는 각각의 찾아보기 흐름에 필요한 후속 인텐트를 복제했고, 그 결과 다음과 같은 인텐트 집합을 생성했습니다.
컨텍스트 충돌 처리
후속 인텐트(Followup Intent)는 어떻게 작동할까요? 후속 인텐트는
컨텍스트
를 통해 인텐트 사이의 방향 관계를 정의합니다. 후속 인텐트는 Dialogflow가 해당 인텐트와 매치하기 위해 활성화해야 하는 컨텍스트(입력 컨텍스트)를 정의합니다. 상위 레벨 인텐트는 매치되었을 때 이 동일한 컨텍스트(출력 컨텍스트)를 활성화합니다. 우리가 다룬 사례에서는 찾아보기-주제-다음(browse-topics-next) 인텐트와 찾아보기-주제-반복(browse-topics-repeat) 인텐트가 매치되도록 활성 상태가 되려면 찾아보기-주제-후속 컨텍스트(browse-topics-followup context)가 필요합니다. 찾아보기-주제 인텐트는 사용자가 세션에서 다루는 주제를 찾아보고 싶다고 할 때 이 컨텍스트를 활성화합니다.
이 때 주의깊게 살펴 볼 부분이 있습니다. 다른 찾아보기 컨텍스트를 삭제한 부분입니다(컨텍스트의 수명을 0으로 설정). 이는 각각의 상위 레벨 찾아보기 인텐트에 사용되는 패턴입니다(찾아보기-세션 및 표시-예약). 이건 왜 필요한 걸까요? 이런 것이 없는 상태에서 사용자가 다음과 같은 대화에 참여한다고 상상해 봅시다(의역된 대화).
다음으로 무슨 일이 일어날까요? 다른 찾아보기 흐름의 컨텍스트를 지우는 각각의 상위 레벨 인텐트가 없다면 사용자의 마지막 쿼리가 찾아보기-세션-다음 인텐트와 매치되리란 보장이 없습니다. 대신에, 사용자의 마지막 쿼리가 찾아보기-주제-다음 인텐트와 매치되어 사용자가 이미 주제를 선택한 후에도 사용자에게 다음 주제 집합을 제시하는 일이 벌어질 수 있습니다.
이는 찾아보기-주제-후속 컨텍스트와 찾아보기-세션-후속 컨텍스트가 둘 다 활성 상태이기 때문입니다. 각 상위 레벨 찾아보기 인텐트에서 다른 찾아보기 흐름의 후속 컨텍스트를 지우는 방법으로 이를 방지합니다.
에이전트를 개발하면서 상위 레벨 인텐트를 확장하는 작업부터 시작했습니다. 계속 추적할 컨텍스트가 없으므로 가장 쉽게 만들고 테스트할 수 있는 방법입니다.
에이전트 버전 관리 및 협업 환경 구축
처음부터 이 에이전트를 개발하려면 방대한 규모의 협업이 필요할 것이라고 예상할 수 있었습니다. 그래서 백엔드 로직 외에도 에이전트도 버전 관리 대상으로 포함하기로 판단했습니다. 더욱이, 에이전트는 압축 해제된 에이전트 디렉토리로 Git 저장소에 상주시키는 것으로 결정했습니다. 그 덕분에 코드 검토를 통해 새로 추가되는 인텐트나 컨텍스트에서 문제를 포착할 수 있었습니다. 이는 에이전트 내부에서 이루어지는 작업에 대한 지식을 공유하고 문제를 미연에 방지하는 데 중요한 단계였습니다.
웹훅 구현
물론, 웹훅으로 이 전체 에이전트를 구동했습니다. 다른 모든
샘플
에서 그렇게 하듯이,
Firebase용 Cloud 함수
를 사용하기로 했습니다. 이 기능을 사용하면 구현하려는 서비스를 위해 매우 비용 효율적이고 간단한 웹훅을 구현할 수 있습니다. 수요가 극단적으로 몰리는 시간에 서비스를 확장하거나 트래픽이 잠잠한 시간에 유휴 시간에 대한 요금을 지불해야 할 걱정을 할 필요가 없습니다. 또한
Firestore
,
Auth
등 다른 Firebase 서비스와 최고 수준의 통합도 가능합니다.
대화 구성
로직에서 먼저 해결해야 할 문제 중 하나는 현재 시간을 식별할 방법을 찾는 것이었습니다. 현재 날짜에 따라(이벤트 이전, 도중 또는 이후) 사용자에게 약간 다른 대화 흐름이 제시되었습니다. 이를 해결하기 위해 최초
커밋
중 하나에서
Actions on Google Node.js Client Library
미들웨어
기능을 사용하여 매번 대화 차례가 바뀌기 전에 현재 사용자 '문구'를 미리 처리했습니다. 주어진 인텐트를 처리할 때 이 문구의 문자열 값('pre', 'during' 또는 'post')이 전역
conv
객체에 첨부되었습니다. 그래서 그 값을 기준으로 응답 대화를 조건부로 선택할 수 있었습니다.
하지만 주어진 문구에 대해 어떻게 적절한 응답을 선택할까요? 해당 문구를 매핑하기 위해 각 인텐트 내에서 거대한 'if/else'를 사용하는 건 확실히 현명하지 못한 일이었습니다. 게다가, 해당 문구가 어떤 인텐트로 매핑될지 기준이 되는 유일한 조건도 아니었습니다. 다음과 같은 다른 조건이 포함되었습니다.
기존 사용자의 대화인지 신규 사용자의 대화인지 여부
화면을 사용 중인지, 스피커 기기를 사용 중인지 여부
이들 각 조건에 대해 다음을 선택해야 했고 때로는 무작위로 선택해야 했습니다.
응답의
Simple Response
/
Basic Card
/
List
요소
응답 뒤에 표시되는
Suggestion
칩
다음에 이어지는 사용자 음성이 Dialogflow 인텐트와 매치되지 않을 경우 사용할 대체 응답
사용자가 스피커 기기에 침묵으로 반응할 경우에 사용할 무입력 응답
이 모든 변동 사항을 고려하기 위해서는 응답 대화를 제시하기 위한 유연한 전용 데이터 구조가 필요하다는 사실이 분명했습니다. 소스 코드의
prompts
디렉토리에서 액션의 각 주요 사용 사례(최상위 레벨 질문과 각각의 찾아보기 흐름)에 대해 표시되는 이 데이터 구조를 찾을 수 있습니다. 데이터 구조는 다음과 같이 구성되었습니다.
모든 응답은 prompts 디렉토리에 저장했고 공통 파싱 로직은 단일 자바스크립트
파일
에 넣어두고 사용했습니다.
로직과 응답 문자열 데이터를 구분한 후, 다음 3가지 주요 흐름에 걸쳐 로직을 분할했습니다.
대부분 최상위 레벨 Dialogflow 인텐트에 상응하는 '정적' 질문
찾아보기를 위한 메뉴(주제 또는 주제 내 세션)
일정 액세스 및 찾아보기
이들은 각각 prompts 디렉토리에서 별개의 하위 디렉토리가 되었는데, 서로에 대해 고유한 애플리케이션 로직을 포함한 utils.js 파일이 들어 있습니다. 루트 app.js 파일의 드라이버 로직은 인텐트 처리를 이러한 utils.js 파일 중 하나로 라우팅합니다.
컨퍼런스 데이터 가져오기: Cloud Function 캐싱에 대한 강좌
찾아보기 흐름 중 하나를 처리하기 위해, 컨퍼런스 데이터를 가져오기 위한 전용 모듈이 필요했습니다. 이벤트의 컨퍼런스 데이터는 클라우드에 호스팅된 JSON 파일에 저장됩니다. 그럼, 이를 가장 수월하게 처리하는 방법은 무엇일까요? 한 가지 옵션은 절전 모드 해제 시 JSON 데이터를 Cloud Function으로 가져와서 전역 범위 변수에 저장하고 미리 처리한 다음,
이후에 호출
할 때 해당 데이터에 액세스하는 것이었습니다. 여기서 주요 문제는 JSON 파일의 콘텐츠가 꽤 많이 변경되고(개발 중 세션 추가, 이벤트 중 라이브스트림 링크 추가 등), Cloud Function이 절전모드 해제 후 상당한 시간 동안 해제 상태로 유지될 수 있다는 점입니다. 그래서 실시간 솔루션이 필요했습니다.
이 문제를 해결하기 위해 취한 첫 번째 접근 방법은 JSON 데이터를 가져와서 미리 처리하고 반환하는 전역 비동기 함수(Promise)를 만든 다음, 인텐트 처리 로직에서 이 함수를 호출하는 것이었습니다. 즉, 이 함수를 재사용 가능한 함수로 선언하여 모든 대화에서 새로운 데이터를 끌어올 수 있도록 하자는 아이디어였습니다. 여기서 흥미로운 문제는 전역적으로 선언한 함수가 절전 모드 해제 시 실행되었고, 결정된 값이 다음 호출을 위해 Promise로서 캐시된다는 점이었습니다. 이게 왜 문제냐고요? 이 문제로 인해 테스트 중에 새 데이터가 표시되지 않는 이유에 관해 많은 혼동이 있었기 때문입니다.
그래서 생각해낸 해결책은 대화의 각 차례에 대해
새로 인스턴스화
되는,
ConferenceData
라는 클래스를 만드는 방법이었습니다. 이 클래스는 처음 필요할 때 해당 데이터를 가져와서 미리 처리하고(정리, 중복 제거 등 포함), 해당 함수 실행의 나머지 부분을 위해 이를 캐시합니다. 이런 방법으로 항상 새로운 데이터를 보장했고, 단일 함수 실행으로 여러 차례 데이터에 액세스하는 경우에 사용자에 대한 응답 시간을 훨씬 더 단축할 수 있었습니다.
여기서 예리한 관찰자라면 아마 뭔가 잘못된 점을 알아차릴 수도 있을 것입니다. 이 해결책이 의미하는 바는, 어쩌면 대화 차례가 바뀔 때마다 컨퍼런스 데이터를 가져와서 미리 처리하게 된다는 사실이었습니다. 이러한 작업의 상대적 비용을 생각해 볼 때 이상적인 해결책은 아닙니다. 한 가지 쉽게 떠올릴 수 있는 수정 방법은 대화를 시작할 때마다 JSON 데이터를
conv.data
에 저장하는 것이겠지만, 이 문자열 데이터의 크기를 고려할 때 합당한 방법은 아니었습니다.
그래서 숙고 끝에 최종적인 해결책으로 내놨지만 시간 제약 조건 때문에 포기해야 했던 방법은 컨퍼런스 데이터를 주기적으로 가져와서 미리 처리하고 캐시하는 백엔드 시스템을 빌드하는 것이었습니다. 이 방법을 쓰면 애플리케이션 로직을 파싱 로직과 분리함으로써 실시간에 가까운 데이터 정확도를 제공하고 지연 시간을 대폭 줄일 수 있었을 것입니다. 필자는 향후 프로젝트에서 이 문제의 우선순위를 훨씬 더 높이 설정할 생각입니다. 사용자 환경에 직접적인 영향을 주는 문제이기 때문이죠. 우리가 다루는 사례에서는 실제로 효과를 발휘한 방법이 있었습니다.
범위 제한
자, 이제 다른 무슨 문제가 남았을까요? 어떤 소프트웨어 프로젝트에서나 그러하듯이, 우리는 온갖 종류의 제한 사항에 맞닥뜨렸고 이로 인해 범위가 제한되었습니다. 예를 들어 시간 문제로 범위를 줄인 한 가지 기능은 사용자가 특정 옵션 집합이 흥미를 돋우는지 말할 수 있도록 하는 기능이었습니다. 초기 설계 요구 사항에는 다음과 같은 대화가 있었습니다.
사용자: “Android 강좌엔 뭐가 있는지 전부 알려줄래?”Action: “먼저 Android 1번 강좌가 진행된 후에 Android 2번 강좌가 진행됩니다. 둘 중에서 흥미를 끄는 강좌가 있으세요?”사용자: “응”Action: “그래요? 어떤 거죠?”사용자: “...에 대해 들어보자”
그리고 이런 대화도 있었습니다.
사용자: “Cloud 강좌엔 뭐가 있는지 전부 알려줄래?”Action: “Cloud에 관한 강좌는 하나밖에 없군요. 들어보실래요?”사용자: “응”Action: “좋아요, 그건...”
두 가지 이상의 옵션을 제시하는 경우 사용자는 주제를 선택하거나 위와 같은 옵션에 만족하는지 여부를 나타낼 수 있습니다. 한 가지 옵션만 제시하는 경우 사용자는 그 옵션에 대해 듣고 싶은지 간단히 확인해 줄 수 있습니다. 하지만 우린 결국 이 흐름을 지원하지 않기로 했습니다. 왜냐고요? 사용자가 "응"과 같이 긍정의 답을 하면 충돌이 생기기 때문입니다. 사용자는 주어진 단일 세션에 대해 듣고 싶을 때나 두 가지 옵션 중에서 고를지 물을 때 모두 "응"이라 답할 수 있을 겁니다. 이 때문에 "응", "그래" 등과 같은 문구로 훈련한 단일 Dialogflow 인텐트를 만들고 마지막으로 제시되는 항목 집합의 크기를 기준으로 어떻게 응답할지 결정하는 애플리케이션 로직을 빌드해야 했을 것입니다.
이런 종류의 기능은 엔지니어링 시간을 늘리고 버그가 발생할 가능성도 있으므로, 더 완전한 액션을 만들기 위해 제거해야 했습니다. 따라서 특히 엔지니어링 시간과 잠재적 UX 결과의 균형을 맞추는 데 있어 우선순위를 정하고 추정을 할 필요가 있었습니다.
QA 및 출시
초기 개발 기간이 지난 후, 우리는 액션에 대한 기본적인 QA 테스트를 실시하기 시작했습니다. 여기에는 포괄적인 대화 집합을 실행해나가면서 사용자 경험이 타당한지 확인하는 작업이 수반되었습니다. 사용자 경험이 타당한 수준일 때 예/아니요 질문을 묻고 있는 것인가? 음성의 SSML 제공이 적당한가? 말하는 속도가 너무 빠르거나 느리지는 않은가? 이 시점에서 이루어진 변경 사항은 대부분 응답 내용을 적절히 조정하는 내용이었습니다.
또한 이 시간을
암시적 호출 인텐트
를 추가하는 데도 활용했는데, 이를 통해 이벤트에 대해 더 자세히 알아보려는 Google 어시스턴트 사용자를 위해 인텐트의 검색 능력을 강화하기 위한 조치였습니다.
버그 발생 상황
이 시기는 개발 과정에서는 발견하지 못했던 버그를 다수 포착한 중요한 때이기도 했습니다. 이때 잡아낸 버그 중 하나는 응답 데이터 구조 형식을 따르지 못하는 문제였는데, 이로 인해 파싱 로직이 장애를 일으켰습니다. 이 버그가 사용자에게는 어떤 문제를 일으켰을까요? 첫 대화 차례 중 하나에서 액션이 사용자에게 인사를 건넨 후에 사용자가 Dialogflow 에이전트가 인식하지 못하는 대답을 한 경우 정적 대체 메시지를 반복해서 받는 문제였습니다. 원래 의도했던 동작은 설계 지침에 따라 사용자의 말(입력)을 3차례 인식하지 못하면 대화를 종료하도록 하는 것이었습니다. 그렇다면 이 문제가 왜 발생한 것일까요? 일부 응답에서
RichResponse 메시지를 배열로 둘러싸야 한다는 점
을 깜빡 잊었기 때문입니다. 이는 데이터 구조와 그에 상응하는 파싱 로직의 상대적 불안정성을 잘 보여주는 사례였습니다.
불안정한 프로세스를 통해 발생하는 다른 중대한 버그도 있었고 약간 바보스럽게 느껴지게 만드는 버그도 있었습니다. Git 저장소에 압축하지 않은 Dialogflow 에이전트를 보관한 것은 코드 검토를 위한 훌륭한 아이디어였지만, 그 때문에 배포에 몇 가지 문제가 있었습니다. 배포 프로세스는 다음과 같았습니다.
중앙 관리되는 Git 저장소에서 로컬 코드베이스로 최신 코드와 Dialogflow 에이전트를 가져오기
Cloud Functions 코드 배포
Dialogflow 에이전트 디렉토리 압축
에이전트 .zip 파일을 프로덕션 Dialogflow 콘솔로 가져오기
어디서 문제가 생겼을까요? Dialogflow 에이전트의 로컬 개발 복사본에 중앙에서 관리되는 버전(개발 초기에 도입되었지만 이후에 삭제됨)보다 많은 인텐트가 있는 경우 이처럼 불필요한 인텐트를 추적하지 않아서 Git 가져오기 단계에서 이런 인텐트를 정리하지 못했기 때문입니다. 즉, Dialogflow에 배포하면서 때로는 관계없는 인텐트가 포함되었다는 뜻입니다. 우리는 프로덕션 에이전트에 너무 많은 인텐트가 나타나는 것을 보고서야 이 문제를 눈치채기 시작했으며, 배포하기 전에 항상 dialogflow-agent 디렉토리를 새로 다운로드하는 과정부터 시작하도록 함으로써 이 문제를 해결했습니다.
마침내, 그 모든 문제와 제한 사항을 극복하고서 만들어낸 액션에 자부심을 느낍니다. 오늘 현재, Action은 300여 개의 평가를 통해
어시스턴트 디렉토리
에서 4.7점의 높은 별점을 받고 있습니다. 이번 블로그 게시물 시리즈가 멋진 액션을 만든다는 목표를 달성하는 데 있어 훌륭한 안내자 역할을 할 수 있기를 바랍니다.
우리가 이 글에서 설명한 모든 내용을 직접 눈으로 확인하고 여러분도 참여해 일조하고 싶으세요? 코드는
여기
서 확인하세요.
Contents
ML/Tensorflow
Android
Flutter
Web/Chrome
Cloud
Google Play
Community
Game
Firebase
검색
Tag
인디게임페스티벌
정책 세미나
창구프로그램
AdMob
AI
Android
Android 12
Android 12L
Android 13
Android 14
Android Assistant
Android Auto
Android Games
Android Jetpack
Android Machine Learning
Android Privacy
Android Studio
Android TV
Android Wear
App Bundle
bootcamp
Business
Chrome
Cloud
Community
compose
Firebase
Flutter
Foldables
Game
gdg
GDSC
google
Google Developer Student Clubs
Google Play
Google Play Games
Interview
Jetpack
Jetpack Compose
kotlin
Large Screens
Library
ma
Material Design
Material You
ML/Tensorflow
mobile games
Now in Android
PC
Play Console
Policy
priva
wa
wear
Wearables
Web
Web/Chrome
Weeklyupdates
WorkManager
Archive
2025
1월
2024
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2023
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2022
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2021
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2020
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2019
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2018
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2017
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2016
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2015
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2014
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2013
12월
11월
10월
9월
8월
7월
6월
5월
4월
3월
2월
1월
2012
12월
11월
10월
9월
8월
7월
6월
5월
3월
2월
1월
2011
12월
11월
Feed