Nuxt Serverless 함수로 Faker 활용해 Mock 데이터 생성하기

심추진·2024년 11월 13일

Nuxt3

목록 보기
1/4

이번에 맡게 된 관리자용 대시보드 프로젝트에서 서버가 준비되지 않은 상황이라, 서버리스 함수랑 Faker 라이브러리를 사용해 Mock 데이터를 만들어봤다. 서버가 아직 연동되지 않은 상황에서 프론트엔드 작업을 진행하려다 보니 임시 데이터가 필요했는데, 이 방법이 꽤 유용했다. 실제로 서버가 완전히 구현되기 전에 데이터 구조를 맞춰두고, 기능 테스트를 할 수 있어서 개발 속도가 꽤 빨라진 것 같다.

디렉토리 구조

Nuxt 프로젝트에서는 서버리스 함수 파일을 server/api 디렉토리에 넣고, 타입 정의 파일은 types 폴더에 정리해두는 식으로 구성했다. 이번 작업의 디렉토리 구조는 아래와 같았다.

📁 project-root
├── 📁 server
│   └── 📁 api
│       └── 📄 products.ts
├── 📁 types
│   └── 📄 product.ts
├── 📄 nuxt.config.ts
└── 📄 package.json

Faker 라이브러리 설치

Mock 데이터를 생성하기 위해 @faker-js/faker를 사용했는데, 설치는 간단했다.

yarn add @faker-js/faker

타입 정의 (types/product.ts)

타입스크립트를 사용하다 보니, 데이터 구조를 미리 정의해두는 게 편리했다.

export interface ProductData {
  id: number;
  name: string;
  description: string;
  price: number;
  imageUrl: string;
  category: string;
  rating: number;
  stock: number;
  lastUpdated: string;
}

서버리스 함수 (server/api/products.ts)

서버리스 함수에서 Faker를 사용해 더미 데이터를 생성하는 부분을 구현했다. 이 방식으로 실제 서버가 없더라도 데이터 기반 기능들을 미리 테스트할 수 있었다.

import { faker } from '@faker-js/faker';
import { defineEventHandler } from 'h3';
import type { ProductData } from '~/types/product';

export default defineEventHandler((event) => {
  const id = Number(event.context.params?.id);

  if (!id || isNaN(id)) {
    return {
      code: 400,
      message: '유효하지 않은 제품 ID',
    };
  }

  const productData = generateProductData(id);
  return { data: productData };
});

const generateProductData = (id: number): ProductData => ({
  id,
  name: faker.commerce.productName(),
  description: faker.commerce.productDescription(),
  price: parseFloat(faker.commerce.price({ min: 10, max: 1000 })),
  imageUrl: faker.image.urlPicsumPhotos(),
  category: faker.helpers.arrayElement(['Electronics', 'Fashion', 'Home', 'Sports']),
  rating: faker.number.float({ min: 1, max: 5, precision: 0.1 }),
  stock: faker.number.int({ min: 0, max: 100 }),
  lastUpdated: faker.date.recent().toISOString(),
});

Mock 데이터로 테스트

서버를 띄운 후, http://localhost:3000/api/products/1로 접근해서 Mock 데이터를 확인해보니, 더미 데이터가 제대로 생성되었다. 실제 API 요청처럼 동작해서 프론트엔드 개발을 빠르게 진행할 수 있었다.

{
  "data": {
    "id": 1,
    "name": "Stylish Leather Wallet",
    "description": "편리한 사용감을 자랑하는 가죽 지갑.",
    "price": 79.99,
    "imageUrl": "https://picsum.photos/200",
    "category": "Fashion",
    "rating": 4.2,
    "stock": 20,
    "lastUpdated": "2024-11-12T12:00:00.000Z"
  }
}

API 호출 예제

이제 대시보드 페이지에서 Nuxt의 useFetch를 활용해 서버리스 함수로부터 데이터를 가져오는 예제를 작성해보자.

<template>
  <div class="dashboard">
    <h1>관리자 대시보드</h1>
    <div v-if="loading">로딩 중...</div>
    <div v-else-if="error">에러 발생: {{ error.message }}</div>
    <div v-else>
      <div v-for="product in products" :key="product.id" class="product-card">
        <img :src="product.imageUrl" alt="Product Image" />
        <h2>{{ product.name }}</h2>
        <p>{{ product.description }}</p>
        <p>가격: ${{ product.price }}</p>
        <p>카테고리: {{ product.category }}</p>
        <p>평점: {{ product.rating }} / 5</p>
        <p>재고 수량: {{ product.stock }}</p>
        <p>마지막 업데이트: {{ product.lastUpdated }}</p>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';

interface ProductData {
  id: number;
  name: string;
  description: string;
  price: number;
  imageUrl: string;
  category: string;
  rating: number;
  stock: number;
  lastUpdated: string;
}

const products = ref<ProductData[]>([]);
const loading = ref(true);
const error = ref<Error | null>(null);

const fetchProducts = async () => {
  try {
    const { data } = await useFetch('/api/products/1');
    if (data.value) {
      products.value = [data.value.data]; // Mock 데이터가 하나만 있기 때문에 배열로 감싸기
    }
  } catch (err) {
    error.value = err as Error;
  } finally {
    loading.value = false;
  }
};

onMounted(() => {
  fetchProducts();
});
</script>

회고

이번 작업에서 서버리스 함수와 Faker를 활용해 Mock 데이터를 생성하고, 프론트엔드 대시보드에서 이를 불러오는 방식까지 구현해봤다. 서버가 아직 준비되지 않은 상황에서도 필요한 데이터를 기반으로 UI를 빠르게 구성할 수 있어서 효율적인 개발이 가능했다.

다만, useFetch를 사용하면서 정적 키 문제 때문에 캐시나 중복 요청 방지 측면에서 한계를 느꼈다. Nuxt의 기본 기능이 단순한 경우에는 충분히 유용하지만, 동적인 상황에서 더 복잡한 요구사항이 필요하다면 TanStack Query를 사용하는 것이 더 나은 선택이라고 판단하여 이후에는 TanStack Query를 적극적으로 도입해볼 계획이다.🚀

profile
Product 개발에 항상 설레는 Web • App 개발자입니다.

0개의 댓글