게시일: 2020년 12월 2일
신뢰할 수 있는 웹 활동이 도입된 이후 Chrome팀은 Bubblewrap을 사용하여 더 쉽게 사용할 수 있도록 했습니다. Google Play 결제 통합과 같은 추가 기능을 추가하고 ChromeOS와 같은 더 많은 플랫폼에서 작동하도록 지원했습니다.
Bubblewrap 및 신뢰할 수 있는 웹 활동 기능
Bubblewrap을 사용하면 플랫폼별 도구에 관한 지식이 없어도 신뢰할 수 있는 웹 활동 내에서 PWA를 실행하는 앱을 만들 수 있습니다.
간소화된 설정 흐름
이전에는 Bubblewrap을 사용하려면 Java 개발 키트와 Android SDK를 수동으로 설정해야 했으며, 이 두 가지 모두 오류가 발생하기 쉬웠습니다. 이제 이 도구는 처음 실행될 때 외부 종속 항목을 자동으로 다운로드합니다.
원하는 경우 기존 종속 항목 설치를 계속 사용할 수 있으며, 새로운 doctor 명령어를 사용하면 문제를 찾고 구성에 대한 수정사항을 추천할 수 있습니다. 이제 updateConfig 명령어를 사용하여 명령줄에서 구성을 업데이트할 수 있습니다.
개선된 마법사
init로 프로젝트를 만들 때 Bubblewrap에는 Android 앱을 생성하기 위한 정보가 필요합니다. 이 도구는 웹 앱 매니페스트에서 값을 추출하고 가능한 경우 기본값을 제공합니다.
새 프로젝트를 만들 때 이러한 값을 변경할 수 있지만 이전에는 각 필드의 의미가 명확하지 않았습니다. 초기화 대화상자가 각 입력란에 대한 더 나은 설명과 유효성 검사로 다시 빌드되었습니다.
전체 화면 및 방향 지원 표시
경우에 따라 애플리케이션이 화면을 최대한 많이 사용하도록 할 수 있으며, PWA를 빌드할 때 웹 앱 매니페스트의 display 필드를 fullscreen로 설정하여 이를 구현합니다.
Bubblewrap은 웹 앱 매니페스트에서 전체 화면 옵션을 감지하면 Android 애플리케이션도 전체 화면 또는 Android 용어로 몰입형 모드로 실행되도록 구성합니다.
웹 앱 매니페스트의 orientation 필드는 애플리케이션을 세로 모드, 가로 모드 또는 기기에서 현재 사용 중인 방향으로 시작해야 하는지 정의합니다. 이제 Bubblewrap은 웹 앱 매니페스트 필드를 읽고 Android 앱을 만들 때 이를 기본값으로 사용합니다.
두 구성 모두 bubblewrap init 흐름의 일부로 맞춤설정할 수 있습니다.
AppBundles 출력
App Bundle은 최종 APK 생성 및 서명을 Play에 위임하는 앱 게시 형식입니다. 실제로 이를 통해 사용자가 스토어에서 앱을 다운로드할 때 더 작은 파일을 제공할 수 있습니다.
이제 Bubblewrap은 애플리케이션을 App Bundle로 app-release-bundle.aab라는 파일에 패키징합니다. 2021년부터 Play 스토어에서 이 형식을 요구하므로 Play 스토어에 앱을 게시할 때는 이 형식을 사용하는 것이 좋습니다.
위치정보 위임
사용자는 기기에 설치된 애플리케이션이 기술과 관계없이 일관되게 작동하기를 기대합니다. 신뢰할 수 있는 웹 활동 내에서 사용되는 경우 이제 GeoLocation 권한을 운영체제에 위임할 수 있으며, 사용 설정되면 사용자는 Kotlin 또는 자바로 빌드된 앱과 동일한 대화상자를 보고 동일한 위치에서 권한을 관리하는 컨트롤을 찾을 수 있습니다.
이 기능은 Bubblewrap을 통해 추가할 수 있으며 Android 프로젝트에 추가 종속 항목을 추가하므로 웹 앱이 위치 정보 정보 액세스 권한을 사용하는 경우에만 사용 설정해야 합니다.
최적화된 바이너리
저장용량이 제한된 기기는 세계의 특정 지역에서 흔히 볼 수 있으며 이러한 기기의 소유자는 작은 애플리케이션을 선호하는 경우가 많습니다. 신뢰할 수 있는 웹 활동을 사용하는 애플리케이션은 작은 바이너리를 생성하므로 사용자의 불안감을 일부 해소합니다.
Bubblewrap은 필요한 Android 라이브러리 목록을 줄여 최적화되었으며, 그 결과 생성된 바이너리가 800k 더 작아졌습니다. 실제로 이는 이전 버전에서 생성된 평균 크기의 절반 미만입니다. 더 작은 바이너리를 활용하려면 최신 버전의 Bubblewrap을 사용하여 앱을 업데이트하기만 하면 됩니다.
기존 앱을 업데이트하는 방법
Bubblewrap에서 생성된 애플리케이션은 웹 애플리케이션과 PWA를 여는 경량 Android 래퍼로 구성됩니다. 신뢰할 수 있는 웹 활동 내에서 열린 PWA는 웹 앱과 동일한 업데이트 주기를 따르지만 네이티브 래퍼는 업데이트할 수 있으며 업데이트해야 합니다.
최신 버그 수정 및 기능이 포함된 최신 버전의 래퍼를 사용하도록 앱을 업데이트해야 합니다. 최신 버전의 Bubblewrap이 설치된 상태에서 update 명령어는 최신 버전의 래퍼를 기존 프로젝트에 적용합니다.
npm update -g @bubblewrap/cli
bubblewrap update
bubblewrap build
이러한 애플리케이션을 업데이트해야 하는 또 다른 이유는 웹 매니페스트의 변경사항이 애플리케이션에 적용되도록 하기 위해서입니다. 새 merge 명령어를 사용합니다.
bubblewrap merge
bubblewrap update
bubblewrap build
품질 기준 업데이트
Chrome 86에서는 신뢰할 수 있는 웹 활동 품질 기준에 변경사항이 도입되었으며, 이는 신뢰할 수 있는 웹 활동을 사용하는 PWA의 품질 기준 변경사항에 자세히 설명되어 있습니다.
간단히 요약하자면 애플리케이션이 비정상 종료되지 않도록 다음 시나리오를 처리해야 합니다.
- 애플리케이션 실행 시 디지털 애셋 링크를 확인하지 못함
- 오프라인 네트워크 리소스 요청에 대해 HTTP 200을 반환하지 못함
- 애플리케이션에서 HTTP 404 또는 5xx 오류가 반환됩니다.
애플리케이션이 디지털 애셋 링크 유효성 검사를 통과하도록 하는 것 외에도 나머지 시나리오는 서비스 워커에서 처리할 수 있습니다.
self.addEventListener('fetch', event => {
event.respondWith((async () => {
try {
return await fetchAndHandleError(event.request);
} catch {
// Failed to load from the network. User is offline or the response
// has a status code that triggers the Quality Criteria.
// Try loading from cache.
const cachedResponse = await caches.match(event.request);
if (cachedResponse) {
return cachedResponse;
}
// Response was not found on the cache. Send the error / offline
// page. OFFLINE_PAGE should be pre-cached when the service worker
// is activated.
return await caches.match(OFFLINE_PAGE);
}
})());
});
async function fetchAndHandleError(request) {
const cache = await caches.open(RUNTIME_CACHE);
const response = await fetch(request);
// Throw an error if the response returns one of the status
// that trigger the Quality Criteria.
if (response.status === 404 ||
response.status >= 500 && response.status < 600) {
throw new Error(`Server responded with status: ${response.status}`);
}
// Cache the response if the request is successful.
cache.put(request, response.clone());
return response;
}
Workbox는 서비스 워커를 사용할 때 권장사항을 적용하고 상용구를 삭제합니다. 또는 Workbox 플러그인을 사용하여 이러한 시나리오를 처리하는 것이 좋습니다.
export class FallbackOnErrorPlugin {
constructor(offlineFallbackUrl, notFoundFallbackUrl, serverErrorFallbackUrl) {
this.notFoundFallbackUrl = notFoundFallbackUrl;
this.offlineFallbackUrl = offlineFallbackUrl;
this.serverErrorFallbackUrl = serverErrorFallbackUrl;
}
checkTrustedWebActivityCrash(response) {
if (response.status === 404 || response.status >= 500 && response.status <= 600) {
const type = response.status === 404 ? 'E_NOT_FOUND' : 'E_SERVER_ERROR';
const error = new Error(`Invalid response status (${response.status})`);
error.type = type;
throw error;
}
}
// This is called whenever there's a network response,
// but we want special behavior for 404 and 5**.
fetchDidSucceed({response}) {
// Cause a crash if this is a Trusted Web Activity crash.
this.checkTrustedWebActivityCrash(response);
// If it's a good response, it can be used as-is.
return response;
}
// This callback is new in Workbox v6, and is triggered whenever
// an error (including a NetworkError) is thrown when a handler runs.
handlerDidError(details) {
let fallbackURL;
switch (details.error.details.error.type) {
case 'E_NOT_FOUND': fallbackURL = this.notFoundFallbackUrl; break;
case 'E_SERVER_ERROR': fallbackURL = this.serverErrorFallbackUrl; break;
default: fallbackURL = this.offlineFallbackUrl;
}
return caches.match(fallbackURL, {
// Use ignoreSearch as a shortcut to work with precached URLs
// that have _WB_REVISION parameters.
ignoreSearch: true,
});
}
}