MSW๋ Mocking Service Worker์ ์ฝ์๋ก, ๋ง ๊ทธ๋๋ก service worker๋ฅผ ์ด์ฉํด ๊ฐ์ง api๋ฅผ mockingํ๋ ๋๊ตฌ์ด๋ค.
์ฆ, ๋ธ๋ผ์ฐ์ ์ ์กด์ฌํ๋ฉฐ ์ค์ ๋ฐฑ์ค๋์ฒ๋ผ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ์ญํ ์ ํ๋ค.
"๊ฐ์ง ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ์ ์๊ฒ ํด์ฃผ๋ ๋๊ตฌ๋ผ๊ณ ๋ณผ ์ ์๋ค."
ํ๋ก์ ํธ ์งํ์, ๋ฐฑ์๋ ๊ฐ๋ฐ์ ์ข ์์ ์ธ ๋ถ๋ถ์ด ์๋ค๋ฉด ํด๋น ๋ถ๋ถ์ด ์์ฑ๋๊ธฐ ์ ๊น์ง๋ ํ๋ก ํธ์์๋ ๊ฐ๋ฐ์ ์งํํ ์ ์๊ณ , API๊ฐ ์๋ ์ํ์ด๊ธฐ ๋๋ฌธ์ ๊ทธ ์๊ฐ ๋งํผ ๋ง๋ฅ ๊ธฐ๋ค๋ ค์ผ ํ ์๋ ์๋ค.
MSW๋ฅผ ํ์ฉํ๋ฉด API๊ฐ ๊ฐ๋ฐ๋๊ธฐ ์ , ๋ฐฑ์๋์ ์ญํ ์ '๊ฐ์ง'๋ก ๋์ ํด์ฃผ๊ธฐ ๋๋ฌธ์ ํ๋ก ํธ์ ๊ฐ๋ฐ์ด ์ ์๊ฐ ์์ ๋๋ ์ ์๋ค.
MSW๋ ์๋ฒ์ ๋คํธ์ํฌ ์์ฒญ์ ๊ฐ๋ก์ฑ ๋ชจ์ ์๋ต์ ๋ณด๋ด์ฃผ๋ ์ญํ ์ ํ๋ค.
MSW๊ฐ ์ด๋ฌํ ์ญํ ์ ํ ์ ์๋ ์ด์ ๋ Service Worker๋ฅผ ํตํด HTTP ์์ฒญ์ ๊ฐ๋ก์ฑ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ด ๊ณผ์ ์์ ์ค์ ์๋ฒ ์กด์ฌ ์ฌ๋ถ์ ์๊ด ์์ด ์ค์ ์์ฒญ์ด ์ด์ด์ง์ง ์๊ณ , ์์ ๊ฐ๋ฅํ ์์ฒญ์ ๋ํด mocking์ด ๊ฐ๋ฅํด์ง๋ค.
service worker๋ ์น ์ดํ๋ฆฌ์ผ์ด์ ์ ๋ฉ์ธ ์ค๋ ๋์ ๋ถ๋ฆฌ๋ ๋ณ๋์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋์์ ์คํ์ํฌ ์ ์๋ ๊ธฐ์ ์ค ํ๋์ด๋ค. service worker ๋๋ถ์ ์ดํ๋ฆฌ์ผ์ด์ ์ ui block ์์ด๋ ์ฐ์ฐ์ ์ฒ๋ฆฌํ ์ ์๋ค.
service worker์ ๊ธฐ๋ฅ ์ค ํ๋๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ์๋ฒ ์ฌ์ด์์ request๋ฅผ ๊ฐ๋ก์ฑ ์ง์ fetch์ ๋ํ ์ปจํธ๋กค์ ํ๊ณ , ์๋ค๋ฅธ ์์ ์ ํ๋ ๊ฒ์ด๋ค.
1. ๋ชฉ๋ฐ์ดํฐ ์์ฑ - ๋ฐฑ์๋์์ ์ฌ api์ ๋น์ทํ ํํ๋ฅผ ๊ฐ์ถ ๋ชฉ๋ฐ์ดํฐ๊ฐ ํ์ํ๋ค.
- ๋๋ ๋ง์ดํ์ด์ง, ํ์๊ฐ์
, ๋ก๊ทธ์ธ ํ์ด์ง์์ ํ์ํ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ์์ฑํ๋ค.
export const userList = [
{
id: 1,
email: "example@naver.com",
password: "1234",
nickname: "aaa",
name: "์ฌ์ฌ์",
phoneNum: "010-1111-1111",
address: "์์ธ์ ์ฑ๋๊ตฌ ์ฑ์๋",
degree: 36.5,
profileImg: FAKEPROFILE,
aboutMe: "์๊ธฐ์๊ฐ ํ์ด์ง์
๋๋ค. ๋ ํํธ๋ก ์ ์ ํ์๋ฉด ํผํํธ.",
registerProducts: [
{
id: 0,
},
],
boughtProducts: [
{
id: 11,
},
],
likeProducts: [
{
id: 22,
},
],
},
{
id: 0,
email: "test@naver.com",
password: "1234",
nickname: "bbb",
name: "ํ
์คํธ",
phoneNum: "010-1234-1234",
address: "์์ธ์ ์ฑ๋๊ตฌ ์ฑ์๋",
degree: 36.5,
profileImg: FAKEPROFILE,
aboutMe: "์๊ธฐ์๊ฐ ํ์ด์ง์
๋๋ค. ๋ ํํธ๋ก ์ ์ ํ์๋ฉด ํผํํธ.",
registerProducts: [],
likeProducts: [],
boughtProducts: [],
},
];
2. api ์์ฒญ ๋ก์ง ์์ฑ
import { userList } from "mock/userList";
import { rest } from "msw";
// get => /users๋ผ๋ ์ฃผ์๋ก , userList๋ผ๋ ๋ชฉ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์์ค๋ค.
export const getUsers = rest.get("/users", async (req, res, ctx) => {
return res(ctx.status(200), ctx.json(userList));
});
// post => /users๋ผ๋ ์ฃผ์๋ก ๋ฐ์ดํฐ ์ถ๊ฐ (ํ์๊ฐ์
์ด๋ ๋ก๊ทธ์ธ์ ์ถ๊ฐ๋๋ ?>
export const addUser = rest.post("/users", async (req, res, ctx) => {
// ๊ฐ์
์ ๋ฐ์์์ผ ํ๋ ์ ๋ณด๋ค ๋ณ์๋ก ์์ฑ
let email;
let password;
let nickname;
let name;
let phoneNum;
let address;
// ๊ธฐ์กด์ ๋ฐ์ดํฐ ์์ฑ์ ์ถ๊ฐํด์ฃผ๊ธฐ (์๋ก ๋ฐ์์ค๋ ๊ฑธ)
await req.json().then(data => {
email = data.email;
password = data.password;
nickname = data.nickname;
name = data.name;
phoneNum = data.phoneNum;
address = data.address;
});
// ์๋ก ๋ฐ์์จ ๋ฐ์ดํฐ + ์๋ก ๋ฐ์ง ์๋ ๋ฐ์ดํฐ (userList๋ชฉ๋ก์ค)๋ฅผ
// ๋ชจ๋ ํฉ์ณ์ ํ๋์ ๋ชฉ๋ฐ์ดํฐ๊ฐ ๋ ์์ฑ๋๋ ๊ฒ .
return res(
ctx.status(200),
ctx.json({
id: Math.floor(Math.random() * 100000),
email,
password,
nickname,
name,
phoneNum,
address,
degree: 36.5,
profileImg: null,
aboutMe: "์์ ์ ์๊ฐํด์ฃผ์ธ์",
registerProducts: [],
boughtProducts: [],
likeProducts: [],
}),
);
});
// ๋ฐ์ดํฐ ์์
// ๋ง์ดํ์ด์ง ์ ๋ณด ์์ ๋ ์ฌ์ฉ๋๋ค. ํ๋ํ๋ ์ผ์ผ์ด ์์ ํ ์ ์๋๋ก ์ง์ธ ๊ตฌ์กฐ์ด๊ธฐ ๋๋ฌธ์
// ํ๋์ ํจ์๋ก ๋ง๋ค์ด์ค๋ค.
const updateUser = key => {
return rest.patch("/user/:id", async (req, res, ctx) => {
const { id } = req.params;
const editedData = { id : parseInt(id) };
await req.json().then(data => {
editedData[`${key}`] = data[`${key}`];
});
return res(ctx.status(200), ctx.json(editedData));
})
})
export const updateUserEmail = updateUser("email");
export const updateUserPassword = updateUser("password");
export const updateUserNickname = updateUser("nickname");
export const updateUserName = updateUser("name");
export const updateUserPhoneNum = updateUser("phoneNum");
export const updateUserAddress = updateUser("address");
export const updateUserAboutMe = updateUser("aboutMe");
export const updateUserProfileImg = updateUser("profileImg");
3. Service Worker ์์ฑ
// handler.js
import { setupWorker } from "msw";
import * as userApi from "../apis/user.api.js";
const handlers = [
...Object.values(userApi),
];
export const worker = setupWorker(...handlers);
4. ๋ธ๋ผ์ฐ์ ์์ service worker ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋๋ก ์ฝ์
ํด์ค๋ค. (react + js์์๋ ๋ฃจํธ์ ์์นํ index.js)
import { worker } from "mocks/handlers";
if (process.env.NODE_ENV === "development") {
worker.start();
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>,
);
5. ์ด์ axios๋ fetch ๋ฑ ๋ฐ์ดํฐ ์์ฒญ ๋ก์ง์ ์ฌ์ฉํ์ฌ ์คํํด ๋ฐ์ดํฐ๊ฐ ์ค๋์ง ํ์ธํ๋ฉด ๋๋ค.
const Main = () => {
useEffect(() => {
axios.get("/users").then(res => console.log(res.data));
}, []);
return (
<></>
)
}