Periodic Background Sync API를 통한 더욱 풍부한 오프라인 환경

앱과 같은 환경을 위해 백그라운드에서 웹 앱의 데이터 동기화

다음과 같은 상황에 처한 적이 있으신가요?

  • 연결 상태가 불안정하거나 연결되지 않은 기차나 지하철을 타는 경우
  • 동영상을 너무 많이 시청하여 이동통신사에서 제한함
  • 대역폭이 수요를 따라가지 못하는 국가에 거주

웹에서 특정 작업을 수행하는 것에 대한 불만을 느끼고 이러한 시나리오에서 플랫폼별 앱이 왜 이렇게 더 나은지 궁금했던 적이 있을 것입니다. 플랫폼별 앱은 뉴스 기사나 날씨 정보와 같은 최신 콘텐츠를 미리 가져올 수 있습니다. 지하철에 네트워크가 없어도 뉴스를 읽을 수 있습니다.

주기적 백그라운드 동기화를 사용하면 웹 애플리케이션이 백그라운드에서 데이터를 주기적으로 동기화하여 웹 앱이 플랫폼별 앱의 동작에 더 가까워집니다.

직접 해 보기

실시간 데모 앱을 사용하여 주기적인 백그라운드 동기화를 시도해 볼 수 있습니다. 사용하기 전에 다음 사항을 확인하세요.

  • Chrome 80 이상을 사용 중입니다.
  • 주기적 백그라운드 동기화를 사용 설정하기 전에 웹 앱을 설치합니다.

개념 및 사용

주기적 백그라운드 동기화를 사용하면 프로그레시브 웹 앱 또는 서비스 워커 지원 페이지가 시작될 때 최신 콘텐츠를 표시할 수 있습니다. 앱 또는 페이지가 사용되지 않을 때 백그라운드에서 데이터를 다운로드하여 이를 실행합니다. 이렇게 하면 실행 후 앱이 표시되는 동안 앱의 콘텐츠를 새로고침할 수 없습니다. 더 나아가 새로고침 전에 앱이 콘텐츠 스피너를 표시하지 못하도록 합니다.

주기적인 백그라운드 동기화가 없으면 웹 앱은 다른 방법을 사용하여 데이터를 다운로드해야 합니다. 일반적인 예는 푸시 알림을 사용하여 서비스 작업자를 깨우는 것입니다. '새 데이터 사용 가능'과 같은 메시지로 인해 사용자의 작업이 중단됩니다. 데이터 업데이트는 본질적으로 부작용입니다. 중요한 속보와 같이 정말 중요한 업데이트의 경우 푸시 알림을 계속 사용할 수 있습니다.

주기적 백그라운드 동기화는 백그라운드 동기화와 쉽게 혼동됩니다. 이름은 비슷하지만 사용 사례는 다릅니다. 무엇보다 백그라운드 동기화는 이전 요청이 실패했을 때 서버에 데이터를 재전송하는 데 가장 일반적으로 사용됩니다.

사용자 참여도 높이기

잘못 실행하면 주기적인 백그라운드 동기화로 인해 사용자 리소스가 낭비될 수 있습니다. 출시하기 전에 Chrome에서는 이 기능이 올바른지 확인하기 위해 무료 체험 기간을 거쳤습니다. 이 섹션에서는 이 기능을 최대한 유용하게 만들기 위해 Chrome에서 내린 몇 가지 설계 결정을 설명합니다.

Chrome에서 내린 첫 번째 설계 결정은 웹 앱이 사용자가 기기에 앱을 설치하고 별도의 애플리케이션으로 실행한 후에만 주기적 백그라운드 동기화를 사용할 수 있다는 것입니다. Chrome의 일반 탭 컨텍스트에서는 주기적 백그라운드 동기화를 사용할 수 없습니다.

