MSW ์ •๋ณตํ•˜๊ธฐ ๐Ÿค“๐Ÿ–ฅ๏ธ

๋ฐ•ํฌ์ˆ˜ยท2023๋…„ 11์›” 9์ผ
0
post-thumbnail

MSW๋ž€?

MSW๋Š” Mocking Service Worker์˜ ์•ฝ์ž๋กœ, ๋ง ๊ทธ๋Œ€๋กœ service worker๋ฅผ ์ด์šฉํ•ด ๊ฐ€์งœ api๋ฅผ mockingํ•˜๋Š” ๋„๊ตฌ์ด๋‹ค.
์ฆ‰, ๋ธŒ๋ผ์šฐ์ €์— ์กด์žฌํ•˜๋ฉฐ ์‹ค์ œ ๋ฐฑ์•ค๋“œ์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
"๊ฐ€์งœ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋„๊ตฌ๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค."

๐Ÿค” ๋ฐฑ์—”๋“œ๊ฐ€ ์žˆ๋Š”๋ฐ ์™œ MSW๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฑธ๊นŒ?

ํ”„๋กœ์ ํŠธ ์ง„ํ–‰์‹œ, ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์— ์ข…์†์ ์ธ ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ๋ถ€๋ถ„์ด ์™„์„ฑ๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ํ”„๋ก ํŠธ์—์„œ๋Š” ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์—†๊ณ , API๊ฐ€ ์—†๋Š” ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ์‹œ๊ฐ„ ๋งŒํผ ๋งˆ๋ƒฅ ๊ธฐ๋‹ค๋ ค์•ผ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
MSW๋ฅผ ํ™œ์šฉํ•˜๋ฉด API๊ฐ€ ๊ฐœ๋ฐœ๋˜๊ธฐ ์ „, ๋ฐฑ์—”๋“œ์˜ ์—ญํ• ์„ '๊ฐ€์งœ'๋กœ ๋Œ€์‹  ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋ก ํŠธ์˜ ๊ฐœ๋ฐœ์ด ์ œ์‹œ๊ฐ„ ์•ˆ์— ๋๋‚  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ›ด MSW ๋™์ž‘ ๋ฐฉ์‹

MSW๋Š” ์„œ๋ฒ„์˜ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑ„ ๋ชจ์˜ ์‘๋‹ต์„ ๋ณด๋‚ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
MSW๊ฐ€ ์ด๋Ÿฌํ•œ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๋Š” Service Worker๋ฅผ ํ†ตํ•ด HTTP ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑŒ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด ๊ณผ์ •์—์„œ ์‹ค์ œ ์„œ๋ฒ„ ์กด์žฌ ์—ฌ๋ถ€์™€ ์ƒ๊ด€ ์—†์ด ์‹ค์ œ ์š”์ฒญ์ด ์ด์–ด์ง€์ง€ ์•Š๊ณ , ์˜ˆ์ƒ ๊ฐ€๋Šฅํ•œ ์š”์ฒญ์— ๋Œ€ํ•ด mocking์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

Service Worker๋ž€?

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 (
					<></>
		)
}
profile
ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž์ž…๋‹ˆ๋‹ค :)

0๊ฐœ์˜ ๋Œ“๊ธ€