SookDev
🌳

MSW 로 일정 병목현상 해결하기

목차

프론트엔드 개발은 UI 퍼블리싱을 진행하고 백엔드 통신을 위해 API 를 붙이는 프로세스로 진행된다.
만약 퍼블리싱이 완료된 상태에서 백엔드가 API 가 완료되지 않았다고 하면 어떻게 해야할까?
여기에, 기획이 딜레이되어 도미노 현상처럼 전부 딜레이가 된다면?
딜레이 됐다고 손가락만 빨다가 모든 타격은 가장 마지막 단계에 있는 프론트엔드가 맞게 된다.
모두가 일정안에 끝낸다면 너무나도 이상적이겠지만 아쉽게도 현실은 그렇지 못하다
모두가 일정안에 끝낸다면 너무나도 이상적이겠지만 아쉽게도 현실은 그렇지 못하다
우리 팀과 같이 애자일 환경에서 운영되는 팀은 빠르게 개발하고 배포하기 위해 이러한 병목현상을 최소화하는 것이 중요하다.
기한 내에 개발을 완료하기 위해, 백엔드와 병렬적으로 작업을 진행할 수 있는 해결책으로 API Mocking 도구인 MSW(Mock Service Worker)를 도입하기로 했다.

1. MSW 란?

Mock Service Worker(MSW)는 테스트 주도 개발(TDD)이나 프론트엔드 개발에서 유용하게 사용되는 도구로, 애플리케이션의 네트워크 요청을 서비스 워커가 가로채 가상의 서버 응답을 제공한다.
브라우저 환경에서 동작하는 서비스 워커를 활용해 백엔드 서버 요청을 중간에서 처리하고,
개발자가 설정한 가상의 응답을 반환함으로써 실제 서버와의 통신 없이 애플리케이션의 동작을 테스트할 수 있다.
이로 인해 백엔드와의 의존성을 줄이고 개발 생산성을 높일 수 있어 프론트엔드 개발에서 많이 쓰이고 있다.
💡
서비스워커 웹 애플리케이션, 브라우저, 네트워크 사이의 프록시 서버 역할을 한다. 푸시 알림과 백그라운드 동기화 지원 등 가능하며, 네트워크 요청 인터셉트 및 조작이 가능하다.
 
장점
  1. 개발 생산성 향상
      • API spec 만으로 프론트엔드 개발을 병렬적으로 진행할 수 있다.
      • 동일한 API 요청 주소로 목업 데이터를 Mocking 처리했기 때문에 실제 API와의 교체가 편하다.
  1. 사전 테스트 시나리오 재현
      • 로딩, 성공, 실패와 같은 다양한 케이스를 분기 처리에 따라 정확하게 재현할 수 있어, 사전에 충분히 검증할 수 있다.
      • 예상치 못한 오류나 예외 상황에 대비한 테스트 작성이 가능하다.
  1. 빠르고 정확한 피드백
      • 기획 변경이나 백엔드 API 설계 변경에 유연하게 대응할 수 있다.
      • 기능 테스트의 정확성을 높이고, 백엔드와의 소통 면에서 빠르게 피드백을 주고받을 수 있다.
  1. 쉽고 직관적인 설정
      • 코드 기반으로 응답을 설정하기 때문에 다른 Mocking 도구에 비해 설정이 직관적이다.
       
단점
  1. Mock 데이터 직접 수정
      • Mock 데이터를 활용하기 때문에 실제 서버 데이터와의 차이가 발생할 수 있다.
      • 백엔드 API가 변경되면 Mock 데이터도 별도로 업데이트해야 한다.
        • msw 지원되는 목업 자동화 라이브러리를 같이 사용하면 해결할 수 있다.
  1. 서버와의 실제 통신 한계
      • 실제 서버와의 통신에서 발생할 수 있는 문제를 완전히 재현하기 어렵다.
      • 서버의 동적 데이터 처리나 인증과 같은 복잡한 로직은 Mocking으로 구현하기 힘들 수 있다.
  1. 브라우저 종속성
      • 서비스 워커를 활용하기 때문에 브라우저 환경에서만 사용할 수 있다.
      • Node.js 환경에서도 사용이 가능하지만 추가 설정이 필요하다.
 
왜 MSW 인가요?
API Mocking 도구로 Axios Mocking, JSON Server, Jest 등 다양하다.
각 도구를 비교한 결과 테이블이다.
도구
설명
MSW (Mock Service Worker)
• Rest api, GraphQl 지원 • 클라이언트 코드수정 불필요 • 실제 API 호출과 동일한 형태로 동작
Axios Mocking
• Axios 인스턴스를 사용하여 API 호출 모킹 • 네트워크 영향을 받아 외부요인에 의한 불규칙한 테스트 결과 초래 • HTTP 클라이언트를 사용하는 프로젝트에서는 적용이 어려움
JSON Server
• 서버 설정이 필요하고, JSON 파일을 매번 수정해야 하므로 관리가 번거로움 • 간단한 API 테스트에는 적합하지만 복잡한 로직을 모킹하기 어려움
Jest
• 실제 데이터 교체보다는 유닛 테스트 목적에 적합 • 실제 네트워크 요청 보장 X
빠른 개발을 위해 사용하는 만큼, 스택 선정에 가장 중요하게 생각한 것은 얼마나 빠르게 실제 데이터와 교체가 가능하냐 에 있었기 때문에 MSW 를 선택하게 되었다.
 

2. MSW 초기 세팅

msw 사이트에 나온 그대로 따라한다면 쉽게 설정할 수 있다.
msw 설치
worker 설정 파일 생성
MSW는 서비스 워커를 통해 요청을 가로채므로, 워커 파일을 생성해야 한다.
  • browser 환경 설정 파일 추가
  • node 환경 설정 파일 추가
  • public 폴더 안에 mockServiceWorker.js 파일 생성하기
