πŸ‘©β€πŸ’»
Megaptera Frontend
  • 주차별 ν•™μŠ΅
    • megaptera-front
    • 1. 개발 ν™˜κ²½
      • 1. 개발 ν™˜κ²½
      • 2. TypeScript
      • 3. React
      • 4. Testing Library
      • 5. Parcel & ESLint
      • ν•œ μ£Όλ₯Ό 마치며
    • 2. JSX
      • 1. JSX
      • ν•œ μ£Όλ₯Ό 마치며
    • 3. React둜 μ‚¬κ³ ν•˜κΈ°
      • 1. React Component
      • 2. React State
      • ν•œ μ£Όλ₯Ό 마치며
    • 4. React Hooks
      • 1. Express
      • 2. Fetch API & CORS
      • 3. React의 Hook
      • 4. useRef & Custom Hook
      • 5. usehooks-ts
      • ν•œ μ£Όλ₯Ό 마치며
    • 5. ν…ŒμŠ€νŠΈ
      • 1. TDD
      • 2. React Testing Library
      • 3. MSW
      • 4. Playwright
      • ν•œ μ£Όλ₯Ό 마치며
    • 6. External Store
      • 1. External Store
      • 2. TSyringe
      • 3. Redux λ”°λΌν•˜κΈ°
      • 4. usestore-ts
      • ν•œ μ£Όλ₯Ό 마치며
    • 7. React Router
      • 1. Routing
      • 2. Routes
      • 3. Router
      • 4. Navigation
      • ν•œ μ£Όλ₯Ό 마치며
    • 8. CSS in JS
      • 1. Design System
      • 2. Style Basics
      • 3. CSS in JS
      • 4. styled-components
      • 5. props와 attrs
      • 6. Global Style & Theme
      • ν•œ μ£Όλ₯Ό 마치며
    • 9. μ‡Όν•‘λͺ° λͺ©λ‘, μƒν’ˆ νŽ˜μ΄μ§€
      • 1. κ°œλ°œν•˜κΈ° μ „ μ€€λΉ„
      • 2. λͺ©λ‘ 보기
      • 3. μƒν’ˆ 상세 보기
      • 4. μž₯λ°”κ΅¬λ‹ˆ 보기
      • 5. μž₯λ°”κ΅¬λ‹ˆμ— μƒν’ˆ λ‹΄κΈ°
      • ν•œ μ£Όλ₯Ό 마치며
    • 10. μ‚¬μš©μž 인증, 인가
      • 1. 둜그인
      • 2. λ‘œκ·Έμ•„μ›ƒ
      • 3. νšŒμ›κ°€μž…
      • 4. μ£Όλ¬Έ λͺ©λ‘ & μ£Όλ¬Έ 상세
      • ν•œ μ£Όλ₯Ό 마치며
    • 11. μ£Όλ¬Έ, 결제
      • 1. 배솑 정보 μž…λ ₯
      • 2. ν¬νŠΈμ› 결제 μš”μ²­
      • 3. 배솑 및 결제 정보 전달
      • ν•œ μ£Όλ₯Ό 마치며
    • 12. μ–΄λ“œλ―Ό
      • 1. κ΄€λ¦¬μž μ›Ή μ‚¬μ΄νŠΈ 개발 μ‹œμž‘
      • 2. 둜그인, μ‚¬μš©μž λͺ©λ‘
      • 3. μΉ΄ν…Œκ³ λ¦¬ 관리
      • 4. μ£Όλ¬Έ 관리
      • 5. μƒν’ˆ 관리
      • ν•œ μ£Όλ₯Ό 마치며
Powered by GitBook
On this page
  • 1. Service Worker
  • νŠΉμ§•
  • μ›Ή μ›Œμ»€ vs μ„œλΉ„μŠ€ μ›Œμ»€
  • 2. MSW(Mock Service Worker)
  • μ‚¬μš© 방법
  • 3. REST API λͺ¨ν‚Ήν•˜κΈ°
  • 폴더 ꡬ쑰
  • handlers.ts 파일 μž‘μ„±
  • App.test.ts 파일 μˆ˜μ •
  • 주의점 & polyfill μ΄μš©ν•˜κΈ°
  • 3. polyfill(폴리필)
  1. 주차별 ν•™μŠ΅
  2. 5. ν…ŒμŠ€νŠΈ

