MSW로 프론트엔드 개발 프로세스 개선하기 : API Mocking
[kt cloud 플랫폼Innovation팀 송재희 님]
MSW로 프론트엔드 개발 프로세스 개선하기 : API Mocking
프론트엔드 개발자라면, 종종 백엔드 API가 준비되기 전까지 대기해야 하는 상황을 경험해 보셨을 겁니다. 이번 포스트에서는 백엔드 API가 준비되기 전에 동일한 규격의 API를 지원하는 가상 서버 환경을 구성하여, 생산성 높은 프론트엔드 개발을 진행할 수 있는 방법을 소개하고자 합니다. 그 중심에는 MSW(Mock Service Worker)가 있습니다.
프론트엔드 개발의 현실
프론트엔드와 백엔드가 협업하며 마주하는 어려움 중 하나는 백엔드 API 연동 과정에 있습니다. 프론트엔드는 클라이언트 UI 화면 구현을 중심으로 작업을 진행하지만, 서버 API를 연동하여 알맞은 데이터와 서비스 기능을 제공합니다. 연동 과정에서 이슈사항이 발생하면, 프로젝트 일정과 코드 품질에 큰 영향을 미칠 수 있습니다.
1. 개발 일정 지연
백엔드 API 개발이 예상보다 길어지는 경우, API를 활용해야 하는 프론트엔드 개발은 대기(Pending) 상태에 놓일 수 있습니다.
예를 들어, 특정 페이지나 컴포넌트가 API 데이터에 종속적인 경우, 만들어진 API가 없으면 '더미 데이터'를 넣고 개발을 진행해야 합니다. 이는 임시방편적인 방식으로, 실제 API와 데이터 구조가 맞지 않을 수 있고, 클라이언트 단에서 API 호출에 대한 응답 처리 로직을 가상으로 설계하고 개발해야 합니다. 실제 백엔드 API 개발이 완료되면, API 규격에 맞추어 코드 수정 작업이 이중으로 발생하여 비효율을 초래합니다.
개발 단계의 마지막에 위치하는 프론트엔드는 마감 기한에 쫓겨 충분한 테스트를 수행하지 못하고, 코드 품질의 저하와 함께 전체 프로젝트 개발 일정이 지연될 수 있습니다.
2. 로컬 개발 환경에서의 불편함
로컬 환경에서 백엔드 서버와 연동하기 위하여 Auth, Gateway 등 부가적인 환경 설정이 필요한 경우가 있습니다. 프론트엔드가 독립적으로 개발할 수 있는 환경이 구성되지 않으면, 개발 효율성이 떨어질 수 있습니다.
이러한 문제를 개선하기 위하여, 프론트엔드의 개발 대기 시간을 최소화 하고 백엔드와 병행하여 개발할 수 있도록 가상(Mock) 서버 환경을 구성하였습니다. 실제 API와 유사하게 네트워크 수준에서 API 연동 테스트를 할 수 있는 MSW(Mock Service worker) 라이브러리를 도입합니다.
MSW(Mock Service Worker)란?
MSW(Mock Service Worker)는 서비스 워커(Service Worker) 기술을 활용하여 네트워크 레벨에서 API 요청을 가로채고 모킹(mocking)할 수 있는 라이브러리입니다.
서비스 워커(Service Worker)란?
서비스 워커는 최신 브라우저에서 지원하는 기술로, 웹 응용 프로그램, 브라우저, 네트워크 사이의 프록시 서버 역할을 수행합니다. 메인 스레드와는 별도로 백그라운드 스레드에서 실행되어 요청을 가로채고 처리할 수 있기 때문에, 웹 애플리케이션 성능 최적화와 사용자 경험 개선에 유리합니다.
MSW의 동작 원리
MSW는 다음과 같은 과정을 통해 API 모킹을 처리합니다.
- 브라우저에 Service Worker가 구성되어 있고, 실제 요청(Request)이 발생하면 Service Worker가 이를 가로챕니다.
- Service Worker는 가로챈 요청(Request)을 복사하여 MSW로 전달합니다.
- MSW는 가로챈 요청을 미리 정의된 모의 응답(Mock Response)과 매칭하는 작업을 수행합니다.
- MSW는 모의 응답을 Service Worker에 전달합니다.
- Service Worker는 모의 응답을 브라우저에 전달합니다.
즉, Service Worker를 중간자 역할을 하여 클라이언트 요청에 대하여 예상되는 API 응답을 네트워크 레벨에서 Mocking 하여 제공할 수 있습니다.
MSW의 특징
MSW는 다음과 같은 특징과 장점을 제공합니다.
- 별도 Mocking 서버를 구축할 필요 없습니다.
- 프론트엔드 프로젝트 내에서 간단하게 API Mocking을 설정할 수 있습니다. - 프레임워크와 라이브러리에 종속되지 않습니다.
- React, Vue, Angular 등 다양한 프레임워크에서 잘 동작합니다. - 다양한 환경을 지원합니다.
- 브라우저, Node.js 환경에서의 동작을 지원합니다. - 기존 코드 수정 없이 사용 가능합니다.
- 기존의 API 요청 로직을 수정하지 않고 모킹 처리가 가능하므로, 실제 백엔드 서버와 MSW 간의 연결 스위칭이 편리합니다.
MSW 사용 환경 구축하기
1.FrontEnd 프로젝트에 MSW 라이브러리를 설치합니다.
# msw 패키지 설치 npm install msw --save-dev # Service worker 모듈 셋팅 (/public 디렉토리 하위에 구성됨) npx msw init public --save |
2.MSW 설정 파일과 API Handler 파일을 구성합니다.
├── public ├── mockServiceWorker.js ├── src ├── mocks ├── brower.ts # Brower 환경 Service Worker Setup ├── server.ts # Server 환경 Service Worker Setup ├── handlers.ts # Handler 등록 관리 ├── handler # API 핸들러 디렉토리 ├── SampleEndpoint1.ts # Sample엔드포인트1 Handler ├── SampleEndpoint2.ts # Sample엔드포인트2 Handler ├── ... |
3.API Handler를 작성합니다.
- Handler 파일은 백엔드 서비스 엔드포인트를 기준으로 작성하며, 관련된 서비스 핸들러를 디렉토리로 그룹화하면 관리에 용이합니다.
- API URL와 요청 메서드 타입에 따른 Request, Response, 더미데이터 등을 정의합니다.
# SampleEndpoint1.ts import { rest } from 'msw' /** * Sample Data - 전체 조회 * @id {string} 아이디 * @name {string} 이름 * @description {string} 설명 */ const dataList = [ { id: '1100', name: 'mock-test1', description: '설명1 입니다.', }, { id: '1101', name: 'mock-test2', description: '설명2 입니다.', }, ] /** * Sample Data - 생성 * @name {string} 이름 * @type {string} 유형 * @description {string} 설명 */ const createData = { name: 'mock-test1', type: 'sample', description: '설명1 입니다.', } export const endpointName = [ // 전체 조회 rest.get('/sddc-m/api/v1/sample1', (req, res, ctx) => { return res(ctx.status(200), ctx.json(dataList)) }), // 단건 조회 - Path Parameter 활용 (/{id}) rest.get(`/sddc-m/api/v1/sample1/:id`, (req, res, ctx) => { const { id } = req.params return res(ctx.status(200), ctx.json(data1)) }), // 생성 rest.post('/sddc-m/api/v1/sample1', (req, res, ctx) => { return res(ctx.status(201), ctx.json({ message: 'POST Success!' })) }), // 수정 rest.patch(`/sddc-m/api/v1/sample1/:id`, (req, res, ctx) => { return res(ctx.status(200), ctx.json({ message: 'PATCH Success!' })) }), // 삭제 rest.delete(`/sddc-m/api/v1/sample1/:id`, (req, res, ctx) => { return res(ctx.status(200), ctx.json({ message: 'DELETE Success!' })) }), ] |
4.handlers.ts 에서 MSW로 사용할 API Handler를 등록합니다.
# handlers.ts import type { DefaultBodyType, MockedRequest, RestHandler } from 'msw' import { sampleEndpoint1 } from './handler/sampleEndpoint1' const handlers: RestHandler<MockedRequest<DefaultBodyType>>[] = [...sampleEndpoint1] export default handlers |
5.index.tsx에서 구동 환경에 따라 MSW를 활성화할 수 있도록 설정합니다. .env파일에서 선언한 환경변수를 활용합니다.
# index.tsx # 개발환경(development)에서만 MSW 구동 활성화 if (process.env.NODE_ENV === "development") { worker.start(); } |
6.Handler에 등록된 API를 호출하는 컴포넌트, 페이지를 개발한 다음, Chrome 개발자도구에서 MSW가 정상적으로 동작하는지 확인합니다.
MSW 활용 사례
MSW는 다양한 개발 시나리오에서 활용할 수 있습니다.
1. 백엔드와 프론트엔드 병행 개발
백엔드 API 개발이 완료되기 전이라도, 프론트엔드 개발자는 Mock API를 활용하여 UI 개발을 진행할 수 있습니다. API 스펙만 사전에 정의되면, 일관된 데이터를 기반으로 UI를 완성할 수 있습니다.
또한 기존 API 처리 로직에 대한 코드 변경이 없기 때문에, 백엔드 API 개발이 완료되면 MSW를 비활성 처리하고 실제 백엔드 서버로 스위칭만 하면 되므로 매우 편리합니다.
2. 테스트 자동화
테스트 작성 시 실제 서버에 요청을 보내는 대신, 모의 API 응답을 사용해 네트워크 레벨 테스트를 수행할 수 있습니다. Jest와 같은 테스트 프레임워크와 통합하여 다양한 케이스에 대한 테스트를 쉽게 작성할 수 있습니다.
*테스트 예시
- 서버에서 데이터를 성공적으로 받아와 UI 렌더링이 잘 되는지 확인합니다.
- 조건부 렌더링이 다양한 데이터에 맞춰 올바르게 동작하는지 확인합니다.
- 엣지 케이스 데이터나 예외 상황에서 UI가 잘 처리되는지 테스트합니다.
- 네트워크 오류가 발생하였을 때, UI가 적절하게 대응하는지 확인합니다.
마무리
MSW는 프론트엔드 개발자들에게 매우 유용한 도구입니다. 백엔드 API가 준비되지 않은 상태에서도 프론트엔드 개발을 효율적으로 진행할 수 있으며, 테스트 자동화에도 큰 도움을 줄 수 있습니다. 프로젝트의 생산성과 개발 속도를 높이고자 한다면 MSW를 적극 활용하는 것을 추천드립니다:)
참고/출처