logo

DowanKim

7. MSW란 무엇일까

2025년 9월 22일

이게머니

지난 이현빈 멘토님과의 멘토링에서, 여러질문을 하였고 그중 대표적인 질문은 다음과 같았습니다.

로그인 API가 구현이 안되어서 그 뒤 작업도 섣부르게 시작하기 어려운데, 그 시간동안 프론트 개발자는 무엇을 해야 하나요?

질문의 퀄리티가 굉장히 낮았지만, 사실 그 속에 든 뜻은, 나름 프론트 팀장으로써 여러 중책을 맡은 상황(공통 컴포넌트, api 커스텀 훅, api 기본 세팅, 그나마 가장 어려운? 로그인 기능)에서, 물론 그 다음 작업들도 지금처럼 목데이터를 직접 노가다로 작성하고 각각 파일을 만들어 연결하면서 만들 수 있지만, 어차피 다시 다 api 작업으로 바꿔야 하는 것에 굳이 시간을 두번씩 소비해야할까? 라는 속뜻이 있었습니다.

그때, 멘토님께서는 msw에 대해 소개해 주셨습니다.

https://mswjs.io/docs/quick-start

늘 한글로된 블로그를 보면서 이러한 새로운 기술에 대해 작업을 시작했다가 문법이 최근에 바뀐(예를 들어 suspense속성이 useSuspense로 바뀐 것 같은..)거에 데인적이 워낙 많아서 공식문서로 시작했습니다.

1. MSW 패키지 설치

npm install msw --save-dev

—save-dev 는 개발 환경에서만 사용하므로 devDependencies에 추가하려고 작성합니다.

npx msw init public/ --save

service worker 파일을 만듭니다.

브라우저에서 네트워크 요청을 가로채기 위해섭니다.

public/mockServiceWorker.js 파일이 생성됩니다.

2. MSW 파일 구조

src/ ├── mocks/ │ ├── handlers.ts # API 핸들러 정의 │ └── browser.ts # 브라우저용 설정 └── main.tsx # MSW 활성화 코드

public/ └── mockServiceWorker.js # MSW Service Worker 파일

파일 구조는 이러합니다. 사실상 지금 저희는 테스트 코드를 작성하고 있지 않기에 테스트 파일 및 세팅은 굳이 하지 않았습니다.

다만 멘토님과 멘토링 과정에서 추후 테스트 코드도 작성해보기로 계획했기에, 추후 고려해볼 내용입니다. 물론 그때는 서버와의 연결이 잘 된 상태일 것 같긴 합니다.

3. handlers.ts

실질적으로 handlers.ts에서 api모킹 로직을 구현하였습니다.

api문서 기반, 간단한 로직만 구현하고, 아직 토큰 기반의 개인화된 데이터는 제공하지 않습니다.

대표적으로 일단 내일 있을 백엔드와의 로그인 기능 대면 구현 전에 로그인 기능 구현에 초점을 두었습니다.

http.post('/api/login', async ({ request }) => { const body = (await request.json()) as { code: string }; console.log('MSW: 카카오 로그인 요청 받음', body); const response = { accessToken: 'mock-access-token-12345', refreshToken: 'mock-refresh-token-67890', userId: 'mock-user-123', user: { id: 'mock-user-123', nickname: '테스트유저', profileImage: 'https://via.placeholder.com/100', email: 'test@example.com', }, }; console.log('MSW: 카카오 로그인 응답 반환', response); return HttpResponse.json(response); }),

핸들러의 역할로는

네트워크 요청을 가로채 실제 서버로 가지 않고 가짜 응답을 반환합니다

그 외에도, 다양한 시나리오 테스트(성공, 실패, 지연), 일관된 테스트 데이터 등의 장점이 있습니다.

4. browser.ts

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

service worker를 사용해 네트워크 요청을 가로채고, api핸들러들을 워커에 등록합니다. main에서 이 워커를 시작, 중지 할 수 있습니다.

5. main에 활성화 코드 추가

if (process.env.NODE_ENV === 'development') { import('./mocks/browser').then(({ worker }) => { worker.start().then(() => { console.log('MSW가 활성화되었습니다. API 요청이 모킹됩니다.'); }); }); }

main에 해당 코드를 추가하면, 개발 환경 확인후 동적으로 import하고 워커를 시작합니다.

그리고 희망차게 npm run dev를 했을 때 로그인 기능이 성공적으로 통과되고 홈화면이 나오길 빌었으나 실패했습니다

[MSW] Warning: intercepted a request without a matching request handler:

생각해보니, api문서에 모든 url의 앞부분에 /api 가 붙어 있어 baseUrl을 /api로 이미 작성 해 두었는데, useKaKaoLogin에 인자로 들어가는 Url에 /api/login 으로 작성해 두었습니다.

즉, 이번 msw 코드는 정상적으로 /api/login을 호출하는데 원 코드가 /api/api/login url로 post하고 있었습니다. msw 코드를 작성하며 기존 코드의 문제점을 파악할 수 있는 놀라운 경험…!

이를 수정하고 다시 npm run dev를 해보았을 때,

원래는 백엔드가 연결이 안되어있어서 1000ms 초과로 로그인 후 다시 오류표시 및 다시 로그인 페이지로 이동하는데

image.png

이제는 msw 를 통해 로그인이 성공하고 홈 화면으로 이동하게 되었습니다.

이제 백엔드와의 진도차이에도 충분히 개발을 진행할 수 있고, 추후 여러 api응답 시나리오 테스트도 진행할 수 있습니다.