3. MSW

Previous2. React Testing LibraryNext4. Playwright

Last updated 2 years ago

1. Service Worker

μ„œλΉ„μŠ€ μ›Œμ»€λŠ” μ›Ή μ‘μš© ν”„λ‘œκ·Έλž¨, λΈŒλΌμš°μ €, 그리고 (μ‚¬μš© κ°€λŠ₯ν•œ 경우) λ„€νŠΈμ›Œν¬ μ‚¬μ΄μ˜ ν”„λ‘μ‹œ μ„œλ²„ 역할을 함

νŠΉμ§•

  • 효과적인 μ˜€ν”„λΌμΈ κ²½ν—˜μ„ 생성

  • λ„€νŠΈμ›Œν¬ μš”μ²­μ„ κ°€λ‘œμ±„μ„œ λ„€νŠΈμ›Œν¬ μ‚¬μš© κ°€λŠ₯ 여뢀에 따라 μ μ ˆν•œ 행동을 취함

  • μ„œλ²„μ˜ μžμ‚°μ„ μ—…λ°μ΄νŠΈ

  • ν‘Έμ‹œ μ•Œλ¦Όκ³Ό λ°±κ·ΈλΌμš΄λ“œ 동기화 API둜의 접근도 제곡

  • λ³΄μ•ˆ μƒμ˜ 이유둜 HTTPSμ—μ„œλ§Œ λ™μž‘

    • λ„€νŠΈμ›Œν¬ μš”μ²­μ„ μˆ˜μ •ν•  수 μžˆλ‹€λŠ” μ μ—μ„œ μ€‘κ°„μž 곡격에 ꡉμž₯히 μ·¨μ•½ν•˜κΈ° λ•Œλ¬Έ

μ›Ή μ›Œμ»€ vs μ„œλΉ„μŠ€ μ›Œμ»€

곡톡점

  • μ›Ή μ‚¬μ΄νŠΈμ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” μ›Œμ»€

  • λ‘˜ λ‹€ 보쑰 μŠ€λ ˆλ“œμ—μ„œ μ‹€ν–‰λ˜λ―€λ‘œ κΈ°λ³Έ μŠ€λ ˆλ“œμ™€ μ‚¬μš©μž μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ°¨λ‹¨ν•˜μ§€ μ•Šκ³  JavaScript μ½”λ“œλ₯Ό μ‹€ν–‰(λ…Ό λΈ”λ‘œν‚Ή)

  • Window 및 Document objects에 λŒ€ν•œ μ•‘μ„ΈμŠ€ κΆŒν•œμ΄ μ—†μœΌλ―€λ‘œ, DOMκ³Ό 직접 μƒν˜Έ μž‘μš©ν•  수 μ—†μœΌλ©°(DOM에 μ ‘κ·Ό λΆˆκ°€) λΈŒλΌμš°μ € API에 λŒ€ν•œ μ•‘μ„ΈμŠ€κ°€ μ œν•œλ¨

차이점

차이점
μ›Ή μ›Œμ»€
μ„œλΉ„μŠ€ μ›Œμ»€

수λͺ…

μ›Ή μ›Œμ»€κ°€ μ†ν•œ νƒ­κ³Ό λ°€μ ‘ν•˜κ²Œ μ—°κ²°

독립적

νƒ­ μ’…λ£Œ μ‹œ

μ’…λ£Œλ¨

λ°±κ·ΈλΌμš΄λ“œμ—μ„œ 계속 μ‹€ν–‰ κ°€λŠ₯

갯수

μ—¬λŸ¬ μ›Ή μ›Œμ»€ 생성 κ°€λŠ₯

λ“±λ‘λœ λ²”μœ„μ˜ λͺ¨λ“  ν™œμ„± 탭을 μ œμ–΄

λ„€νŠΈμ›Œν¬ μš”μ²­

-

