waitkit
로딩, 스켈레톤, 에러, 타임아웃 상태를 개발 중에 일부러 재현하는 네트워크 시뮬레이션 라이브러리
- 누적 다운로드 2,600회 이상 (4개 패키지 합산)
- 테스트 커버리지 86% (Lines)
- fetch 인터셉터·React·MSW·CLI 4개 패키지
배경
웹 페이지를 개발하다 보면 로딩 UI, 에러 UI처럼 특정 네트워크 상황에서만 보이는 화면을 자주 확인해야 합니다. 하지만 로컬 환경은 응답이 빠르고 안정적이라, 이런 화면을 원하는 때에 띄워 보기가 번거롭습니다. waitkit은 개발자가 지연, 에러, 타임아웃 같은 상황을 원할 때 바로 재현해 로딩·에러 UI를 편하게 확인할 수 있도록 만든 TypeScript 라이브러리입니다.
맡은 일
혼자 패키지 경계와 공개 API를 설계하고, @waitkit/core, @waitkit/react, @waitkit/msw, @waitkit/cli를 구현했습니다. PR 7개를 머지하며 시뮬레이션 규칙, React 연동·개발 도구, MSW resolver 통합, 설정 CLI와 각 패키지 테스트·문서를 함께 다듬었습니다.
한 일
네트워크 시뮬레이션 코어와 규칙 우선순위
- 문제: 네트워크 지연과 실패를 UI에서 재현하려면 요청마다 테스트 코드를 바꾸거나 API 목을 별도로 관리해야 했습니다.
- 해결:
@waitkit/core가globalThis.fetch를 감싸도록 하고, URL 매처(string/RegExp/predicate)와 HTTP 메서드로 요청을 골라 첫 번째로 일치한 규칙만 적용했습니다. 규칙은 고정·범위 지연, 확률 기반 오류 응답, 확률 기반 타임아웃을 표현하며 이름 있는 시나리오로 묶어 전환할 수 있습니다. #2 - 결과: 지연 후 타임아웃, 오류 응답 생성, abort 동작 등 경계 조건을 README에 명시하고 회귀 테스트로 고정했습니다. 시나리오 변경 콜백과 동적 이벤트 구독도 controller API에 추가했습니다. #2 · #4
React 상태 구독과 개발 도구
- 문제: 프레임워크 중립적인 controller를 React 컴포넌트에서 구독하고 시나리오를 바꾸려면 상태 연결 계층이 필요했습니다.
- 해결: controller 생성은 core에 남기고,
@waitkit/react의 Provider에 전달하도록 경계를 나눴습니다. 외부 store를useSyncExternalStore로 구독하는 hook을 제공하고, controller 이벤트 API를 이용해 활성화 상태·시나리오·요청 로그를 보여 주는WaitKitDevTools를 구성했습니다. #3 · #4 - 결과: React UI가 core 내부 구현에 묶이지 않으며, DevTools는 별도 CSS 의존성 없이 Provider 안에서 동작합니다. 후속 개선에서 시나리오 이름 자동 파생과 복원 버튼도 추가했습니다. #6
MSW resolver를 감싸는 선택적 통합
- 문제: 이미 MSW handler에서 응답을 관리하는 프로젝트에 fetch 전역 인터셉터를 추가하지 않고도 동일한 시뮬레이션 규칙을 적용할 방법이 필요했습니다.
- 해결: 별도
@waitkit/msw패키지의withWaitKit(rule, resolver)고차 함수가 기존 resolver를 감싸도록 했습니다. handler가 URL·method를 이미 지정하므로 MSW용 규칙 타입에서는 해당 필드를 제외하고, 평가 순서를 지연 → 타임아웃 → 오류 → resolver 호출로 고정했습니다. 오류는 MSW v2 타입과 맞는HttpResponse로 반환합니다. #5 - 결과: fetch 패치 방식과 MSW handler 방식 중 프로젝트 구조에 맞는 경로를 선택할 수 있고, fake timer로 지연·타임아웃·오류 케이스를 검증합니다.
트러블슈팅
시나리오 변경을 React UI에 안정적으로 반영
- 상황: DevTools와 hook은 controller 상태 변경을 구독해야 하지만, 기존 API는 초기 콜백 옵션 중심이었습니다.
- 원인: 런타임에 구독·해제할 이벤트 인터페이스가 없어 UI 계층이 변경을 관찰하기 어려웠습니다.
- 해결: 이벤트별
addEventListener와 unsubscribe 반환을 추가하고 기존 콜백과 공존시켰습니다. 이후 시나리오 이름은 controller에서 파생해 중복 입력을 줄이고,getScenarioNames()결과를 캐시해 구독 store의 참조 안정성을 보완했습니다. #4 · #6
결과
- 누적 다운로드 2,600회 이상 (4개 패키지 합산)
- 테스트 커버리지 86% (Lines)