푸시 이벤트

지금까지 사용자 구독과 푸시 메시지 전송에 관해 알아보았습니다. 다음 단계는 사용자의 기기에서 이 푸시 메시지를 수신하고 알림을 표시하는 것입니다 (다른 작업도 진행해야 함).

푸시 이벤트

메시지가 수신되면 푸시 이벤트가 서비스 워커에 전달됩니다.

푸시 이벤트 리스너를 설정하는 코드는 자바스크립트로 작성하는 다른 이벤트 리스너와 매우 유사합니다.

self.addEventListener('push', function(event) {
    if (event.data) {
    console.log('This push event has data: ', event.data.text());
    } else {
    console.log('This push event has no data.');
    }
});

서비스 워커를 처음 사용하는 대부분의 개발자에게 이 코드에서 가장 이상한 부분은 self 변수입니다. self는 일반적으로 웹 워커(서비스 워커)에서 사용됩니다. self는 전역 범위를 나타내며 웹페이지의 window와 같습니다. 하지만 웹 워커와 서비스 워커의 경우 self는 워커 자체를 나타냅니다.

위의 예에서 self.addEventListener()는 서비스 워커 자체에 이벤트 리스너를 추가하는 것으로 생각할 수 있습니다.

푸시 이벤트 예에서 데이터가 있는지 확인하고 콘솔에 무언가를 출력합니다.

푸시 이벤트에서 데이터를 파싱할 수 있는 다른 방법이 있습니다.

// Returns string
event.data.text()

// Parses data as JSON string and returns an Object
event.data.json()

// Returns blob of data
event.data.blob()

// Returns an arrayBuffer
event.data.arrayBuffer()

대부분의 사람들은 애플리케이션에 기대하는 항목에 따라 json() 또는 text()를 사용합니다.

이 예에서는 푸시 이벤트 리스너를 추가하는 방법과 데이터에 액세스하는 방법을 보여주지만 매우 중요한 두 가지 기능이 누락되었습니다. 알림을 표시하지 않고 event.waitUntil()를 사용하지 않습니다.

대기 시간

서비스 워커에 대해 알아야 할 사항 중 하나는 서비스 워커 코드가 실행되는 시기를 제어할 수 없다는 것입니다. 브라우저는 절전 모드를 해제하는 시점과 종료 시점을 결정합니다. 브라우저에 '중요한 일에 너무 바빠서'라고 말할 수 있는 유일한 방법은 프로미스를 event.waitUntil() 메서드에 전달하는 것입니다. 이를 통해 브라우저는 전달한 프로미스를 해결할 때까지 서비스 워커를 계속 실행합니다.

푸시 이벤트의 경우, 전달한 프로미스를 해결하기 전에 알림을 표시해야 한다는 추가적인 요구사항이 있습니다.

다음은 알림을 표시하는 기본적인 예입니다.

self.addEventListener('push', function(event) {
    const promiseChain = self.registration.showNotification('Hello, World.');

    event.waitUntil(promiseChain);
});

self.registration.showNotification() 호출은 사용자에게 알림을 표시하고 알림이 표시되면 해결될 프로미스를 반환하는 메서드입니다.

이 예를 최대한 명확하게 유지하기 위해 promiseChain이라는 변수에 이 프로미스를 할당했습니다. 그런 다음 event.waitUntil()로 전달됩니다. 이 내용이 매우 장황하다는 것을 알고 있지만, waitUntil()에 전달해야 하는 항목을 잘못 이해했거나 프로미스 체인이 끊어져 여러 문제가 발생했습니다.

다음은 데이터에 대한 네트워크 요청과 애널리틱스로 푸시 이벤트를 추적하는 좀 더 복잡한 예입니다.

self.addEventListener('push', function(event) {
    const analyticsPromise = pushReceivedTracking();
    const pushInfoPromise = fetch('/api/get-more-data')
    .then(function(response) {
        return response.json();
    })
    .then(function(response) {
        const title = response.data.userName + ' says...';
        const message = response.data.message;

        return self.registration.showNotification(title, {
        body: message
        });
    });

    const promiseChain = Promise.all([
    analyticsPromise,
    pushInfoPromise
    ]);

    event.waitUntil(promiseChain);
});

여기서는 프로미스 pushReceivedTracking()를 반환하는 함수를 호출합니다. 이 예에서는 분석 제공업체에 네트워크 요청을 한다고 가정하겠습니다. 또한 네트워크 요청을 하여 응답을 가져오고 알림 제목과 메시지의 응답 데이터를 사용하여 알림을 표시합니다.

프로미스를 Promise.all()와 결합하여 이 두 태스크가 모두 실행되는 동안 서비스 워커가 활성 상태로 유지되도록 할 수 있습니다. 결과 프로미스는 event.waitUntil()에 전달됩니다. 즉, 브라우저가 두 프로미스가 모두 완료될 때까지 기다린 후에 알림이 표시되었는지 확인하고 서비스 워커를 종료합니다.

waitUntil()와 그 사용 방법을 고려해야 하는 이유는 개발자가 직면하는 가장 일반적인 문제 중 하나는 프로미스 체인이 잘못되었거나 깨졌을 때 Chrome에서 다음과 같이 '기본' 알림을 표시하기 때문입니다.

Chrome의 기본 알림 이미지

Chrome은 '백그라운드에서 업데이트된 사이트입니다'라는 알림만 표시합니다. 푸시 메시지가 수신되고 event.waitUntil()에 전달된 프로미스가 완료된 후 서비스 워커의 푸시 이벤트에 알림이 표시되지 않습니다.

이 오류가 발생하는 주된 이유는 코드가 self.registration.showNotification()를 호출하기는 하지만 반환되는 프로미스로 아무것도 하지 않기 때문입니다. 이렇게 하면 간헐적으로 기본 알림이 표시됩니다. 예를 들어 위 예에서 self.registration.showNotification()의 반환을 삭제하면 이 알림이 표시될 위험이 있습니다.

self.addEventListener('push', function(event) {
    const analyticsPromise = pushReceivedTracking();
    const pushInfoPromise = fetch('/api/get-more-data')
    .then(function(response) {
        return response.json();
    })
    .then(function(response) {
        const title = response.data.userName + ' says...';
        const message = response.data.message;

        self.registration.showNotification(title, {
        body: message
        });
    });

    const promiseChain = Promise.all([
    analyticsPromise,
    pushInfoPromise
    ]);

    event.waitUntil(promiseChain);
});

놓치기 쉬운 것을 알 수 있습니다.

이 알림이 표시되면 프로미스 체인과 event.waitUntil()를 확인하세요.

다음 섹션에서는 알림의 스타일을 지정하기 위해 할 수 있는 일과 표시할 수 있는 콘텐츠에 관해 알아보겠습니다.

다음에 수행할 작업

Codelab