λ„€νŠΈμ›Œν¬ μš”μ²­μ„ κ°€λ‘œμ±”(fetch이벀트λ₯Ό 톡해), λ°±κ·ΈλΌμš΄λ“œμ—μ„œ ν‘Έμ‹œ API 이벀트λ₯Ό μˆ˜μ‹ 

  • μ›Ή μ›Œμ»€μ˜ 수λͺ…은 μ›Ή μ›Œμ»€κ°€ μ†ν•œ νƒ­κ³Ό λ°€μ ‘ν•˜κ²Œ μ—°κ²°λ˜μ–΄ μžˆλŠ” 반면, μ„œλΉ„μŠ€ μ›Œμ»€μ˜ 수λͺ… μ£ΌκΈ°λŠ” 독립적 μ›Ή μ›Œμ»€κ°€ μ‹€ν–‰ 쀑인 탭을 λ‹«μœΌλ©΄ μ’…λ£Œλ˜μ§€λ§Œ, μ„œλΉ„μŠ€ μ›Œμ»€λŠ” μ‚¬μ΄νŠΈμ— μ—΄λ € μžˆλŠ” ν™œμ„± 탭이 μ—†λŠ” κ²½μš°μ—λ„ λ°±κ·ΈλΌμš΄λ“œμ—μ„œ 계속 μ‹€ν–‰ κ°€λŠ₯

  • νŽ˜μ΄μ§€λŠ” μ—¬λŸ¬ μ›Ή μ›Œμ»€λ₯Ό 생성할 수 μžˆμ§€λ§Œ, 단일 μ„œλΉ„μŠ€ μ›Œμ»€λŠ” λ“±λ‘λœ λ²”μœ„μ˜ λͺ¨λ“  ν™œμ„± 탭을 μ œμ–΄

  • μ›Ή μ›Œμ»€μ™€ 달리 μ„œλΉ„μŠ€ μ›Œμ»€λ₯Ό μ‚¬μš©ν•˜λ©΄ fetch이벀트λ₯Ό 톡해 λ„€νŠΈμ›Œν¬ μš”μ²­μ„ κ°€λ‘œμ±„κ³ , λ°±κ·ΈλΌμš΄λ“œμ—μ„œ push이벀트λ₯Ό 톡해 Push API 이벀트λ₯Ό μˆ˜μ‹ 

2. MSW(Mock Service Worker)

express 보닀 쑰금 λΆˆνŽΈν•¨ μ½”λ“œ 레벨이 μ•„λ‹ˆλΌ λ„€νŠΈμ›Œν¬ λ ˆλ²¨μ—μ„œ κ°€μ§œ κ΅¬ν˜„(ν”„λ‘μ‹œλ₯Ό 이용) μ˜€ν”„λΌμΈ μž‘μ—… 등을 μ§€μ›ν•˜κΈ° μœ„ν•œ μ„œλΉ„μŠ€ μ›Œμ»€μ˜ κΈ°λŠ₯을 μœ μš©ν•˜κ²Œ ν™œμš©ν•œ 것 Node, λΈŒλΌμš°μ € λ‘˜ λ‹€ 지원

πŸ₯Š Express vs MSW

λ‹¨μˆœνžˆ μž„μ‹œ μ„œλ²„λ₯Ό λ§Œλ“€ 거라면 Expressλ₯Ό μ“°λŠ” 게 더 λ‚«μ§€λ§Œ, MSWλŠ” ν…ŒμŠ€νŠΈ μ½”λ“œλ„ μ§€μ›ν•˜λ©΄μ„œ 겸사겸사 μ›Ή λΈŒλΌμš°μ €λ₯Ό μ§€μ›ν•˜λŠ” μš©λ„λ‘œλŠ” λ‚˜μ˜μ§€ μ•Šμ€ 선택

MSWλŠ” jest의 ν…ŒμŠ€νŠΈ ν™˜κ²½(Node.js 기반) 외에 μ›Ή λΈŒλΌμš°μ €λ„ 지원 API μŠ€νŽ™μ€ λ‚˜μ™”μ§€λ§Œ 아직 κ΅¬ν˜„λ˜μ§€ μ•Šμ€ 경우 μž„μ‹œλ‘œ μ‚¬μš©ν•  수 있음

μ‚¬μš© 방법

1. MSW νŒ¨ν‚€μ§€ μ„€μΉ˜

npm i -D msw

2. server.ts 파일 생성

src/mocks/server.ts κ²½λ‘œμ— 생성

// src/mocks/server.ts

import {setupServer} from 'msw/node';

