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

백그라운드에서 웹 앱의 데이터를 동기화하여 앱과 비슷한 환경을 제공합니다.

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

  • 기차나 지하철이 불안정하거나 연결되지 않는 경우
  • 동영상을 너무 많이 시청한 후 이동통신사에서 제한을 받음
  • 대역폭이 수요를 따라잡기 어려운 나라에서 살기

이미 웹에서 작업을 실행할 때 불편함을 느끼셨을 것이고 플랫폼별 앱이 이러한 시나리오에서 왜 더 좋은지 궁금하셨을 것입니다. 플랫폼별 앱은 뉴스 기사나 날씨 정보와 같은 최신 콘텐츠를 미리 가져올 수 있습니다. 지하철에 네트워크가 없더라도 뉴스를 읽을 수는 있습니다.

주기적 백그라운드 동기화를 사용하면 웹 애플리케이션이 백그라운드에서 데이터를 주기적으로 동기화하여 웹 앱을 플랫폼별 앱의 동작에 더 가깝게 만들 수 있습니다.

직접 해 보기

라이브 데모 앱으로 주기적인 백그라운드 동기화를 사용해 볼 수 있습니다. 사용하기 전에 다음을 확인하세요.

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

개념 및 사용법

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

주기적인 백그라운드 동기화가 없으면 웹 앱은 대체 메서드를 사용하여 데이터를 다운로드해야 합니다. 일반적인 예는 푸시 알림을 사용하여 서비스 워커의 절전 모드를 해제하는 것입니다. '새 데이터 있음'과 같은 메시지가 표시되면서 사용자를 중단시킵니다. 데이터를 업데이트하는 것은 본질적으로 부작용입니다. 중요한 속보와 같이 정말로 중요한 업데이트에는 푸시 알림을 사용할 수 있습니다.

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

적절한 사용자 참여 유도

주기적으로 백그라운드 동기화를 실행하면 사용자 리소스가 낭비될 수 있습니다. 출시 전에 Chrome은 제대로 작동하는지 확인하기 위해 체험 기간을 진행했습니다. 이 섹션에서는 이 기능을 최대한 유용하게 만들기 위해 Chrome에서 내린 디자인 관련 결정 몇 가지를 설명합니다.

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

또한 Chrome은 사용되지 않거나 거의 사용되지 않는 웹 앱이 배터리 또는 데이터를 불필요하게 소비하는 것을 원하지 않기 때문에 개발자가 사용자에게 가치를 제공하여 수익을 얻도록 하기 위해 정기적인 백그라운드 동기화를 설계했습니다. 구체적으로 Chrome은 사이트 참여 점수(about://site-engagement/)를 사용하여 특정 웹 앱에서 주기적인 백그라운드 동기화가 발생할 수 있는지 여부와 빈도를 결정합니다. 즉, 참여 점수가 0보다 크지 않으면 periodicsync 이벤트가 전혀 실행되지 않으며 값은 periodicsync 이벤트가 실행되는 빈도에 영향을 미칩니다. 이렇게 하면 현재 활발하게 사용 중인 앱만 백그라운드에서 동기화될 수 있습니다.

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

브라우저에서 제한 없이 빈번하게 이러한 동작이 허용되면 개인 정보 보호 문제가 발생할 수 있습니다. 다음은 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 섹션을 통해 수행할 수 있습니다. 주기적 동기화 필드를 사용하면 사용할 이벤트의 태그를 제공하고 원하는 횟수만큼 트리거할 수 있습니다.

Application 패널의 'Service Workers' 섹션에 'Periodic Sync' 텍스트 필드와 버튼이 표시됨

DevTools 인터페이스 사용

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

주기적 백그라운드 동기화 섹션이 표시된 Application 패널