백엔드 API를 기다리지 마세요: TypeScript‑First Mock Server인 Fakelab 소개
Source: Dev.to
프론트엔드 개발자라면 이런 상황을 겪어봤을 겁니다: 기능을 구현할 준비는 되었지만 백엔드 API가 아직 준비되지 않았거나, 준비는 되었지만 느리거나 신뢰성이 떨어지거나 로컬에서 설정하기 번거로운 인증이 필요합니다. 실제와 같은 데이터를 필요로 하지만, 목 핸들러를 작성하거나 타입과 동기화되지 않는 JSON 픽스처를 유지 관리하는 데 시간을 들이고 싶지는 않죠.
저도 그 경험이 있습니다. 그래서 저는 Fakelab—TypeScript 인터페이스에서 직접 현실적인 데이터를 생성하는 목 API 서버를 만들었습니다. 몇 달간의 개발과 실제 환경 테스트를 거쳐 v1.0을 출시합니다.
API 모킹의 실제 문제
대부분의 프론트엔드 개발자는 다음 중 하나의 방식을 사용합니다:
옵션 1: 하드코딩된 JSON 파일
- 시작은 빠르지만 유지보수가 악몽이 됩니다
- 타입 안전성 없음
- 데이터가 오래됩니다
- 변형을 만들기 어렵습니다
옵션 2: json-server 또는 MSW 같은 도구
json-server는 훌륭하지만 여전히 JSON을 수동으로 작성해야 합니다- MSW는 강력하지만 모든 엔드포인트에 대한 핸들러를 작성해야 합니다
- 두 경우 모두 타입과 별도로 모의 데이터를 관리해야 합니다
옵션 3: 백엔드가 준비될 때까지 기다리기
- 기능을 배포하고 싶다면 실질적인 옵션이 아닙니다
핵심 문제는 중복입니다: TypeScript에서 타입을 정의하고, 다른 곳에서 모의 데이터를 정의합니다. 타입이 변경되면 모의 데이터가 깨지고, 모의 데이터가 변경되면 타입이 잘못될 수 있습니다. 이는 지속적인 마찰의 원인입니다.
기존 도구들이 충분하지 않았던 이유
나는 모든 방법을 시도해봤다. json-server는 견고하지만, 내 타입과 맞지 않는 JSON을 작성하는 것이 지겨워졌다. MSW는 테스트에 뛰어나지만, 개발에서는 더 간단한 것이 필요했다—그냥 TypeScript 파일을 가리키기만 하면 API를 얻을 수 있는.
MirageJS도 근접했지만, 내가 필요로 하는 것에 비해 무겁게 느껴졌고, API가 오래된 느낌이었다. 나는 현대 TypeScript 워크플로우에 자연스럽게 녹아드는 것이 필요했다.
내가 진정으로 원했던 것은:
- 타입을 한 번 정의하면, 자동으로 목(mock) 데이터를 생성
- 타입 안전한 목 데이터 생성
- 수동 작업 없이 현실적인 데이터
- 상태를 유지하는 테스트를 위한 영구 데이터베이스
- 엣지 케이스 테스트를 위한 네트워크 시뮬레이션
- 보일러플레이트 제로
그래서 나는 Fakelab을 만들었다.
Fakelab이란?
Fakelab은 TypeScript 인터페이스를 읽어 실제와 같은 가짜 데이터를 제공하는 REST 엔드포인트를 생성하는 Node.js 목업 API 서버입니다. JSDoc 주석을 사용해 Faker.js 지시자를 타입에 주석으로 달면, Fakelab이 나머지를 처리합니다.
하이라이트
- TypeScript‑first – 타입이 진실의 원천입니다. 별도의 목업 정의가 필요 없습니다.
- Zero boilerplate – 인터페이스에 주석만 달고, 서버를 실행하면 엔드포인트가 바로 생성됩니다.
- Persistent database – 내장 데이터베이스 모드로 생성, 업데이트, 삭제 작업을 테스트할 수 있습니다.
- Snapshot real APIs – 실제 API의 응답을 캡처해 재사용 가능한 목업으로 전환합니다.
- Network simulation – 코드를 변경하지 않고도 로딩 상태, 재시도, 오류 처리를 테스트할 수 있습니다.
- Runtime API – 간단한 API를 통해 프런트엔드 코드에서 목업에 접근합니다.
주요 기능 설명
Faker 어노테이션을 활용한 TypeScript‑First
수동으로 목 데이터를 작성하는 대신, TypeScript 인터페이스에 어노테이션을 추가합니다:
// fixtures/user.ts
export interface User {
/** @faker string.ulid */
id: string;
/** @faker person.fullName */
name: string;
/** @faker location.streetAddress */
address: string;
/** @faker phone.number */
phone: string;
/** @faker number.int({ min: 10, max: 80 }) */
age: number;
}
Fakelab은 이 어노테이션을 파싱하고 Faker.js를 사용해 현실적인 데이터를 생성합니다. /api/User를 요청하면 "test"나 "asdf"가 아닌 적절한 이름, 주소, 전화번호를 가진 사용자 배열을 받게 됩니다.
스냅샷: 실제 API 캡처
제가 가장 좋아하는 기능 중 하나는 snapshot 명령입니다. 기존 API에서 목 데이터를 바로 만들고 싶을 때가 있습니다:
npx fakelab snapshot https://jsonplaceholder.typicode.com/todos --name Todo
Fakelab은 응답을 가져와 TypeScript 타입을 추론하고 이를 목 소스로 저장합니다. 나중에 갱신하거나 설정 파일에 여러 소스를 정의할 수 있습니다. 실제 API에서 마이그레이션하거나 오프라인 개발을 위해 응답을 고정해야 할 때 완벽합니다.
데이터베이스 모드
기본적으로 Fakelab은 각 요청마다 새로운 데이터를 생성합니다. 상태를 유지하는 작업을 테스트하려면 데이터베이스 모드를 활성화할 수 있습니다:
// fakelab.config.ts
export default defineConfig({
database: { enabled: true },
});
이제 데이터를 시드하고, 조회하고, 레코드를 업데이트하며 앱의 데이터 흐름을 테스트할 수 있습니다. 데이터베이스는 서버 재시작 사이에도 유지됩니다(내부적으로는 lowdb를 사용한 JSON 파일).
네트워크 시뮬레이션
목이 항상 즉시 성공하면 오류 상태와 로딩 스피너를 테스트하기가 번거롭습니다. Fakelab은 실제 네트워크 조건을 시뮬레이션할 수 있게 해줍니다:
network: {
delay: [300, 1200], // 300‑1200 ms 사이의 랜덤 지연
errorRate: 0.1, // 10 % 요청 실패
timeoutRate: 0.05, // 5 % 요청 타임아웃
errors: {
statusCodes: [400, 404, 500],
},
}
fetch나 axios를 별도로 목킹하지 않아도 재시도 로직, 에러 경계, 로딩 상태 등을 테스트할 수 있습니다.
런타임 API
Fakelab은 프론트엔드에서 사용할 수 있는 런타임 API를 제공합니다:
import { fakelab } from "fakelab/browser";
// 10명의 사용자 가져오기
const users = await fakelab.fetch("User", 10);
// 기본 URL 얻기
const apiUrl = fakelab.url(); // "http://localhost:50000/api"
프로그래밍 방식으로 데이터를 생성하거나 Fakelab을 개발 워크플로에 통합하고 싶을 때 유용합니다.
짧은 코드 예시
전체 예시입니다. 먼저 타입과 설정을 정의합니다:
// fakelab.config.ts
import { defineConfig } from "fakelab";
export default defineConfig({
sourcePath: ["./fixtures"],
server: { port: 50000 },
database: { enabled: true },
network: {
delay: [200, 800],
errorRate: 0.05,
},
});
// fixtures/product.ts
export interface Product {
/** @faker string.uuid */
id: string;
/** @faker commerce.productName */
name: string;
/** @faker commerce.price */
price: number;
/** @faker commerce.department */
category: string;
}
서버 실행:
npx fakelab start
이제 http://localhost:50000/api에서 현실적인 Product 데이터와 영구 저장소, 네트워크 시뮬레이션을 갖춘 완전한 목 API를 사용할 수 있습니다—모두 단일 TypeScript 인터페이스에서 파생되었습니다.
// fakelab.config.ts (대체 최소 설정)
import { defineConfig } from "fakelab";
export default defineConfig({
port: 50101,
database: { enabled: true },
});
서버 시작
npx fakelab serve
현재 제공되는 엔드포인트:
GET /api/User– 사용자 배열을 반환GET /api/User?count=5– 5명의 사용자를 반환POST /api/User– 새 사용자를 생성 (데이터베이스가 활성화된 경우)
React 앱에서
import { fakelab } from "fakelab/browser";
const users = await fakelab.fetch("User", 10);
// 또는 일반 fetch 사용:
const response = await fetch("http://localhost:
```javascript
50101/api/User?count=10");
const users = await response.json();
그게 전부입니다. 핸들러도 없고, JSON 파일도 없으며, 보일러플레이트도 없습니다.
Fakelab을 사용해야 할 때 (그리고 사용하면 안 되는 경우)
Fakelab을 사용할 때:
- 백엔드가 아직 준비되지 않은 상태에서 프론트엔드를 구축하고 있을 때.
- 백엔드 의존성 없이 오프라인으로 개발하고 싶을 때.
- 현실적인 데이터 변형을 테스트해야 할 때.
- 타입과 동기화된 타입‑안전 모크가 필요할 때.
- 빠르게 API가 필요한 프로토타이핑을 할 때.
Fakelab을 사용하면 안 되는 경우:
- 모크에 복잡한 비즈니스 로직이 필요할 때 (MSW를 사용하세요).
- 실제 백엔드와 함께 통합 테스트를 진행할 때 (실제 API를 사용하세요).
- GraphQL이 필요할 때 (Fakelab은 현재 REST‑전용입니다).
- 인증/인가 로직이 필요할 때 (Fakelab은 의도적으로 단순합니다).
Fakelab은 개발 도구이며, 테스트 프레임워크가 아닙니다. 프론트엔드 개발을 더 빠르고 독립적으로 만들기 위해 설계된 것이지, 통합 테스트를 대체하기 위한 것이 아닙니다.
대상 사용자
- 프론트엔드 개발자로서 독립적으로 작업하고 싶은 사람.
- React/Next.js 개발자로서 실시간에 가까운 데이터를 빠르게 필요로 하는 사람.
- 팀으로서 프론트엔드와 백엔드가 병행해서 작업하는 경우.
- 개발자로서 타입 안전성을 중시하고 타입을 반영한 목(mock) 데이터를 원하는 사람.
만약 MSW, json‑server, MirageJS와 같은 도구에 익숙하다면, Fakelab은 익숙하면서도 더 단순하게 느껴질 것입니다. 모의 서버를 사용해 본 적이 없다면, Fakelab이 가장 쉽게 시작할 수 있는 도구일 것입니다.
향후 로드맵
Fakelab v1은 대부분의 사용 사례에 대해 안정적이며 기능이 완전하지만, 앞으로도 더 많은 기능이 추가될 예정입니다:
- GraphQL 지원 – 타입으로부터 GraphQL 스키마를 생성합니다.
- 맞춤형 생성기 – Faker를 넘어 자체 데이터 생성기를 작성합니다.
- 관계 – 타입 간 관계를 정의합니다 (예: User가 여러 Posts를 가짐).
- Webhook 개선 – 재시도 로직 및 향상된 오류 처리.
- 성능 – 대규모 데이터셋 및 빠른 시작을 위해 최적화합니다.
기능 요청도 환영합니다. Fakelab이 필요로 하는 기능을 제공하지 않는다면, 이슈를 열어 논의해봅시다.
직접 사용해 보기
Fakelab은 오픈 소스이며 MIT 라이선스를 가지고 있습니다. 다음 명령으로 설치하세요:
npm install fakelab --save-dev
문서를 확인하거나 예제를 살펴보면서 실제 동작을 확인해 보세요.
사용해 보고 배포 속도가 빨라진다면 알려 주세요. 문제가 발생하거나 아이디어가 있으면 이슈나 PR을 열어 주세요. 이 도구는 제가 직접 사용하기 위해 만들었지만, 다른 개발자들에게도 유용할 것이라 생각해 공유합니다.
마무리 생각
Fakelab을 만들면서 개발자들이 실제로 도구에서 필요로 하는 것이 무엇인지 많이 배웠습니다. 우리는 더 많은 기능이 필요하지 않습니다—우리는 방해되지 않고 개발에 집중할 수 있게 해주는 도구가 필요합니다. Fakelab은 모든 사람을 위한 모든 것이 되려는 것이 아니라, 한 가지를 잘 하려고 합니다: TypeScript 타입과 맞물려 작동하는 모의 API 서버를 제공하는 것이죠, 타입에 반하는 것이 아니라.
그것이 유용해 보인다면 한 번 사용해 보세요. 그렇지 않다면 괜찮습니다. 하지만 백엔드 API를 기다리느라 지치거나 항상 동기화되지 않는 모의 데이터를 관리하는 데 지쳤다면, Fakelab이 찾고 있던 것일지도 모릅니다.