Develop Note by J.S.

[Worker] Service Worker 본문

FrontEnd/Worker

[Worker] Service Worker

js-web 2023. 6. 21. 10:56
반응형

Service Worker 

- 웹 페이지 외에서 브라우저 내 스크립트와는 다른 쓰레드로 동작되는 기능입니다. http 요청을 catch하는 네트워크 프록시 기능을 구현할 수 있습니다. 
- 리소스 caching 처리 기능 구현이 가능하고 Push 알림(PWA)이 가능하여 개발 단계에서 MSW(mocking service worker)를 사용한 API Testing 기능 구현이 가능합니다. 
- Service Work는 페이지의 DOM과의 직접적인 상호작용은 할수 없지만 Message를 통하여 통신합니다.

- Service Worker 생명주기 : 설치중 -> 설치완료/대기 -> 활성화중 -> 활성화완료 -> 중복(설치실패 및 교체) 

 

설치

npm install register-service-worker

1. Service Worker 정의

// service-worker.js
const channel = new BroadcastChannel('broadcast-messages'); // broadcast 메세시 채널
let token = ''; // service worker 단에서 사용하는 token

self.addEventListener('install', async (e) => {
    await self.skipWaiting();
});

//service worker 제어권을 준다
self.addEventListener('message', async (event) => {
    if ('CLAIM' === event.data.type) {
        self.clients.claim();
    }
});

// custom message
channel.addEventListener('message', async (event) => {
	channel.postMessage({ id: id, data: token });
});

// catch http request 
self.addEventListener('fetch', (event) => {
	event.respondWith( //header token 추가 예제
        (async () => {
            try {
                let res;
                const req = async () => {
                    res = await fetch(request, {
                        headers: {
                            ...Object.fromEntries(request.headers.entries()),
                            Authorization: `Bearer ${token}`, // header에 token을 추가
                        },
                    });
                };
                await req(); //api 요청

                return res; // client로 respone data return
            } catch (e) {
                console.error('access token 셋팅 에러! 로그아웃 처리', e);
                token = '';
            }
        })()
    );
})

//활성 상태 event
self.addEventListener('activate', (event) => {
    event.waitUntil(
        (async () => {
            await self.clients.claim(); // 제어권을 넘겨준다
        })()
    );
});

2. Service Worker Register File

// registerServiceWorker.js

import { register } from 'register-service-worker';

register(`@/service-worker.js`, {  //service-worker 정의 file 호출
    ready() {
        console.log('App is being served from cache by a service worker.');
    },
    async registered() {
        if (!navigator.serviceWorker.controller) {
            location.reload();
        }
        console.log('Service worker has been registered.');
    },
    cached() {
        console.log('Content has been cached for offline use.');
    },
    updatefound() {
        console.log('New content is downloading.');
    },
    updated() {
        console.log('New content is available; please refresh.');
    },
    offline() {
        console.log('No internet connection found. App is running in offline mode.');
    },
    error(error) {
        console.error('Error during service worker registration:', error);
    },
});

3. registerServiceWorker 사용 등록

// app.js or main.js
import '@/registerServiceWorker';  // 등록할 service worker 추가

4. service worker Message 통신

//브라우저 단 소스파일 

//custom message
const channel = new BroadcastChannel('broadcast-messages'); // broadcast 메세지 채널
channel.addEventListener('message', handleResponseMessage); //service
const resolveObj = {}; //resolve
const rejectsObj = {};
let promiseId = 0;

export const serviceWorkerMessage = {
	//먼저 service worker의 제어권을 가져온다
	claim() {
        window.navigator.serviceWorker.controller.postMessage({ type: 'CLAIM' });
    },
    
    async customMessage() {
        await promiseMessage({ type: 'TEST' });
    },
}

//Message 비동기 처리
function promiseMessage(payload) {
    promiseId += 1;
    payload = { ...payload, id: promiseId };

    return new Promise((resolve, reject) => {
        resolveObj[payload.id] = resolve; //비동기 성공 응답 객체 저장
        rejectObj[payload.id] = reject; // 비동기 실패 응답 객체 저장
        channel.postMessage(payload);
    });
}


async function handleResponseMessage(event) {
    // service worker로부터 받은 비동기 response처리
    if (event) {
        const resolve = resolveObj[id]; 
        if (resolve) {
            resolve(event); //저장된 응답 객체 실행
        }
    } else {
        const reject = rejectObj[id]; 
        if (reject) {
            reject(error); //저장된 응답 객체 실행
        }
    }
}

5. 실행 확인

Service Worker가 정상적으로 동작되는지 확인하려면 개발자모드 -> application Tab을 클릭하면 아래와 같이 실행된 Service Worker 정보를 확인할 수 있습니다.

 

참고사이트
https://developer.mozilla.org/ko/docs/Web/API/Service_Worker_API

반응형

'FrontEnd > Worker' 카테고리의 다른 글

[Worker] Web Worker  (0) 2023.06.23
[Worker] Mock Service Worker  (0) 2023.06.22