백그라운드 동기화 소개

제이크 아치볼드
제이크 아치볼드

백그라운드 동기화는 사용자가 안정적으로 연결할 때까지 작업을 연기할 수 있는 새로운 웹 API입니다. 이렇게 하면 사용자가 전송하고자 하는 것이 실제로 전송되도록 할 수 있습니다.

문제

인터넷은 시간을 낭비하기에 좋은 곳입니다. 인터넷에서 시간을 낭비하지 않는다면 고양이는 꽃을 싫어하고 카멜레온은 거품을 좋아하거나 우리가 직접 만든 에릭 비델만90년대 후반의 퍼트 퍼트 골프 영웅이라는 사실도 알 수 없습니다.

하지만 때로는 시간을 낭비하고 싶지 않은 경우도 있습니다. 원하는 사용자 환경은 다음과 같습니다.

  1. 휴대전화를 주머니에서 꺼냈습니다.
  2. 사소한 목표를 달성합니다.
  3. 휴대전화를 주머니에 다시 넣습니다.
  4. 수명을 재개합니다.

안타깝게도 이 환경은 연결 상태가 좋지 않아 자주 손상됩니다. 누구나 그런 경험이 있을 것입니다. 흰색 화면이나 스피너를 바라보면 포기하고 인생을 계속해야 한다는 것을 알지만 만약을 위해 10초를 더 주어야 합니다. 10초 후에요? 없습니다.

하지만 왜 지금 포기해야 할까요? 이미 시간을 투자했으니 아무것도 빼먹지 않고 걸어가는 것이 낭비가 되므로 계속 기다려야 합니다. 이 시점에는 포기하고 싶지만 포기하는 순간은 기다리기만 했다면 모든 것이 로드되기 전에 두 번째로 로드된다는 점을 알고 있습니다.

서비스 워커는 사용자가 캐시에서 콘텐츠를 제공하도록 하여 페이지 로드 부분을 해결합니다. 하지만 페이지에서 서버에 무언가를 보내야 하는 경우에는 어떻게 해야 할까요?

현재는 사용자가 메시지에서 '보내기'를 누르면 완료될 때까지 스피너를 쳐다봐야 합니다. 사용자가 다른 페이지로 이동하거나 탭을 닫으려고 하면 onbeforeunload를 사용하여 '아니요, 이 스피너를 좀 더 봐주세요. 죄송합니다." 사용자가 인터넷에 연결되어 있지 않으면 사용자에게 '죄송합니다. 나중에 다시 시도해 주세요'라고 알립니다.

이건 쓰레기입니다. 백그라운드 동기화로 더 편리하게 작업하세요.

해결 방법

다음 동영상은 그림 이모티콘 전용 채팅 데모인 Emojoy를 보여줍니다. 오프라인 우선으로 작동하는 프로그레시브 웹 앱입니다. 앱이 푸시 메시지와 알림을 사용하고 백그라운드 동기화를 사용합니다.

연결이 끊겼을 때 사용자가 메시지를 보내려고 하면 다행히 연결이 되면 메시지가 백그라운드에서 전송됩니다.

2016년 3월부터 Chrome 버전 49 이상에서 백그라운드 동기화를 사용할 수 있습니다. 아래 단계에 따라 해당 작업을 확인할 수 있습니다.

  1. Emojoy를 엽니다.
  2. 오프라인으로 전환합니다 (비행기 모드를 사용하거나 가까운 Faraday 케이지 방문).
  3. 메시지를 입력합니다.
  4. 홈 화면으로 돌아갑니다 (원하는 경우 탭 또는 브라우저 닫기).
  5. 인터넷에 연결하세요.
  6. 메시지가 백그라운드에서 전송됩니다.

이와 같이 백그라운드에서 전송할 수 있으면 체감 성능도 개선됩니다. 앱은 메시지 전송에 크게 신경 쓸 필요가 없으므로 출력에 메시지를 바로 추가할 수 있습니다.

백그라운드 동기화 요청 방법

진정한 확장 가능한 웹 스타일에서 이 기능은 필요한 작업을 자유롭게 수행할 수 있도록 하는 하위 수준의 기능입니다. 사용자가 연결되면 이벤트를 실행하도록 요청합니다. 이는 사용자가 이미 연결되어 있는 경우 즉시 실행됩니다. 그런 다음 해당 이벤트를 수신 대기하고 필요한 작업을 수행합니다.

푸시 메시지와 마찬가지로 서비스 워커를 이벤트 대상으로 사용하므로 페이지가 열려 있지 않아도 서비스 워커가 작동할 수 있습니다. 시작하려면 페이지에서 동기화를 등록합니다.

// Register your service worker:
navigator.serviceWorker.register('/sw.js');

// Then later, request a one-off sync:
navigator.serviceWorker.ready.then(function(swRegistration) {
  return swRegistration.sync.register('myFirstSync');
});
 ```

Then listen for the event in `/sw.js`:

```js
self.addEventListener('sync', function(event) {
  if (event.tag == 'myFirstSync') {
    event.waitUntil(doSomeStuff());
  }
});

이상입니다 위에서 doSomeStuff()는 수행하려는 작업의 성공/실패를 나타내는 프로미스를 반환해야 합니다. 충족되면 동기화가 완료된 것입니다. 동기화에 실패하면 다른 동기화가 다시 시도하도록 예약됩니다. 동기화 재시도 역시 연결을 대기하며 지수 백오프를 적용합니다.

