개발 중인 API 홈페이지 리액트 프로젝트에 API 모킹 라이브러리인 MSW를 적용해보았다.
API 모킹의 필요한 이유
현재 AID 홈페이지 리뉴얼 프로젝트는 한창 개발이 진행 중이다. 프론트엔드에서 api 요청을 테스트하기 위해서는 로컬에 백엔드의 코드를 다운받고 실행시켜 로컬 네트워크에서 테스트해야 한다. 여기서 불편함이 느껴졌다.
백엔드 개발자들이 Docker로 잘 말아서 올려주었지만 매번 API를 테스트할 때마다 백엔드 프로젝트를 열어서 도커 명령어를 실행시킨 후, 테스트 종료 후에는 다시 도커 명령어를 입력해주어야 해서 번거로웠다. 그리고 로컬에서 리액트 프로젝트와 장고+도커 프로젝트를 동시에 실행시켜야 했기에 노트북의 배터리도 빠르게 녹아갔다. 마지막으로 백엔드의 DB 구조나 api url 같은 것들이 자주 바뀌었지만 그것을 PR을 올리고 Merge 후 내가 다시 Pull 받는 과정도 번거로웠다.
이런 불편함을 느끼고 API 모킹의 필요성을 절실히 느꼈다. 실 서버와의 차이는 있겠지만 api 요청 콜에 간단한 데이터 응답만 돌려받으면 됐기에 복잡하게 할 필요도 없었다. 그래서 MSW를 도입하기로 결정했다.
MSW 사용방법은 그냥 공식문서를 보는 것이 짱이다:) https://mswjs.io/
MSW 마이그레이션
1. yarn add msw
2. src/mocks/handlers.ts 및 src/mocks/browser.ts 작성
// src/mocks/handlers.ts
import { http, HttpResponse } from 'msw';
import { qnaCategoryList } from '../data/qna-data';
export const handlers = [
http.post('/api/auth', () => {
// Note that you DON'T have to stringify the JSON!
return HttpResponse.json({
user: {
id: 'abc-123',
name: 'John Maverick',
},
});
}),
http.get('/api/study', () => {
return HttpResponse.json({
studyList: [
{
id: 123,
name: '밑바닥부터 시작하는 딥러닝',
},
{
id: 124,
name: '혼자 공부하는 머신러닝',
},
{
id: 125,
name: '강화학습 스터디',
},
],
});
}),
http.get('/api/qna/category', () => {
return HttpResponse.json(qnaCategoryList);
}),
];
// src/mocks/browser/ts
import { setupWorker } from 'msw/browser';
import { handlers } from './handlers';
export const worker = setupWorker(...handlers);
3. yarn msw init public/ --save
모킹을 위한 Service Worker 파일 생성. 수정하지 않을 것을 권장.
4. main.tsx에서 호출
// src/main.tsx
/**
* 개발 모드(DEV)일 때만, api 모킹 처리 로직을 킨다.
* msw: api 모킹을 위한 라이브러리
* worker: 클라이언트에서 요청하는 api를 네트워크단에서 가로채는 Service Worker를 등록하는 객체
*/
async function enableMocking() {
// 백엔드에 직접 api 요청을 날리고 싶다면, 아래 주석을 해제하라.
// return;
if (import.meta.env.PROD) {
return;
}
const { worker } = await import('./mocks/browser');
// `worker.start()` returns a Promise that resolves
// once the Service Worker is up and ready to intercept requests.
return worker.start();
}
enableMocking().then(() => {
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<RouterProvider router={routers} />
</React.StrictMode>
);
});
Vite 기반의 리액트 프로젝트였고 MSW 공식문서를 따라 설치를 무사히 마쳤다. 그러나 여러 에러가 발생하면서 골머리를 앓았다.
트러블 슈팅
1. Service Worker script does not exist at the given path.
이 문제는 AID 깃허브 URL이 'https://pnu-aid.github.io/homepage/'로 'homepage'가 붙어서 발생한 것이다. 프론트엔드를 github.io로 배포하기 위해선 (1) 레포 이름을 변경하거나 (2) 배포하는 URL을 변경하는 수 밖에 없다. 우리는 후자를 택했었고 이 상황에서 mockServiceWorker.js를 호출하기 위해선 /homepage/mockServiceWorker.js로 호출해야 했다.
async function enableMocking() {
// 백엔드에 직접 api 요청을 날리고 싶다면, 아래 주석을 해제하라.
// return;
if (import.meta.env.PROD) {
return;
}
const { worker } = await import('./mocks/browser');
// `worker.start()` returns a Promise that resolves
// once the Service Worker is up and ready to intercept requests.
// HERE: url에 배포할 URL을 직접 지정해주었다.
return worker.start({
serviceWorker: {
url: '/homepage/mockServiceWorker.js',
}
});
}
2. api 호출 에러
Service Worker의 url을 정확하게 지정해줌으로써, "Mocking enabled"가 나타났지만 막상 api 호출 시 에러가 터졌다. 요청을 날렸지만 못 받아온다. handlers의 문제라 생각했고 MSW 세팅 때와 마찬가지로 url 앞에 '/homepage'를 붙여야만 정상적으로 api 호출 콜을 받을 수 있었다.
http.get('/homepage/api/qna/category', () => {
return HttpResponse.json(qnaCategoryList);
}),
결과
api 모킹이 정상적으로 동작하는 모습을 확인할 수 있었다. api 모킹 테스트를 통해 디벨롭하여 리액트 쿼리의 캐싱까지 적용할 수 있을 것 같다.
'프로젝트 > 인공지능 동아리, AID' 카테고리의 다른 글
[AID] Zero-shot 기반의 채용공고 필터링 디스코드 훅 (0) | 2024.03.11 |
---|---|
AID 모각코 다녀옴 (0) | 2024.01.23 |
[팀프로젝트] AID 홈페이지 리뉴얼 - (2) 코드 가독성을 높이기 위한 전략 (1) | 2023.12.28 |
[팀프로젝트] AID 홈페이지 리뉴얼 - (1) 기획 및 큰 틀 구현 (0) | 2023.12.16 |