웹 워커로 버전 업데이트 알림 보내기 (netx.js)

박정훈·2023년 3월 16일
0

Next.js

목록 보기
3/5

웹 서비스를 배포한 후에 서비스의 버전은 달라졌는데 어떻게 유저에게 알리고 새로고침을 유도할 수 있을까? 라는 고민에서 시작해 여러 글을 보고 비교하며 고민한 결과, 웹 워커를 사용하게 되었다. 관련한 글들은 너무 정리가 잘 된 글이 많아서.. 난 실제로 어떻게 사용했는지를 기록해 두려고 한다!

web worker

너무나도 잘 정리된 글이 많은것도 사실이고 하니 간단하게만 짚고 넘어가보자! 우선 웹 워커하면 항상 따라나오는 키워드가, 자바스크립트의 싱글스레드... 이다. 맞다. 우리의 영원한 친구 자바스크립트는 무려 싱글 스레드이다. 그런데, 웹 서비스를 사용하는 우리들은 웹 서비스와 인터렉티브를 하나씩 주고받지는 않는다. 여기서 이벤트루프와 같은 친구가 뽜밤하고 등장하기도 하는데, 아무튼 싱글 스레드인 자바스크립트의 동시성을 도와주는 친구가 있다는게 얘기의 핵심이다. 그렇다. 웹 워커 또한 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로 해보려는데 잘 안되서...

아무튼 이렇게 웹 워커로 나름 간단하게 백그라운드에서 열심히 돌아갈 탐지견 하나를 심어놨다.
열심히 평생 돌아라..!

profile
그냥 개인적으로 공부한 글들에 불과

0개의 댓글