blog.stackframe.dev

블로그 개발 삽질기 4 - Service Worker

  1. 블로그 개발 삽질기 0 - 발단
  2. 블로그 개발 삽질기 1 - 설계
  3. 블로그 개발 삽질기 2 - reStructuredText 파서 구현
  4. 블로그 개발 삽질기 3 - 템플릿 구현
  5. 블로그 개발 삽질기 4 - Service Worker
  6. 블로그 개발 삽질기 5 - 파서 리팩토링

사실 Service Worker에 대해선 그리 삽질하지 않았다. 예전에 다른 사이트에 Progressive Web App을 구현하려고 좀 만져보다가 수정해야 할 게 너무 많아서 포기한 적이 있었다. 그래도 작동원리와 구현방법은 계속 읽어봤고, 블로그를 직접 만들 기회가 생겼으니 처음부터 적용하고 개발을 시작했다.

Service Worker의 가장 주된 활용은 캐싱이다. 기존의 브라우저들도 기본적으로 자바스크립트, 스타일시트, 이미지 같은 정적 요소들에 대한 캐싱을 한다. 하지만 서버 측에서 캐시를 관리하기 위한 방법은 Cache-Control 헤더를 이용하는 정도로 매우 제한적이다. Service Worker는 모든 GET 요청이 프록시되므로 사이트 측에서 자유롭게 캐시 정책을 만들 수 있고 임의로 리다이렉트 하는 등 자유롭게 요청을 조작할 수 있다.

이 블로그의 캐시 정책은 매우 간단하다. 먼저 서버에 요청을 하고 에러가 발생한다면 캐시에서 가져온다. 이렇게하면 인터넷 연결없이도 한번이라도 접속한 페이지는 마치 인터넷에 연결되어 있는 것처럼 링크를 클릭하면 접속된다.

var VERSION = 'V3';
var mustCacheList = [
	'/css/common.css',
	'/css/rst.css',
	'/css/style.css',
	'/js/comment.js',
];

self.addEventListener('install',(ev) => {
	ev.waitUntil(caches.open(VERSION).then((cache) => {
		return cache.addAll(mustCacheList);
	}));
});

self.addEventListener('fetch',(ev) => {
	ev.respondWith(
		fetch(ev.request.clone()).then((res) => {
			return caches.open(VERSION).then((cache) => {
				cache.put(ev.request,res.clone());
				return res;
			});
		}).catch((e) => {
			return caches.match(ev.request).then((res) => {
				return res;
			});
		})
	);
});

self.addEventListener('activate',(ev) => {
});

현재 이 블로그에서 사용되고 있는 코드이다. 처음 설치될 때 기본적으로 사용되는 스타일시트와 자바스크립트를 캐시에 넣는다. 위에서 설명했듯이 fetch()로 요청을 그대로 서버에 넘기고 성공하면 응답을 캐시에 저장하고 되돌려준다. 에러가 발생하면 해당 요청에 대응하는 응답을 캐시에서 찾아서 가져온다. 만약 캐시에서도 찾지 못한다면 당연히 에러가 발생한다.

인터넷 연결없이 캐시되지 않은 페이지에 접근한 결과

댓글