개발 내용
웹앱 어플리케이션 프로젝트를 진행하며 workbox
의 캐시 기능을 이용하여 PWA을 개발하였습니다.
어플리케이션 최초 구동 시 필요한 리소스의 캐시가 완료되면, 재실행시 캐시 된 리소스 파일들을 사용하여 오프라인 상태에서 사용할 수 있도록 개발을 진행하였습니다.
개발 환경 구성
workbox
를 사용하기 위해서 workbox-build
모듈을 설치 후 service-worker
에서 사용될 serviceWorker.js
파일을 생성하도록 하였습니다.
리소스 캐시
프로젝트 내에서 캐시 할 리소스를 필수적으로 캐시가 되어야 하는지, 사용자 또는 환경에 따라 캐시가 필요한 리소스로 구분을 지었습니다.
그리고 각 구분에 따라 캐시 하는 내용을 다르게 구성하였습니다.
필수적으로 캐시가 되어야 하는 리소스
해당 리소스는 js
, css
와 같이 어플리케이션을 구동함에 있어 필수적인 것들을 구분하였습니다.
필수적으로 캐시가 되어야 하는 리소스는 workbox-routing
을 사용하여 캐싱될 수 있도록 하였습니다.
또한 추후 어플리케이션이 업데이트될 때 변경된 리소스 파일을 불러와야 하기 때문에 NetworkFirst
전략을 선택하였습니다.
...
workbox.routing.registerRoute(
'/',
new workbox.strategies.NetworkFirst({
cacheName: 'home',
})
);
//
...
사용자 또는 환경에 따라 캐시가 되어야 하는 리소스
사용자 또는 환경에 따라 캐시 되어야 하는 리소스는 사용자가 특정 액션을 취했을 때,
캐시 해야 할 리소스 리스트를 전달하여 해당 리스트에 있는 리소스 파일을 캐시 하도록 진행하였습니다.
먼저 service-worker
와 client 간의
통신을 위해서 postMessage 인터페이스
를 구성하여 사용하였습니다.
// index.js
public sendToMessage = async (params) => {
return new Promise((resolve, reject) => {
const channel = new MessageChannel();
channel.port1.onmessage = event => {
if (event.data.error) {
reject(event.data.error);
} else {
resolve(event.data);
}
};
if ('serviceWorker' in navigator) {
if (navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.postMessage(params, [channel.port2]);
}
}
});
};
// service-worker.js
function sendToMessageClient(type, params) {
const event = { type, params };
this.clients.matchAll().then(clients => {
clients.forEach(client => client.postMessage(JSON.stringify(event)));
});
}
클라이언트 페이지
에서는 캐시가 필요한 리소스 리스트를 postMessage 인터페이스
를 사용하여 RESOURCE_LIST
를 호출합니다.
sendToMessage({ type: 'RESOURCE_LIST', resourceList: ['../resources/1.png', '../resources/2.png'] });
client
에서 PostMesage RESOURCE_LIST
호출 시 전달받은 resourceList를 캐싱하도록 작업하였습니다.
또한 serviceWorker에서는 HTML DOM에 직접 접근이 불가함으로, client
페이지에서 캐싱 과정의 화면처리를 위하여 캐싱 성공 여부를 PostMeesage
로 전달하도록 하였습니다.
self.addEventListener('message', event => {
if (event.data.type === 'RESOURCE_LIST') {
cacheList = event.data.resourceList;
event.waitUntil(
caches
.open(resource.key)
.then(function(cache) {
cacheList.forEach(async item => {
cache
.add(item)
.then()
.catch(function(e) {
})
.finally(function() {
sendToMessageClient('ADD_CACHE', {});
});
});
})
.catch(function(e) {
})
);
}
});
이러한 과정을 통해 어플리케이션을 구동하기 위한 리소스 파일 캐싱이 완료되었습니다.
이후 어플리케이션 실행 시 캐시 된 리소스 파일을 사용하는 걸 확인되었으며, 또한 어플리케이션 업데이트가 있다면 workbox
의 NetworkFirst
의 전략에 따라 네트워크를 통해 변경된 리소스를 먼저 조회하기 때문에 변경된 리소스 파일을 다시 캐싱하여 사용하게 되었습니다.
참고자료
'Develope > 개발일지' 카테고리의 다른 글
QueryFunctionContext을 고민하면서.. (0) | 2024.07.02 |
---|