// Import handlers from './handlers';

const handlers = []; // μž„μ‹œλ‘œ 적어둠 

// This configures a request mocking server with the given request handlers.
const server = setupServer(...handlers);

export default server;
// src/setupTests.ts

import server from './mocks/server.ts';
// Establish API mocking before all tests.
beforeAll(() => server.listen({onUnhandledRequest: 'error'}));

// Reset any request handlers that we may add during the tests,
// so they don't affect other tests.
afterEach(() => server.resetHandlers());

// Clean up after the tests are finished.
afterAll(() => server.close());
  • beforeAll : Jest μ‹œμž‘ν•  λ•Œ 맨 μ²˜μŒμ— μ‹€ν–‰

    • onUnhandledRequest: 'error' : handlerλ₯Ό μ•ˆ μž‘μ•˜μ„ λ•Œ 였λ₯˜ 내도둝 μ„€μ •

  • afterEach : 각 ν…ŒμŠ€νŠΈκ°€ 끝날 λ•Œλ§ˆλ‹€ μ‹€ν–‰

  • afterAll : μ „λΆ€ 끝날 λ•Œ μ‹€ν–‰

3. jest.config.js 파일의 β€œsetupFilesAfterEnv” 속성에 setupTests.ts 파일 μΆ”κ°€

// jest.config.js

module.exports = {
    testEnvironment: 'jsdom',
    setupFilesAfterEnv: [
        '@testing-library/jest-dom/extend-expect',
        '<rootDir>/src/setupTests.ts',
    ],
    transform: {
        '^.+\\.(t|j)sx?$': ['@swc/jest', {
            jsc: {
                parser: {
                    syntax: 'typescript',
                    jsx: true,
                    decorators: true,
                },
                transform: {
                    react: {
                        runtime: 'automatic',
                    },
                },
            },
        }],
    },
};

3. REST API λͺ¨ν‚Ήν•˜κΈ°

⚠️ λ„ˆλ¬΄ 본격적으둜 μ½”λ”©ν•˜λ©΄ 사싀상 λ°±μ—”λ“œλ₯Ό κ°œλ°œν•˜κ²Œ λ˜λ‹ˆ, 이 뢀뢄에 μ£Όμ˜ν•  것

폴더 ꡬ쑰

β”œβ”€β”€ package.json
β”œβ”€β”€ package-lock.json
β”œβ”€β”€ jest.config.js βœ…
β”œβ”€β”€ src
β”‚   β”œβ”€β”€ main.tsx
β”‚   β”œβ”€β”€ App.tsx
β”‚   β”œβ”€β”€ App.test.tsx βœ…
β”‚   β”œβ”€β”€ setupTests.ts βœ…
β”‚   β”œβ”€β”€ components πŸ“
β”‚   β”œβ”€β”€ hooks πŸ“
β”‚   β”œβ”€β”€ mocks πŸ“
β”‚   β”‚   β”œβ”€β”€ handlers.ts βœ…
β”‚   β”‚   └── server.ts βœ…

handlers.ts 파일 μž‘μ„±

μ§„μ§œκ°™μ€ 것이지 μ§„μ§œκ°€ μ•„λ‹˜ μ§„μ§œλ„ ν…ŒμŠ€νŠΈκ°€ ν•„μš”ν•¨ β‡’ E2E ν…ŒμŠ€νŠΈ

// src/mocks/handlers.ts 

import {rest} from 'msw';
// import fixtures from '../../fixtures';

const BASE_URL = 'http://localhost:3000';

const handlers = [
    rest.get(`${BASE_URL}/products`, (req, res, ctx) => {
        // const { products } = fixtures; // fixturesλ₯Ό μ‚¬μš©ν•΄λ„ 됨  
        const products = [
            {
                category: 'Fruits', price: '$1', stocked: true, name: 'Apple',
            },
        ];

        return res(
            ctx.status(200), // 없어도 됨(κΈ°λ³Έ 섀정이 200)
            ctx.json({products}), // μœ„μ˜ μš”μ²­μ„ 이 ν˜•νƒœλ‘œ λ°˜ν™© 
        );
    }),
];

export default handlers;

App.test.ts 파일 μˆ˜μ •

// App.test.ts

import {render, screen, waitFor} from '@testing-library/react';

