[MSW] next.js 적용해보기

해달·2022년 6월 7일
8

MSW Mock Service Worker

데이터 모킹 라이브러리

모킹(Mocking)이란?

Mock(모의 데이터)을 만들어서 활용하는 방식

이전에 Jest를 가볍게 사용해보면서 Mock에 대한 개념이 추상적으로 잡혀있었는데,
찾아보니 서버에서 API개발이 완료되기 전에
클라이언트에서 테스트를 하거나, 서버에 데이터를 받아오는것처럼
임의의 데이터를 만들어놓고 사용할 때 필요한것이라고 한다.

현재 친구를 위해 만들어주고 있는 사이트가 있는데 강의를 듣고 전반적으로 내용을 정리하고
적용해본 내용을 기록해보고자 한다!


MSW 적용하기

브라우저 Request flow diagram

  1. 브라우저에서 리퀘스트를 보내면
  2. 서비스워커가 받고
  3. 리퀘스트를 클론해서
  4. msw에게 보낸다
  5. 모킹한값으로 응답을 내려준다

서비스워커는 브라우저 환경이 아닌곳에서는 동작하지 않는다
노드에서는 노드버서 방식을 사용한다


⚙️ 설치 및 세팅

npm 명령어를 이용해서 설치 한 뒤
public 폴더에 mockServiceWorker 파일을 생성해주는 명령어까지 실행시킨다.

  • mockServiceWorker 파일을 생성해야만 작동이 된다.
npm install msw --save-dev
npx msw init public/ --save (--save 생략가능)

생성 된 파일 모습

_app.tsx

//worker를 실행 시켜주는 코드 추가

if (process.env.NEXT_PUBLIC_API_MOCKING === 'enabled') {
  import('../mocks');
}

개발환경이면 mocks/browser안에 있는 worker를 꺼내 start 시킨다.

.env

NEXT_PUBLIC_API_MOCKING=enabled

mocks

next.js 깃허브 예제에 나와있는대로 mocks 폴더 아래에 파일들을 세팅해준다.

mocks/browser.ts

import { setupWorker } from 'msw';
import { handlers } from './handlers';

export const worker = setupWorker(...handlers);

mocks/handlers.ts

import { rest } from 'msw';

export interface FriendResponse {
  data: {
    name: string;
    info: {
      brithday: string;
      mbti: string;
      blood: string;
      etc: string;
    };
  };
}

export const handlers = [
  // Handles a GET /user request
  rest.get<FriendResponse>('https://backend.dev/friends', (req, res, ctx) => {
 
    return res(
      ctx.status(200),
      ctx.json({
        name: 'x',
        info: {
          brithday: '0_월 __일',
          mbti: 'ISFP',
          blood: '_형',
          etc: '',
        },
      })
    );
  }),
];

mocks/index.ts

if (typeof window === 'undefined') {
  const { server } = require('./server');
  server.listen();
} else {
  const { worker } = require('./browser');
  worker.start();
}
export {};

mocks/server.ts

import { setupServer } from 'msw/node';
import { handlers } from './handlers';

export const server = setupServer(...handlers);

index.tsx(적용파일)

InferGetServerSidePropsType<typeof getServerSideProps>
서버사이드로 데이터를 받아오면 이렇게 데이터타입을 지정해주었는데
받아온 데이터의 타입을 아래와 같이 지정해주었다
맞는 방법인지 잘 모르겠다

const Friend = ({ data }: FriendResponse) => {}


//fetch
  const response = await fetch('https://backend.dev/friends');
  const res = await response.json();

 
//axios
  const { data } = await axios.get<FriendResponse>('https://backend.dev/friends');

  return {
    props: {
      data,
    },
  };

MSW 타입 에러

Invariant Violation: Failed to respond to "GET URL" request: the "request" event has already been responded to.
GitHub ISSUES : https://github.com/mswjs/msw/issues/1271

서버사이드로 데이터를 내려주려고 했는데
첫 요청에서만 데이터를 받아오고 그 이후로는 위와 같은 에러코드가 발생해서

요청코드에 문제가 있는건가싶어서 검색을 엄청했는데 같은 에러로
그저께 등록된 이슈가 있었다

내 MSW 버전을 확인해보니까 이슈에 등록되어있는 버전과 같은 버전이였고 (v.0.42)
MSW에서 만들어놓은 next.js 예제에 있는 버전으로 다운그레이드 하고 나니까
해결하려고 여러가지삽질을 했지만
위 에러가 해결되고 데이터도 정상적으로 받아와졌다 😭

MSW버전 (v.0.42)
다운그레이드 : "^0.29.0"


Reference

0개의 댓글