본문 바로가기
개발

프론트엔드 치트키[1] - MSW(Mock Service Worker)

by dohye1 2022. 10. 19.

목차

    반응형

    사실 어그로를 끌려고 제목을 저렇게 적어봤다ㅎ

     

    근데 난 치트키라고 생각하긴함.

    왜냐면 프론트작업에서 귀찮은 작업을 줄여주기때문임!

    MSW

    • DX를 위한 Mock Service Worker
    • 웹 프론트 개발자가 API구현 작업의 영향을 덜 받게 하여 DX를 개선하는것이 목표
    • 브라우저에 몰래?숨어있다가 마치 백앤드 API인 척하면서 프론트엔드의 요청이 발생하면 Mock 데이터를 응답해줌

    https://yozm.wishket.com/magazine/detail/1711/

    위 그림이 프론트엔드 작업 플로우를 잘 표현한다고 생각해서 첨부해봄

     

    새로운 기능이나 페이지를 만들때, api가 아직 준비가 안되어 있는 경우가 많다.

    그럴때마다 우리 팀은 mock파일을 만들어 가짜 데이터를 만들었다.

     

    그리고 비동기에 대한 처리(로딩 표현, state에 값 넣어주기 등)도 나중에 api를 연결할때 처리를 해주는경우도 있었기때문에

    2번이나 작업(퍼블리싱 할 때 /api연동 할 때)하는일이 많았다.

    (근데 이건 퍼블리싱할때 비동기 처리를 해줘도되긴한데, 내가 귀찮아서 안한거임. 점심메뉴는 그렇게 신중하게 고르면서 코드는 대충짜네ㅠㅜㅠ)

     

    API 개발 작업에 대한 의존성을 낮추자!

    • 프론트 개발 시 API 개발 작업에 대한 의존성을 낮추려면 결국 API가 필요한 시점에 실제로 존재하는 것처럼 가장해야하고, 이를 Mocking이라고 한다.
    • MSW는 브라우저의 Service Worker에서 동작한다.
    • 서비스 워커(Service Worker)를 사용하면 브라우저로 부터 나가는 요청이나 들어오는 응답을 중간에서 감시하거나 변조, 캐싱과 같은 기존에 웹에서 할 수 없었던 부가적인 작업들을 할 수 있다.

     

    Mock data 의 위치에 따른 특성을 생각해보자

    1. Mock데이터가 어플리케이션 로직 내부에 섞여있는 경우

    • 비지니스 로직 내에서 mocking을 하면 쉽게 moking할 수 있는 반면, 실제 API 연동 코드로 교체해주는 작업을 추가로 해야한다.

    2. Mocking용 서버를 외부에 만드는 경우

    • 외부 mocking용 api server를 만들어야한다.
    • 이럴거면 실제 api를 빨리 만드는게 나을지도..?

    3. Mocking을 서비스 워커에서 하는 경우 - MSW 

    • 웹 어플리케이션의 비지니스로직에 Mocking코드가 들어가지않는다.
    • api endpoint를 실제 api의 것으로 사용할 수 있다.
    • js를 이용해 웹 어플리케이션 프로젝트에 Mocking코드를 작성하는것이라, 프론트엔드 개발자가 쉽게 이용할 수 있다.
    • 실제 api 개발이 완료되면, MSW에서 핸들러만 제거하면 교체가 끝난다.

     

    실습

    - react-query와 msw를 같이 사용해봤다.

    msw를 사용하면 퍼블리싱과 api연동을 분리해서 작업할 필요가없을것같아 한번에 처리가 가능한 방식으로 생각해봤다.

     

    일단 

    react프로젝트에 실습을 해봄

    (이 글을 보고 따라했습니다.)

     

    1. msw를 설치해준다.

    npm install msw -d

    2. 그리고 service worker를 사용할 수 있는 환경을 세팅해준다.

    npx msw init public/ --save

    위 명령을 실행하면 public 폴더에 mockServiceWorker.js라는 파일이 생성된다. 근데 코드는 잘 이해가 안가긴함..ㅜㅠ

    족흠 어렵네

    3. mock api 적어주기

    src밑에 mocks라는 폴더를 만들어주고

    그 안에 handler.js라는 파일을 만들어줬다.

    import { rest } from "msw";
    
    const todos = ["React", "Svelte", "Vue", "Node"];
    
    export const handlers = [
      // 할일 목록
      rest.get("/todos", (req, res, ctx) => {
        return res(
          ctx.status(200),
          ctx.json({ data: todos }),
        );
      }),
    
      // 할일 추가
      rest.post("/todos", (req, res, ctx) => {
        todos.push(req.body);
        return res(ctx.status(201));
      }),
    ];

    4. worker에 추가해주기

    mocks폴더에 worker.js를 만들어주고 아래의 내용을 적는다.

    import { setupWorker } from "msw";
    import { handlers } from "./handler";
    
    export const worker = setupWorker(...handlers);

    워커에 내가 작성한 api를 연결해주는 코드같다.

    setupWorker에 handlers를 넘겨줄때 spread 문법을 쓰지않으면 에러가난다!

    꼭 붙이기!

    5. worker 실행시키기

    index.js에 아래의 코드를 추가해준다.

    ...
    import { worker } from "./mocks/worker";
    if (process.env.NODE_ENV === "development") {
      worker.start();
    }
    ...

    개발 모드일때만 워커가 실행되도록 한다. (이건 개발자마음대로 조건 정하면될듯)

     

     

    세팅은 끝났으니 이제 사용해보자!

     

    나는 react-query를 사용할거라 react-query도 설치해 줬다.

     

    나는 app.js에 간단하게 테스트를 해봄

    async function fetchTodo() {
      return await fetch("/todos").then((response) => response.json());
    }
    
    function App() {
      const { data, isLoading } = useQuery("todos", fetchTodo);
    
      console.log(data);
    
      if (isLoading) {
        return <div>Loading..</div>;
      }
    
      return (
        <div className="App">
        	Hello world~
        </div>
      );
    }

    hander.js에 /todos를 작성해줬었는데, 실제로 사용할때 저렇게 path만 적어주면 된다!

     

     

    앞으로 잘 써봐야겠군

    혹시 잘못된내용이있다면 댓글에 남겨주십쇼소솟...