또한 Chrome은 사용하지 않거나 거의 사용하지 않는 웹 앱이 배터리나 데이터를 무료로 소모하는 것을 원하지 않으므로 개발자가 사용자에게 가치를 제공하여 이를 얻어야 하는 주기적 백그라운드 동기화를 설계했습니다. 구체적으로 Chrome은 사이트 참여 점수(about://site-engagement/)를 사용하여 특정 웹 앱에 주기적인 백그라운드 동기화가 발생할 수 있는지 여부와 그 빈도를 결정합니다. 즉, 참여 점수가 0보다 크지 않고 그 값이 periodicsync 이벤트의 실행 빈도에 영향을 주지 않으면 periodicsync 이벤트가 전혀 실행되지 않습니다. 이렇게 하면 백그라운드에서 동기화되는 앱이 내가 실제로 사용 중인 앱으로 제한됩니다.

주기적 백그라운드 동기화는 기존 API와 몇 가지 유사점이 있으며 널리 사용되는 플랫폼의 방식도 다릅니다. 예를 들어 일회성 백그라운드 동기화와 푸시 알림을 사용하면 사용자가 페이지를 닫은 후에도 웹 앱 로직이 서비스 워커를 통해 조금 더 오래 유지될 수 있습니다. 대부분의 플랫폼에서는 중요한 업데이트, 콘텐츠 미리 가져오기, 데이터 동기화 등에 더 나은 사용자 환경을 제공하기 위해 백그라운드에서 주기적으로 네트워크에 액세스하는 앱을 설치하는 것이 일반적입니다. 마찬가지로 주기적 백그라운드 동기화는 웹 앱 로직의 전체 기간을 연장하여 한 번에 몇 분 정도 일정한 기간 동안만 실행되도록 합니다.

브라우저에서 이러한 일이 제한 없이 자주 발생하도록 허용하면 개인 정보 보호 문제가 발생할 수 있습니다. Chrome에서는 주기적 백그라운드 동기화의 이러한 위험을 다음과 같이 해결했습니다.

  • 백그라운드 동기화 활동은 기기가 이전에 연결된 네트워크에서만 발생합니다. Chrome에서는 신뢰할 수 있는 당사자가 운영하는 네트워크에만 연결하는 것이 좋습니다.
  • 모든 인터넷 통신과 마찬가지로 주기적인 백그라운드 동기화는 클라이언트의 IP 주소, 통신 중인 서버, 서버 이름을 보여줍니다. 이러한 노출을 앱이 포그라운드에 있을 때만 동기화되는 경우와 비슷한 수준으로 줄이기 위해 브라우저는 사용자가 앱을 사용하는 빈도에 맞게 앱의 백그라운드 동기화 빈도를 제한합니다. 사용자가 앱과의 상호작용을 자주 중단하면 주기적 백그라운드 동기화가 트리거되지 않습니다. 이는 플랫폼별 앱의 현상보다 확실히 개선된 것입니다.

언제 사용할 수 있나요?

사용 규칙은 브라우저마다 다릅니다. 위에서 요약하자면 Chrome은 주기적 백그라운드 동기화에 다음 요구사항을 적용합니다.

  • 특정 사용자 참여도 점수입니다.
  • 이전에 사용된 네트워크가 있는지 여부

동기화 시점은 개발자가 제어할 수 없습니다. 동기화 빈도는 앱 사용 빈도에 따라 달라집니다. (플랫폼별 앱은 현재 이 작업을 하지 않습니다.) 또한 기기의 전원 및 연결 상태도 고려합니다.

언제 사용해야 하나요?

서비스 워커가 periodicsync 이벤트를 처리하기 위해 깨어나면 데이터를 요청할 기회가 있지만 그렇게 할 의무는 없습니다. 이벤트를 처리할 때는 네트워크 상태와 사용 가능한 저장용량을 고려하고 응답에 따라 서로 다른 양의 데이터를 다운로드해야 합니다. 다음 리소스를 참고하세요.

권한

서비스 워커가 설치된 후 Permissions API를 사용하여 periodic-background-sync를 쿼리합니다. 창 또는 서비스 워커 컨텍스트에서 이를 실행할 수 있습니다.

const status = await navigator.permissions.query({
  name: 'periodic-background-sync',
});
if (status.state === 'granted') {
  // Periodic background sync can be used.
} else {
  // Periodic background sync cannot be used.
}

주기적 동기화 등록

이미 언급했듯이 주기적인 백그라운드 동기화에는 서비스 워커가 필요합니다. ServiceWorkerRegistration.periodicSync를 사용하여 PeriodicSyncManager를 검색하고 이 인스턴스에서 register()를 호출합니다. 등록하려면 태그와 최소 동기화 간격 (minInterval)이 모두 필요합니다. 태그는 등록된 동기화를 식별하므로 여러 동기화를 등록할 수 있습니다. 아래 예에서 태그 이름은 'content-sync'이고 minInterval은 1일입니다.

const registration = await navigator.serviceWorker.ready;
if ('periodicSync' in registration) {
  try {
    await registration.periodicSync.register('content-sync', {
      // An interval of one day.
      minInterval: 24 * 60 * 60 * 1000,
    });
  } catch (error) {
    // Periodic background sync cannot be used.
  }
}

등록 확인

periodicSync.getTags()를 호출하여 등록 태그 배열을 가져옵니다. 아래 예에서는 태그 이름을 사용하여 캐시 업데이트가 활성 상태인지 확인하여 다시 업데이트되지 않도록 합니다.

const registration = await navigator.serviceWorker.ready;
if ('periodicSync' in registration) {
  const tags = await registration.periodicSync.getTags();
  // Only update content if sync isn't set up.
  if (!tags.includes('content-sync')) {
    updateContentOnPageLoad();
  }
} else {
  // If periodic background sync isn't supported, always update.
  updateContentOnPageLoad();
}

getTags()를 사용하여 웹 앱의 설정 페이지에 활성 등록 목록을 표시하여 사용자가 특정 유형의 업데이트를 사용 설정하거나 사용 중지할 수 있도록 할 수도 있습니다.

주기적 백그라운드 동기화 이벤트에 응답

주기적 백그라운드 동기화 이벤트에 응답하려면 서비스 워커에 periodicsync 이벤트 핸들러를 추가합니다. 전달된 event 객체에는 등록 중에 사용된 값과 일치하는 tag 매개변수가 포함됩니다. 예를 들어 주기적 백그라운드 동기화가 'content-sync'라는 이름으로 등록된 경우 event.tag'content-sync'입니다.

self.addEventListener('periodicsync', (event) => {
  if (event.tag === 'content-sync') {
    // See the "Think before you sync" section for
    // checks you could perform before syncing.
    event.waitUntil(syncContent());
  }
  // Other logic for different tags as needed.
});

동기화 등록 취소

등록된 동기화를 종료하려면 등록 해제하려는 동기화의 이름을 사용하여 periodicSync.unregister()를 호출합니다.

const registration = await navigator.serviceWorker.ready;
if ('periodicSync' in registration) {
  await registration.periodicSync.unregister('content-sync');
}

인터페이스

다음은 Periodic Background Sync API에서 제공하는 인터페이스에 관한 간단한 개요입니다.

  • PeriodicSyncEvent. 브라우저가 선택한 시점에 ServiceWorkerGlobalScope.onperiodicsync 이벤트 핸들러로 전달됩니다.
  • PeriodicSyncManager. 주기적 동기화를 등록 및 등록 취소하고 등록된 동기화에 태그를 제공합니다. ServiceWorkerRegistration.periodicSync` 속성에서 이 클래스의 인스턴스를 검색합니다.
  • ServiceWorkerGlobalScope.onperiodicsync. PeriodicSyncEvent를 수신하는 핸들러를 등록합니다.
  • ServiceWorkerRegistration.periodicSync. PeriodicSyncManager 참조를 반환합니다.

콘텐츠 업데이트

다음 예에서는 주기적인 백그라운드 동기화를 사용하여 뉴스 사이트나 블로그의 최신 기사를 다운로드하고 캐시합니다. 동기화 유형을 나타내는 태그 이름 ('update-articles')을 확인합니다. updateArticles() 호출은 event.waitUntil()로 래핑되어 있으므로 자료가 다운로드되고 저장되기 전에 서비스 워커가 종료되지 않습니다.

async function updateArticles() {
  const articlesCache = await caches.open('articles');
  await articlesCache.add('/api/articles');
}

self.addEventListener('periodicsync', (event) => {
  if (event.tag === 'update-articles') {
    event.waitUntil(updateArticles());
  }
});

기존 웹 앱에 주기적 백그라운드 동기화 추가

기존 PWA에 주기적 백그라운드 동기화를 추가하려면 이러한 변경사항이 필요했습니다. 이 예에는 웹 앱의 주기적 백그라운드 동기화 상태를 설명하는 유용한 로깅 문이 많이 포함되어 있습니다.

디버깅

로컬에서 테스트하는 동안 주기적 백그라운드 동기화를 얻고 처음부터 끝까지 확인하기 어려울 수 있습니다. 활성 등록, 대략적인 동기화 간격, 이전 동기화 이벤트의 로그에 관한 정보는 웹 앱 동작을 디버그하는 동안 중요한 맥락을 제공합니다. 다행히 Chrome DevTools의 실험용 기능을 통해 이러한 정보를 모두 확인할 수 있습니다.

로컬 활동 기록

DevTools의 주기적 백그라운드 동기화 섹션은 주기적 백그라운드 동기화 수명 주기의 주요 이벤트(동기화 등록, 백그라운드 동기화 실행, 등록 취소)를 중심으로 구성됩니다. 이러한 이벤트에 관한 정보를 얻으려면 기록 시작을 클릭하세요.

DevTools의 녹화 버튼
DevTools의 기록 버튼

녹화하는 동안 DevTools에 이벤트에 해당하는 항목이 표시되며 각 항목에 관한 컨텍스트와 메타데이터가 기록됩니다.

기록된 주기적 백그라운드 동기화 데이터의 예
기록된 주기적 백그라운드 동기화 데이터의 예

녹화를 한 번 사용 설정하면 최대 3일 동안 사용 설정된 상태로 유지되므로 DevTools에서 앞으로 몇 시간 후에도 발생할 수 있는 백그라운드 동기화에 관한 로컬 디버깅 정보를 캡처할 수 있습니다.

이벤트 시뮬레이션

백그라운드 활동을 기록하는 것이 유용할 수 있지만, 이벤트가 정상적인 주기로 실행될 때까지 기다리지 않고 periodicsync 핸들러를 즉시 테스트해야 하는 경우가 있습니다.

이 작업은 Chrome DevTools의 Application 패널에 있는 서비스 워커 섹션을 통해 수행할 수 있습니다. 주기적 동기화 필드를 사용하면 이벤트에 사용할 태그를 제공하고 원하는 횟수만큼 트리거할 수 있습니다.

애플리케이션 패널의 'Service Workers' 섹션에 '주기적 동기화' 텍스트 필드와 버튼이 표시됩니다.

DevTools 인터페이스 사용

Chrome 81부터 DevTools Application 패널에 Periodic Background Sync 섹션이 표시됩니다.

주기적 백그라운드 동기화 섹션을 보여주는 애플리케이션 패널