NextJS에서 MSW를 사용해보자

pingu·2023년 5월 24일
5
post-thumbnail

MSW란?

Mock Service Worker의 약자로 Service Worker API를 사용하여 실제 요청을 가로채는 API mocking 라이브러리


왜 사용하냐?

보통 프로젝트를 진행할 때, 백엔드가 API를 만들면 그 API를 통해 프론트엔드가 인터페이스를 만든다. 만약 같이 시기에 프로젝트를 시작했다면? 프론트엔드는 백엔드가 API를 만들어주기 전까지 손가락만 빨면서 기다려야한다.
그럴땐 가서 백엔드 멱살을 잡으면 된다

이럴때 프론트의 손가락 빠는 시간을 줄여주는 놈이 바로 MSW이다.
API요청을 보낼때 MSW가 가로채서 내가 원하는 데이터를 가져다 주고 브라우저한텐 모르게하는 방식이다.
언뜻 생각하면 교차-출처 리소스 공유(Cross-origin resource sharing, CORS)를 허용하기 위해 사용하는 Proxy의 동작 방식과 유사하다.

JsonServer와의 차이점

전에 JsonServer 라는 REST API Mock server 툴을 사용해 본 경험이 있다.
MSW가 브라우저에서 API요청을 가로채서 데이터를 바꿔치기하고 돌려주는 방식이라면, JsonServer는 로컬에 Json파일을 그대로 localhost 서버를 띄운다. ( postman 접근 가능 )
둘중에 편한 방식이라면 빠르고 postman으로 테스트도 쉬운 JsonServer를 선택했겠지만
내가 경험했을 때 중첩 배열에 접근하여 데이터를 조작하는 부분에 있어서 단점인점과 그 외의 단점도 많이 갖고 있는 JsonServer이기에 ( 깃헙 이슈가 굉장히 많다 ) 현업에서는 MSW를 많이 사용한다고 한다.


NextJS에서의 MSW?

MSW에 대한 레퍼런스는 굉장히 많다. 개인적으로 코딩악마 유툽에서 한번 봤는데 한번에 이해가 되었다.
근데 NextJS + MSW 는 상대적으로 많이 없다.
NextJS 유행한지 얼마 안됐는데 그럴만 하다
그냥 리액트로는 테스트 해봤을 때 별 문제가 없어서 신경을 안썼는데 NextJS에서는 뭐가 자꾸 에러나길래 포스팅을 시작했다.


설치 및 파일 추가

npm install msw --save-dev
또는
yarn add msw --dev

src/mock/handlers.ts // 요청을 모킹하는 핸들러 작성

import { rest } from 'msw';

export const handlers = [
  rest.get('https://jsonplaceholder.typicode.com/todos', (req, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json(["먹기", "자기", "놀기"]),
    );
  }),
];

파일 생성 후에 사기칠 데이터를 만든다. URL은 아무 주소 갖다 넣어도 상관없다. 나중에 호출할 때 쓰이는 요청 URL이랑 동일하기만 하면 된다.
난 내일 먹고 자고 놀거다.

src/mocks/browser.ts // 브라우저 환경 설정

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

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

src/mocks/server.ts // node 환경 설정

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

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

src/pages/_app.tsx // MSW 동작 방식 설정

import '@/styles/globals.scss';
import type { AppProps } from 'next/app';

export default function App({ Component, pageProps }: AppProps) {
  if (process.env.NODE_ENV === 'development') {
    if (typeof window === 'undefined') {
      (async () => {
        const { server } = await import('../mocks/server');
        server.listen();
      })();
    } else {
      (async () => {
        const { worker } = await import('../mocks/browser');
        worker.start();
      })();
    }
  }
  return <Component {...pageProps} />;
}

여기서 리액트 MSW 방식과의 차이점이 있다
CRA의 경우 src/mocks/browser 파일의 worker를 불러와 worker.start() 만 실행하면 된다.
CNA(NextJS)의 경우 server side가 먼저 실행된 후 브라우저 환경인 client side가 실행되기 때문에 node 환경에 대해서 추가적으로 설정을 진행해줘야 한다. 안그럼 에러뜸 ㅅㄱ
그래서 위에서 src/mocks/server를 추가해줬다.

.env // 개발 환경에서만 동작하게끔 설정해주기

NODE_ENV=development

이제 설정은 끝났다.
아래 명령어로 서비스 워커를 생성하자

npx msw init public/ — save

MSW는 브라우저에서 서비스 워커를 통해서 작동하기 때문에 서비스 워커 등록을 위한 기본적인 코드가 필요하다. 다행히도 서비스 워커에 대해서 잘 몰라도 MSW에서 제공하는 CLI 도구를 사용하면 이 코드를 쉽게 만들어 낼 수 있다.

그러면
public/mockServiceWorker.js 가 생성된다.

이제 요청을 보낼 코드를 입력한다.

const getTest = () => {
    axios
      .get(
        'https://jsonplaceholder.typicode.com/todos',
      )
      .then((res) => {
        const { data } = res;
        console.log(data);
      })
      .catch((error) => console.log(error));
  };

여기서 URL은 아까 위에서 설명했듯이, 사기칠 URL과 동일한 주소로 입력한다.
그러면 이 URL로 요청을 보낼 때마다 MSW가 가로채서 내가 원하는 데이터를 뱉어줄거다.

이제 프로젝트 실행해서 테스트하면 된다.


프로젝트 실행 및 테스트


성공이다.
솔직히 빨간 글자라서 에러뜬줄 알고 뭐가 잘못된건지 계속 뒤져봤음
근데 알고보니 disabled가 아니고 enabled 이더라...

가로채기 성공해서 아까 내가 넣어줬던 데이터를 뱉어준다.
원래 주소로는 요청이 가긴 하는데 X-Powered-By: msw 이므로 msw API 응답임을 다시한번 확인 가능하다.

profile
코딩공부 리뷰

0개의 댓글