웹 서비스를 배포한 후에 서비스의 버전은 달라졌는데 어떻게 유저에게 알리고 새로고침을 유도할 수 있을까? 라는 고민에서 시작해 여러 글을 보고 비교하며 고민한 결과, 웹 워커를 사용하게 되었다. 관련한 글들은 너무 정리가 잘 된 글이 많아서.. 난 실제로 어떻게 사용했는지를 기록해 두려고 한다!
너무나도 잘 정리된 글이 많은것도 사실이고 하니 간단하게만 짚고 넘어가보자! 우선 웹 워커하면 항상 따라나오는 키워드가, 자바스크립트의 싱글스레드... 이다. 맞다. 우리의 영원한 친구 자바스크립트는 무려 싱글 스레드이다. 그런데, 웹 서비스를 사용하는 우리들은 웹 서비스와 인터렉티브를 하나씩 주고받지는 않는다. 여기서 이벤트루프와 같은 친구가 뽜밤하고 등장하기도 하는데, 아무튼 싱글 스레드인 자바스크립트의 동시성을 도와주는 친구가 있다는게 얘기의 핵심이다. 그렇다. 웹 워커 또한 mdn을 살펴보면, window와는 다른 맥락에서 동작하는 별개의 스레드라고 소개하고 있다.
사용하는데 있어서 몇가지 제약은 존재하는 것으로 보인다. mdn에서 확인해보쟈.
사용했다는 여러 글들을 보면 웹 워커를 통해 메인 스레드를 방해할만한 커다란 로직 처리를 하는것으로 보인다...
웹의 어디에 있던지 지속적인 api호출로 서비스의 버전이 최신인지 여부를 지속적으로 체크하게 할 것이므로, 그 비용이 크지 않다고 하더라도 뒷단에서 돌려보자.
흐름은 대략 이렇다.
뭐... 그냥 setinterval 돌려도 잘 돌아간다.
업데이트 되었다고 뜬 모달은 어느 페이지를 가던지 새로고침을 하기 전까진 항상 표시되게 할 것이다. 그리고 모달이 떠 있다면 그 후로는 api 호출을 멈출 것이다.
새로고침하면 이후부터는 다시 api콜이 지속적으로 호출을 시작할 것이다.
간략하게 작성해봅시당.
모달은 최상단에서 항상 떠 있어야 하므로 _app.js에서 그려주었다. 웹 워커 또한 이곳에서 관리된다.
// _app.js
const [isReleaseUpdate, setisReleaseUpdate] = useState(false);
const workerRef = useRef();
useEffect(() => {
workerRef.current = new Worker(
new URL("worker.js 파일 위치", import.meta.url) // new URL을 사용 안할시에는 실제 서버에서의 위치라고 한다.
);
workerRef.current.onmessage = (e) => {
setReleaseUpdate(e.data.update);
};
workerRef.current.postMessage("Start");
}, []);
useEffect(() => {
if (isReleaseUpdate) {
workerRef.current.postMessage("Stop");
}
}, [isReleaseUpdate]);
return (
// ...
<Hydrate state={pageProps.dehydratedState}>
<Component {...pageProps} />
{isReleaseUpdate && <Modal refreshPage={refreshPage} />}
</Hydrate>
)
worker.js도 작성해보자.
import { getVersion } from "../api";
let intervalID = null;
onmessage = async (e) => {
if (e.data === "Stop" && intervalID) {
clearInterval(intervalID);
}
else {
intervalID = setInterval(async () => {
const version = await getVersion();
// process.env... 은 .env에 작성된 값이다. package.json에서 version 프로퍼티 값을 가져온다.
if (parseInt(process.env.NEXT_VERSION) < version) {
postMessage({ version: lbhVersion, update: true });
} else {
postMessage({ version: lbhVersion, update: false });
}
}, 3000);
}
};
// package.json
{
"version": "1.0.0",
}
잘 돌아가는지... package.json의 버전을 바꿔보며 테스트해보면 된다...!
vue.js는 worker-loader를 설치해서 구현했다. 그냥 Worker로 해보려는데 잘 안되서...
아무튼 이렇게 웹 워커로 나름 간단하게 백그라운드에서 열심히 돌아갈 탐지견 하나를 심어놨다.
열심히 평생 돌아라..!