동기화의 태그 이름(위 예에서 'myFirstSync')은 특정 동기화에 대해 고유해야 합니다. 대기 중인 동기화와 동일한 태그를 사용하여 동기화를 등록하면 기존 동기화와 병합됩니다. 즉, 사용자가 메일을 보낼 때마다 '보낼편지함 비우기' 동기화에 등록할 수 있지만, 사용자가 오프라인 상태에서 메일을 5개 보내는 경우 온라인 상태가 되었을 때 메일을 한 번만 동기화하면 됩니다. 5개의 개별 동기화 이벤트를 원하는 경우 고유한 태그를 사용하면 됩니다.

다음은 간단한 데모입니다. 이 데모에서는 동기화 이벤트를 사용하여 알림을 표시합니다.

백그라운드 동기화를 어떤 용도로 사용할 수 있나요?

이상적으로는 해당 페이지를 사용하여 페이지의 수명 이후에 관심 있는 데이터를 전송하는 것이 좋습니다. 채팅 메시지, 이메일, 문서 업데이트, 설정 변경사항, 사진 업로드 등 사용자가 다른 곳으로 이동하거나 탭을 닫아도 서버에 전달하려는 모든 항목. 페이지에서 이러한 객체를 indexDB의 '보낼편지함' 저장소에 저장하면 서비스 워커가 이를 검색하여 전송합니다.

그러나 소량의 데이터를 가져오는 데도 사용할 수 있습니다...

또 다른 데모입니다.

이것은 페이지 로드 강화를 위해 만든 오프라인 위키백과 데모입니다. 그 이후로 몇 가지 백그라운드 동기화 매직을 추가했습니다.

직접 해 보세요. Chrome 49 이상을 사용 중인지 확인합니다.

  1. Chrome과 같은 도움말로 이동합니다.
  2. 오프라인으로 전환합니다 (비행기 모드를 사용하거나 저처럼 심각한 모바일 제공업체에 가입).
  3. 다른 자료로 연결되는 링크를 클릭합니다.
  4. 페이지를 로드하지 못했다는 메시지가 표시됩니다 (페이지를 로드하는 데 시간이 걸리는 경우에도 표시됨).
  5. 알림에 동의합니다.
  6. 브라우저를 닫습니다.
  7. 온라인 전환
  8. 기사가 다운로드 및 캐시되어 볼 수 있게 되면 알림이 전송됩니다.

이 패턴을 사용하면 사용자는 휴대전화를 주머니에 넣고 생활할 수 있습니다. 휴대전화가 원하는 대로 가져왔을 때 알림을 보내준다는 것을 알 수 있습니다.

권한

보여드린 데모에서는 권한이 필요한 웹 알림을 사용하지만 백그라운드 동기화 자체는 사용하지 않습니다.

동기화 이벤트는 사용자가 사이트에 페이지를 열어두는 동안 완료되는 경우가 많으므로 사용자에게 권한을 요청하는 것은 좋지 않습니다. 대신 악용을 방지하기 위해 동기화가 등록되고 트리거될 수 있는 시점을 제한하고 있습니다. 예를 들면 다음과 같습니다.

  • 사용자가 사이트에 대한 창을 열어 둔 경우에만 동기화 이벤트에 등록할 수 있습니다.
  • 이벤트 실행 시간이 제한되어 있으므로 x초마다 서버를 핑하거나 비트코인을 채굴하는 등의 용도로 사용할 수 없습니다.

물론 이러한 제한사항은 실제 사용에 따라 완화되거나 강화될 수 있습니다.

점진적 개선

Safari와 Edge에서는 아직 서비스 워커가 아직 지원되지 않기 때문에, 모든 브라우저가 백그라운드 동기화를 지원하는 데는 시간이 다소 걸릴 것입니다. 하지만 이 과정에서 점진적인 개선이 도움이 됩니다.

if ('serviceWorker' in navigator && 'SyncManager' in window) {
  navigator.serviceWorker.ready.then(function(reg) {
    return reg.sync.register('tag-name');
  }).catch(function() {
    // system was unable to register for a sync,
    // this could be an OS-level restriction
    postDataFromThePage();
  });
} else {
  // serviceworker/sync not supported
  postDataFromThePage();
}

서비스 워커 또는 백그라운드 동기화를 사용할 수 없는 경우에는 지금 하는 것처럼 페이지의 콘텐츠를 게시하면 됩니다.

백그라운드 동기화는 데이터 전송 중에 탐색이나 탭 닫힘으로부터 보호되므로 연결 상태가 양호해 보이는 경우에도 사용할 필요가 있습니다.

앞으로

Google은 2016년 상반기에 백그라운드 동기화를 Chrome의 안정화 버전으로 출시할 예정이며, 이와 동시에 '주기적 백그라운드 동기화'라는 변형을 제공하고자 합니다. 주기적인 백그라운드 동기화를 사용하면 시간 간격, 배터리 상태 및 네트워크 상태에 따라 제한된 이벤트를 요청할 수 있습니다. 물론 이를 위해서는 사용자 권한이 필요하며, 이러한 이벤트가 실행되는 시점과 빈도는 브라우저에 따라 다릅니다. 즉, 뉴스 사이트에서 매시간 동기화를 요청할 수 있지만 브라우저는 사용자가 해당 사이트를 07:00에만 읽었다는 사실을 인식하므로 매일 06:50에 동기화가 실행됩니다. 이 아이디어는 일회성 동기화보다 조금 멀지만 곧 적용될 예정입니다.

우리는 웹의 멋진 기능을 계속 유지하면서도 Android와 iOS에서 성공적인 패턴을 조금씩 가져오고 있습니다.