API 통신을 어떻게 구현할지 고민하던 중, 우아콘에서 봤던 MSW가 생각이 났다.
MSW는 백엔드 API가 구현되기 전, 프론트에서 사용할 Mockup 용으로 주로 이용된다.
MSW로 API와 통신하는 척을 할 수 있고, 요청 응답을 자유롭게 커스텀할 수 있어 이번 프로젝트에 채택하게 되었다.
MSW 공식 도큐먼트와 함께 사용법을 따라가보자.
1. 설치
npm install msw --save-dev
2. 초기화
npx msw init public/ --save
브라우저에서 MSW를 사용할 수 있도록 서비스 워커를 등록하는 커맨드
`npx msw init <PUBLIC_DIR>`
public 폴더의 주소를 적어주고, `mockServiceWorker.js`를 저장하기 위해 `--save`옵션을 추가한다.
2. 핸들러 등록
// src/mocks/handlers.ts
export const handlers = [];
// src/mocks/browsers.ts
import { setupWorker } from 'msw/browser';
import { handlers } from './handlers';
export const worker = setupWorker(...handlers);
handler.ts는 intercept할 API들의 요청과 응답을 작성하는 곳이다. 작성법은 후술하겠다.
browsers.ts는 작성한 핸들러가 브라우저에서 동작할 수 있도록 설정하는 파일이다.
3. 서비스 워커 활성화
마지막으로 서비스 워커를 등록하고 활성화해준다.
서비스 워커 등록이 비동기 작업이므로, async/await을 사용해 앱 렌더링을 연기하는 게 좋다고 한다.
// index.ts
const root = document.getElementById('root') as HTMLElement;
async function enableMocking() {
const { worker } = await import('./mocks/browser');
return worker.start();
}
enableMocking().then(() => {
ReactDOM.createRoot(root).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
});
4. 핸들러 작성
MSW에서 제공하는 http 메소드를 이용해 쉽게 CRUD를 구현할 수 있다.
// src/mocks/handlers.ts
const todos: Array<ToDoDTO> = [
{
id: 1,
text: 'TO DO LIST를 만들어보자!',
checked: true
}
];
export const handlers = [
http.get<never, never, Array<ToDoDTO>>('/todos', () => {
return HttpResponse.json(todos);
}),
http.post<never, ToDoDTO>('/todos', async ({ request }) => {
const data = await request.json();
const nextId = Math.max(...todos.map(todo => todo.id)) + 1;
todos.unshift({
id: nextId,
text: data.text,
checked: false
});
return new HttpResponse(null, { status: 201 });
}),
http.patch<UpdateToDoParams, ToDoDTO>('/todos/:id', async ({ params, request }) => {
const data = await request.json();
const findItem = todos.find(({id}) => id === Number(params.id));
if (!findItem) {
return new HttpResponse(null, { status: 404 });
}
findItem.checked = data.checked;
return new HttpResponse(null, { status: 204 });
}),
http.delete<UpdateToDoParams>('/todos/:id', async ({ params }) => {
const findItemIdx = todos.findIndex(({id}) => id === Number(params.id));
if (0 > findItemIdx) {
return new HttpResponse(null, { status: 404 });
}
todos.splice(findItemIdx, 1);
return new HttpResponse(null, { status: 200 });
})
];
5. 사용
handler에 등록한 path와 메소드를 조합하여 호출하면 성공적으로 응답을 받을 수 있다.
const fetchTodo = async () => {
try {
const res = await axios.get('/todos');
setToDos(res.data);
} catch (e) {
console.error('error', e);
}
};
Safari 이슈
axios와 msw를 동시에 사용했는데, Safari 환경에서 AxiosError - 'Request failed with status code 404' 오류가 발생하였다.
msw2.0으로 업데이트 된 지 얼마 안되어 정보가 많이 없어 오류를 고치지 못했다. (버전 자체에 버그가 많기도 하다..)
msw 깃헙과 디스코드에도 문의했지만 아직 답변을 받지 못했는데, 혹시 해결방법이나 제 코드에 문제가 있다면 얘기 부탁드립니다🥲
'PROJECT > TO DO LIST' 카테고리의 다른 글
React로 만든 TO DO LIST (0) | 2024.03.21 |
---|---|
React, styled-components 환경에서 폰트 적용하기 (0) | 2024.01.13 |