.env 파일
개발 서버에서만 msw 를 적용하기 위해 .env 에 아래 설정값을 추가한다.

3. 서비스 워커 설정

MSWProvider.jsx 컴포넌트를 생성하여 내부에 서비스 워커를 실행해주는 로직을 작성한다.
worker.start() 함수의 onUnhandledRequest 옵션 처리
  • 처리되지 않은 요청(예: 일치하는 요청 핸들러가 없는 요청에 대응하는 방법)
  • bypass : Prints nothing, performs the request as-is. (콘솔 waring 뜨지 않게 해줌)
 
🚨 주의할 점
서버/클라이언트 사이드 각 환경에 맞는 모듈 로드를 설정해 주어야 한다.
Next.js 는 서버 사이드가 먼저 실행되고 난 뒤 클라이언트 사이드가 실행되는 특징이 있다.
서버 사이드에서는 브라우저와 관련된 모듈을 불러올 수 없기 때문에 worker 를 찾지못하기 때문에 다음과 같은 에러가 발생한다.
notion image
이것을 해결하기 위해 서비스 워커 실행이 완료된 후에 페이지가 렌더링 되도록 처리해야 한다.
그래야 서비스 워커 설정이 완료되기 전에 API 를 호출해서 mocking 이 되지 않는 상황을 방지할 수 있다.
이제 _app.js 에서 작성한 <MSWProvider> 컴포넌트로 감싸주면 된다.

4. handler 작성하기

mocking 하기 위한 handler 파일을 생성하고 코드를 작성한다.
  • rest api 방식은 http 를 이용해서 작성할 수 있다.
handler 작성을 완료하면 지정한 API 주소로 가는 요청을 msw 가 가로채서 우리가 지정한 값을 반환해준다.
아래와 같이 콘솔이 뜨면 정상적으로 mocking 이 된 것이다.
notion image
 
handler 폴더 구조
handlers.js 파일 내에서 너무 많은 양의 코드가 생성되거나 카테고리별로 관리하고 싶다면 handlers 폴더를 생성해 관리해줄 수 있다.
handlers 폴더를 만들고 각 원하는 handler 이름으로 파일을 생성해준 뒤 코드를 작성한다.
작성한 handler 들은 index.js 에서 handler 들을 모아주면 된다.
 

5. faker.js로 목업 데이터 자동화

위에서 언급한 msw 의 단점 중 하나가 목업데이터를 직접 작성해야 하는 것이다.
어차피 테스트를 위한 목업이므로 내용은 중요하지 않으니, 라이브러리의 힘을 빌려보도록 한다.
찾아본 라이브러리 중 제일 간편하고 업데이트도 자주 되고있어 선택하게 되었다.
faker.js 설치
handler 에 각 타입에 맞는 데이터를 보내줄 수 있도록 설정하면 끝난다.
 

6. 마주친 에러들

크롬 브라우저 Refused to set unsafe header "cookie” 에러
handler 까지 작성을 마치고 실행을 하니 아래와 같이 cookie 관련 에러가 매우 많이 떴었다.
notion image
아래의 링크에서 동일한 이슈에 대해 작성된 글을 보니, https 가 아닌 로컬 환경에서 실행하고 있기 때문에 발생하는 문제라고 한다.
공식 문서에서는 보안상의 이유로 서비스 워커는 보안 연결을 통해서만 연결이 가능하다고 적혀있고,
이를 해결하기 위한 방법도 공식 문서에 나와 있어 크롬의 flag 설정을 통해 해결할 수 있었다.
 
[MSW] Failed to register a Service Worker for scope … 에러
msw 세팅하는 과정에서 npx msw init 으로 mockServiceWorker 파일을 생성해주었는데도 해당 에러가 발생했다.
notion image
mockServiceWorker.js 파일을 찾지 못해 발생하는 에러다.
worker start 를 해줄 때 serviceWorker 의 url을 지정해주니 해결되었다.
  • serviceWorker 의 url 기본값은 ‘/mockServiceWorker.js' 라고 한다.
 

7. 결론

고해성사 하자면 msw를 적용하기 전에는 일정을 핑계로 대국민 QA 한다고 생각하고 기도하며 배포했다. 현재는 적어도 그런무책임하고 가슴졸이는 일은 없어진 듯 하다.
스프린트마다 개발 소요시간은 다 달랐기 때문에 정확하게 산정할 순 없지만, 분명한것은 QA 시점에 모든 개발은 거의 완료된 상태로 온전히 테스트에 집중할 수 있다는 것이다.
이로 인해 개발 정확도는 상승했고, 개발 이슈로 인한 문의가 많이 줄어든것을 체감했다.
하지만 개발자경험 측면에서 본다면 아쉬운점은 있다.
faker.js 를 이용하더라도 스웨거에 있는 문서 타입과 동일하게 작성해야하는 번거로움은 여전히 존재하기 때문이다. 명세 타입이 변경된다면 그에 맞게끔 수정해야 한다.
찾아보니 swagger-typescript-api 라이브러리를 통해 handler와 mock 데이터 자동 생성하는 방법도 있던데, Swagger로부터 자동으로 타입을 생성하여 MSW에서 사용하여 더욱 편리해질것 같다.
추후에 해당 방법에 대해 공부하고 꾸준히 개선 해봐야겠다.
 

참조
🔗 MSW Docs
🔗 MSW git issue
Initial page load requests aren't intercepted since 2.1.0
Updated Oct 31, 2024
🔗 Next.js에서 MSW 적용하기