MSW로 비동기 UI와 API 호출 테스트하기
Mock Service Worker로 HTTP 요청을 모의 처리해 데이터를 가져오는 컴포넌트를 테스트합니다.
MSW로 비동기 UI와 API 호출 테스트하기은(는) CoddyKit의 무료 React Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 React Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. React Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
Mock Service Worker가 필요한 이유
MSW는 네트워크 수준에서 서비스 워커(브라우저) 또는 http 인터셉터(Node)를 사용해 HTTP 요청을 가로챕니다. 따라서 애플리케이션 코드를 수정하지 않고도 API를 모의 처리할 수 있습니다.
MSW 설치
MSW를 설치하고 Jest/Vitest 테스트를 위한 Node 인터셉터를 설정하십시오.
// npm install msw --save-dev
// src/mocks/handlers.ts
import { http, HttpResponse } from 'msw';
export const handlers = [
http.get('/api/users', () => {
return HttpResponse.json([{ id: 1, name: 'Alice' }]);
}),
];모의 서버 설정
처리기를 사용해 setupServer 인스턴스를 만들고, 테스트 전에 server.listen()을 호출하십시오. 각 테스트 후에는 server.resetHandlers()를 호출하고, 모든 테스트가 끝난 후에는 server.close()를 호출하십시오.
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
const server = setupServer(...handlers);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());데이터를 가져오는 컴포넌트 테스트
데이터 가져오기를 트리거하는 컴포넌트를 렌더링하십시오. MSW가 요청을 가로채 모의 데이터를 반환합니다. 데이터가 로드된 후 사용자에게 보이는 내용을 검증하십시오.
test('shows user list after fetch', async () => {
render(<UserList />);
expect(screen.getByText('Loading...')).toBeInTheDocument();
expect(await screen.findByText('Alice')).toBeInTheDocument();
});비동기 사용자 인터페이스를 위한 findBy 조회
findBy 조회는 요소가 나타나면 완료되는 프로미스를 반환합니다. 기본 제한 시간은 최대 1초입니다. 비동기 작업 후 나타나는 콘텐츠에 사용하십시오.
// findByText waits for the element to appear
const username = await screen.findByText('Alice');
expect(username).toBeInTheDocument();
// waitFor wraps assertions that need to wait
await waitFor(() => {
expect(screen.getByText('3 users')).toBeInTheDocument();
});테스트별 처리기 재정의
테스트 내부에서 server.use()를 사용하면 해당 테스트에서만 기본 처리기를 재정의하는 일회성 처리기를 추가할 수 있습니다.
test('shows error on API failure', async () => {
server.use(
http.get('/api/users', () => {
return HttpResponse.json({ message: 'Server error' }, { status: 500 });
})
);
render(<UserList />);
expect(await screen.findByText('Failed to load users')).toBeInTheDocument();
});로딩 상태 테스트
비동기 데이터가 도착하기 전에 렌더링 직후 동기적으로 로딩 표시기를 검증하십시오.
test('shows loading state initially', () => {
render(<UserList />);
expect(screen.getByRole('progressbar')).toBeInTheDocument();
// or
expect(screen.getByText('Loading...')).toBeInTheDocument();
});POST 요청 테스트
요청 본문을 검증하고 생성된 리소스를 반환하는 POST 처리기를 정의합니다. 구성 요소가 성공 상태를 반영하는지 검증합니다.
server.use(
http.post('/api/users', async ({ request }) => {
const body = await request.json();
return HttpResponse.json({ id: 2, ...body }, { status: 201 });
})
);
test('creates a user', async () => {
const user = userEvent.setup();
render(<NewUserForm />);
await user.type(screen.getByLabelText('Name'), 'Bob');
await user.click(screen.getByRole('button', { name: /create/i }));
expect(await screen.findByText('User created!')).toBeInTheDocument();
});현실적인 테스트를 위한 네트워크 지연
delay 유틸리티를 사용하는 MSW 처리기에 인위적인 지연을 추가하여 로딩 사용자 인터페이스를 더 철저하게 테스트합니다.
import { delay } from 'msw';
http.get('/api/users', async () => {
await delay(200);
return HttpResponse.json([{ id: 1, name: 'Alice' }]);
})리액트 쿼리를 사용한 테스트
테스트 간 상태가 유출되지 않도록 각 테스트마다 새로운 QueryClientProvider로 구성 요소를 감쌉니다.
function renderWithQuery(ui: React.ReactElement) {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
return render(
<QueryClientProvider client={queryClient}>{ui}</QueryClientProvider>
);
}요청 데이터 검증
처리기 내부에서 요청 감시 함수를 사용하여 애플리케이션이 올바른 요청 본문이나 헤더를 전송했는지 확인합니다.
let capturedBody: unknown;
server.use(
http.post('/api/login', async ({ request }) => {
capturedBody = await request.json();
return HttpResponse.json({ token: 'abc' });
})
);
test('sends credentials to API', async () => {
// ... submit form ...
expect(capturedBody).toEqual({ email: 'a@b.com', password: 'pass' });
});개발 환경에서 브라우저로 MSW 사용하기
개발 중에는 브라우저에서도 MSW를 사용할 수 있습니다. npx msw init public/을 실행하여 서비스 워커를 설치하고, main.tsx에서 처리기를 가져와 로컬 개발 중에 사용할 모의 API를 설정합니다.
빠른 확인
API 호출이 완료된 후 나타나는 콘텐츠를 검증하려면 어떤 RTL 쿼리 유형을 사용해야 하나요?
요약
MSW는 실제 HTTP 요청을 가로채므로 실제 서버에 접속하지 않고도 현실적인 테스트를 만들 수 있습니다. 테스트마다 처리기를 재정의하려면 server.use()를 사용하고, 비동기 검증에는 findBy를 사용하며, 리액트 쿼리 테스트는 새로운 QueryClientProvider로 감싸십시오.
자주 묻는 질문
“MSW로 비동기 UI와 API 호출 테스트하기” 강의는 무료인가요?
네 — “MSW로 비동기 UI와 API 호출 테스트하기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 React Academy 강의 전체를 잠금 해제할 수 있습니다. React Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“MSW로 비동기 UI와 API 호출 테스트하기”에서 뭘 배우나요?
Mock Service Worker로 HTTP 요청을 모의 처리해 데이터를 가져오는 컴포넌트를 테스트합니다. 브라우저에서 직접 실행하는 실습 코드로 React Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
React Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 React Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“MSW로 비동기 UI와 API 호출 테스트하기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 React Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 React Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- React Testing Library로 통합 테스트하기
- MSW로 비동기 UI와 API 호출 테스트하기
- React용 Playwright 시작하기
- 양식과 사용자 흐름 엔드 투 엔드 테스트