import App from './App';

// jest.mock λΆˆν•„μš”

test('App', async () => {
    render(<App / >);

    await waitFor(() => {
        screen.getByText('Apple');
    });
});
  • waitFor : ~ κ°€ 될 λ•ŒκΉŒμ§€ λŒ€κΈ°

    • μ½œλ°±ν•¨μˆ˜μ˜ νƒ€μž…μ΄ Promise둜 λ˜μ–΄ μžˆμ–΄μ„œ async/await ν•„μš”

주의점 & polyfill μ΄μš©ν•˜κΈ°

// hooks/useFetchProducts.ts

export default function useFetchProducts() {
    const url = 'http://localhost:3000/products';
    const {data, error} = useFetch<ProductsResult>(url);
    console.log({error});
    if (!data) {
        return [];
    }

    return data.products;
}
🚨 error: ReferenceError: fetch is not defined

fetchλŠ” μœˆλ„μš°μ— μžˆλŠ” 것 λΈŒλΌμš°μ €μ—μ„œλŠ” λ˜μ§€λ§Œ Nodeμ—μ„œλŠ” 였λ₯˜ Node μ΅œμ‹  버전은 fetchλ₯Ό μ§€μ›ν•˜μ§€λ§Œ, ν˜„μž¬ μ‚¬μš© 쀑인 Node λ²„μ „μ—μ„œλŠ” 지원 X

β‡’ polyfill(폴리필) 을 μ΄μš©ν•΄ ν•΄κ²°

μ„€μΉ˜

npm i -D whatwg-fetch

setupTests.ts νŒŒμΌμ— import

import 'whatwg-fetch'

hooks/useFetchProducts.ts 파일 μ›μƒνƒœλ‘œ 되돌리기

export default function useFetchProducts() {
    const url = 'http://localhost:3000/products';
    const {data} = useFetch<ProductsResult>(url);
    if (!data) {
        return [];
    }

    return data.products;
}

3. polyfill(폴리필)

기본적으둜 μ§€μ›ν•˜μ§€ μ•ŠλŠ” 이전 λΈŒλΌμš°μ €μ—μ„œ μ΅œμ‹  κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” 데 ν•„μš”ν•œ μ½”λ“œ (일반적으둜 μ›Ήμ˜ JavaScript)

μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진을 λ§Œλ“œλŠ” 각 쑰직은 λ‚˜λ¦„λŒ€λ‘œ μš°μ„ μˆœμœ„λ₯Ό 맀겨 λͺ…μ„Έμ„œ λ‚΄ μ–΄λ–€ κΈ°λŠ₯을 λ¨Όμ € κ΅¬ν˜„ν• μ§€ κ²°μ • λͺ…μ„Έμ„œμ— λ“±λ‘λœ κΈ°λŠ₯보닀 μ΄ˆμ•ˆ(draft)에 μžˆλŠ” μ œμ•ˆμ„ λ¨Όμ € κ΅¬ν˜„ν•˜κΈ°λ‘œ κ²°μ •ν•˜λŠ” κ²½μš°λ„ 쑴재 κ΅¬ν˜„ λ‚œλ„κ°€ λ†’μ•„μ„œ 이런 결정을 λ‚΄λ¦¬λŠ” κ²½μš°λ„ μžˆμ§€λ§Œ, ꡬ미λ₯Ό λ‹ΉκΈ°μ§€ μ•Šμ•„ 이런 결정을 내리기도 함 엔진이 ν‘œμ€€ 전체λ₯Ό μ§€μ›ν•˜μ§€ μ•Šκ³  μΌλΆ€λ§Œ μ§€μ›ν•˜λŠ” 것은 ν”ν•œ 일

쀑 ν•˜λ‚˜

3. 파일 생성

Web API
MSW
μ•„μƒ¬λ‹˜μ˜ Mock Service Worker (MSW)
Integrate mocking into Node
setupTests.ts
Mocking REST API
πŸ”— μ‹€μŠ΅ 링크
GitHubμ—μ„œ λ§Œλ“  fetch polyfill
MDN - Polyfill
λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ - 폴리필
GitHubμ—μ„œ λ§Œλ“  fetch polyfill
Service Worker API
Workers overview
service_worker