MSW가 API 호출보다 늦게 시작될때

한호수 (The Lake)·2023년 7월 23일
2
post-thumbnail
post-custom-banner

개요

프론트에서 API를 mocking 할때 msw를 항상 사용했는데 초기 설정을 하고 작성한 api를 테스트하면 항상 첫 요청이 실행되지 않는 문제가 자주 있었다. 최근에는 vite를 사용하면서 api를 테스트하려고 했는데 같은 문제가 발생했는데 해결방법을 찾아서 포스팅한다.

원인

보통 msw 초기 설정을 할때 index.jsmain.js에 react render 코드 보다 위에 실행 코드를 작성한다. 공식사이트에서는 기본 권장 설정으로 아래와 같이 권하고 있다.

if (process.env.NODE_ENV === 'development') {
  const { worker } = require('./mocks/browser')
  worker.start()
}

worker 시작은 비동기 작업이며, 마운트 시 요청을 만드는 애플리케이션과 경쟁 조건을 생성할 수 있습니다. 이 경우 작업자가 준비되었을 때 애플리케이션 마운트를 시행하려면 지연된 마운트 방법을 참조하십시오.

하지만 서비스 워커 등록은 비동기 프로세스로 이루어지기 때문에 기본 권장 설정시 API를 호출하는 앱과 경쟁상태를 일으켜 문제를 일으킬 수 있기 때문에 지연된 마운트라는 해결방법을 권장하고 있었다.

원인은 렌더링이 서비스 워커 등록보다 먼저 시작된 것이었다.

해결법

해결방법은 생각보다 간단했다. 말그대로 비동기이기 때문에 promise를 사용하여 서비스 워커와 렌더링의 순서를 정해주면 되었다.

// src/index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from './App'

function prepare() {
  if (process.env.NODE_ENV === 'development') {
    const { worker } = require('./mocks/browser')
    return worker.start()
  }

  return Promise.resolve()
}

prepare().then(() => {
  const root = ReactDOM.createRoot(document.getElementById("root"));
  root.render(<App />);
})

또는 ES2022에 추가된 Top-level await와 IIFE를 통해 간단하게 작성 할 수도 있다.

// src/index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

if (process.env.NODE_ENV === "development") {
  await (async () => {
    const { worker } = await import("./mocks/browser");
    worker.start();
  })();
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);

맺음말

사실 msw 공식문서에 부연 설명으로 해당 문제에 대해서 경고했고, 해결할 수 있는 방법도 따로 문서로 제공하였지만 사용하는데 급급해서 제대로 확인을 못한 잘못이었다. 앞으로는 조금 더 꼼꼼히 학습할 필요성을 느꼈다.

profile
항상 근거를 찾는 사람이 되자
post-custom-banner

0개의 댓글