-
Notifications
You must be signed in to change notification settings - Fork 0
Service Worker
서비스 워커는 브라우저가 백그라운드에서 실행하는 스크립트로, 웹 페이지와는 별개로 작동하며 웹 페이지 또는 사용자의 인터랙션이 필요하지 않은 기능만 제공하고 있다. 서비스 워커의 수명주기는 웹 페이지와는 완전히 별개이다. 웹 서비스와 브라우저 및 네트워크 사이에서 프록시 서버 역할을 하며, 오프라인에서도 서비스를 사용할 수 있도록 한다.
웹 페이지와 별개로 존재하기 때문에 다음과 같은 제약이 있다.
- 서비스 워커는 요청하지 않는 이상, 없는 것이나 다름이 없다.
- 웹 페이지 life cycle을 따르지 않는다. 서비스 워커는 웹 페이지가 닫히더라도 자동으로 비활성화되지 않는다.
- 웹 페이지와 별개로 존자해므로 DOM이나 window 요소에 접근할 수 없다.
fetch
이벤트의 중간자 역할로 사용할 수 있다. 이 경우 서비스 워커는 HTTP를 통해 정보를 요청하는 대신 가지고 있는 캐시에서 자료를 전달한다. 캐시가 삭제되지 않는 한 브라우저는 인터넷 연결 없이도 정보를 보여줄 수 있다.
브라우저 창이 닫힌 상태에서도 동작하므로, 푸시 알림을 구현할 수 있다.
채팅 메시지 또는 사진 업로드 등의 작업 도중 컴퓨터가 오프라인 상태가 되는 경우 온라인 상태가 되었을 때 해당 작업을 마저 완료할 수 있다.
fetch란 web resource에 접근하기 위해 행해지는 모든 request action을 의미한다. service worker는 fetch를 통해 발생하는 모든 http request를 중간에서 가로챌 수 있다. (proxy) 예를 들어 실 서버로 보내지는 request를 중간에서 가로채어 서버로 보내지 말고 대신 cache 된 데이터를 제공하는 등의 처리를 하는 것이 가능하다.
http request가 있을 때마다 fetch이벤트가 발생하는데 service worker는 fetch event listener를 등록하여 이벤트를 감지하고 있다가 fetch이벤트가 발생할 때 listener에서 request를 intercept하는 방식이다.
- 윈도우에서 해당 윈도우를 제어하는 서비스 워커로 메시지 보내기
- 서비스 워커에서 범위 내의 모든 윈도우로 메시지 보내기
- 서비스 워커에서 특정 윈도우로 메시지 보내기
- 윈도우간 메시지 보내기 (서비스 워커를 통해)
페이지에서 서비스워커를 가져오려면 다음과 같이한다.
navigator.serviceWorker.controller
그 후에는 메시지 자체를 첫번째 인수로 받는 서비스 워커의 postMessage()
메서드를 활용한다.이 메시지는 무엇이든 될 수 있다.
메시지가 게시되고 나면 서비스 워커는 message 이벤트를 수신하여 해당 메시지를 받을 수 있다.
self.addEventListener('message', function(event){
console.log(event.data)
})
위 예제는 메시지를 받아서 콘솔에 출력한다. 메시지에 포함된 콘텐츠는 이벤트 리스너에 전달된 이벤트 객체의 데이터 속성에서 찾을 수 있다. 메시지 데이터 자체를 포함하는 것 이외에도 이벤트 객체는 여러 유용한 속성을 가지고 있다. 가장 유용한 속성중 일부는 source 속성에 있다.
source 속성에는 메시지를 보낸 윈도우 정보가 들어있다. 이 정보를 활용해서 무엇을 할지 그리고 응답을 어디로 보낼지 판단할 수 있다. 다음 코드는 메시지의 source 속성을 사용하는 간단한 예제 코드이다.
self.addEventListener('message', function(event) {
console.log('Message received:', event.data);
console.log('From a window with the id:', event.source.id);
console.log('which is currently pointing at:', event.source.url);
console.log('and is', event.source.focused ? 'focused' : 'not focused');
console.log('and', event.source.visibilityState)
})