Firestore seed data 설계: 리뷰 더미 데이터 구조 잡기

··설명 약 5분·작성: 해비·블로그 소개

Firestore 리뷰 시드 데이터의 ID·시각·평점 경계값은 어떻게 설계하나요?

Firestore 시드 데이터는 실제 고객처럼 보이게 만드는 것보다 테스트할 조건을 반복 재현하는 것이 우선입니다. 고정 ID·기준 시각·평점 경계값을 정하고 같은 입력을 다시 만들었을 때 비교할 수 있게 하세요.

적용 조건·범위: 예시는 관측한 쇼핑몰 통계가 아니라 검증용으로 만든 균등 평점 분포입니다. 4.5에 ±0.5를 더하고 반올림하면 대부분 4·5만 나와 낮은 평점 테스트가 빠집니다. 무작위 분포가 꼭 필요하면 난수 seed를 고정하고 분포 가정을 기록하세요. Date를 Timestamp로 바꾸는 것은 타입 변환이며 서버 시각으로 보정하는 작업이 아닙니다.

본문 근거: firebase.google.com/docs/firestore/manage-data/add-data · firebase.google.com/docs/firestore/query-data/indexing · firebase.google.com/docs/emulator-suite/connect_firestore

학습 목표와 사전 지식

목표: 리뷰 시드의 재현성·중복 방지·조회 검증 기준을 설계합니다.
사전 지식: Firestore CRUD, JavaScript 배열·날짜, 테스트 데이터와 운영 데이터 구분

좋은 시드는 실제 고객처럼 보이는 문장보다 테스트할 경계값이 명확해야 합니다. 일정한 ID와 기준 시각을 사용하면 재실행 전후 문서 수와 정렬을 비교할 수 있습니다.

조회 요구에서 데이터 구조를 결정하기

루트 reviews에 productId, authorId, rating, text, createdAt, seedVersion을 둡니다. 상품별 최근 리뷰는 productId 동등 조건과 createdAt 정렬로 표현합니다. 상품 하위 reviews도 collection group 쿼리로 여러 상품을 조회할 수 있으므로 루트 구조만 가능한 것은 아닙니다. Firestore의 컬렉션 구조를 Storage의 파일 구조라고 부르지 않습니다.

테스트 목적 준비할 데이터
평점 필터 1·2·3·4·5점 모두 포함
페이지 경계 limit보다 1개 많은 문서·빈 결과
정렬 서로 다른 날짜·같은 날짜
입력 검증 빈 text·과도한 길이는 별도 거부 테스트
권한 분리 서로 다른 authorId의 문서

scripts/review-fixtures.mjs · 전체 파일; 네트워크 없이 실행 가능한 데이터 생성 모듈

export function makeReviews(productId, count = 10) {
  if (!/^[a-z0-9-]+$/.test(productId)) throw new Error('잘못된 상품 ID');
  if (!Number.isInteger(count) || count < 0 || count > 100) {
    throw new Error('count는 0~100 정수입니다.');
  }
  const base = Date.UTC(2026, 0, 1);
  return Array.from({ length: count }, (_, index) => ({
    id: `seed-v1-${productId}-${index}`,
    productId,
    authorId: `fixture-user-${index % 3}`,
    rating: (index % 5) + 1,
    text: `학습용 리뷰 ${index + 1}`,
    createdAt: new Date(base + index * 86400000),
    seedVersion: 'v1'
  }));
}
Firestore seed data 설계: 리뷰 더미 데이터 구조 잡기 핵심 개념을 설명하는 첫 번째 본문 이미지

랜덤보다 고정 fixtures부터

예시는 관측한 쇼핑몰 통계가 아니라 검증용으로 만든 균등 평점 분포입니다. 4.5에 ±0.5를 더하고 반올림하면 대부분 4·5만 나와 낮은 평점 테스트가 빠집니다. 무작위 분포가 꼭 필요하면 난수 seed를 고정하고 분포 가정을 기록하세요. Date를 Timestamp로 바꾸는 것은 타입 변환이며 서버 시각으로 보정하는 작업이 아닙니다.

저장 단계에서 중복을 막는 방식

생성한 id를 문서 ID로 쓰고 setDoc을 사용하면 같은 v1 데이터 재실행은 같은 문서를 덮어씁니다. addDoc의 새 ID를 매번 만들면 중복이 늘어납니다. 단, count를 10에서 5로 줄이면 기존 뒤쪽 5개는 저절로 삭제되지 않습니다. seedVersion과 명시적인 ID 목록으로 개발 데이터만 정리하는 별도 단계가 필요합니다. 운영 고객 리뷰 전체 삭제를 시드 초기화로 사용하지 마세요.

Firestore seed data 설계: 리뷰 더미 데이터 구조 잡기 적용 흐름을 설명하는 두 번째 본문 이미지

서버 SDK 선택과 한계

Admin SDK는 Rules가 아닌 IAM 권한으로 접근합니다. 로컬 개발에서는 Firestore Emulator의 demo- 프로젝트로 제한하고, 실제 개발 프로젝트를 쓸 때는 실행 대상과 자격 증명을 별도로 확인합니다. 크기가 큰 시드는 요청 크기·인덱스·속도에 맞춰 나누고 실패 배치를 재시도합니다. 리뷰 저장과 상품 평점 집계를 따로 성공시킨 뒤 일관되다고 주장하지 말고 트랜잭션 또는 재계산 작업을 설계합니다.

직접 해 볼 확인

makeReviews("demo", 6)을 두 번 호출해 ID·평점·날짜가 같은지 비교하세요. count 0은 빈 배열, count 101은 오류가 기대 결과입니다. 실제 저장 후 같은 시드를 두 번 실행해 문서 수가 증가하지 않는지 확인하고, productId 필터·createdAt 정렬의 인덱스는 실제 개발 Firestore에서도 확인합니다.

같은 입력의 시드가 같은지 직접 검사하기

학습용 리뷰 생성 결과

원래 demo·6 입력으로 생성한 ID·평점·날짜를 확인하세요.

예제 크게 보기 (새 탭)

앞의 전체 코드를 scripts/review-fixtures.mjs로 저장하고 아래 파일을 같은 폴더에 만드세요. Firebase 프로젝트나 자격 증명 없이 Node에서 배열의 ID·평점·날짜와 입력 경계를 확인할 수 있습니다.

scripts/check-fixtures.mjs

import { strict as assert } from 'node:assert';
import { makeReviews } from './review-fixtures.mjs';

const one = makeReviews('demo', 6);
const two = makeReviews('demo', 6);
assert.deepEqual(one, two);
assert.deepEqual(one.map((item) => item.rating), [1, 2, 3, 4, 5, 1]);
assert.deepEqual(one.map((item) => item.id),
  Array.from({ length: 6 }, (_, n) => `seed-v1-demo-${n}`));
assert.equal(one[0].createdAt.toISOString(), '2026-01-01T00:00:00.000Z');
assert.equal(one[5].createdAt.toISOString(), '2026-01-06T00:00:00.000Z');
assert.deepEqual(makeReviews('demo', 0), []);
assert.throws(() => makeReviews('demo', 101), /0~100/);
assert.throws(() => makeReviews('bad/id', 1), /상품 ID/);
console.log('8 fixture checks passed');
node scripts/check-fixtures.mjs

실제 실행에서 ‘8 fixture checks passed’와 종료 코드 0을 확인했습니다. 이 결과는 네트워크 없는 데이터 생성 함수만 검증합니다. 스스로 바꿔 보기: count를 6에서 5로 줄이면 생성 배열에는 여섯 번째 ID가 사라지지만, 이미 Firestore에 쓴 여섯 번째 문서도 자동 삭제될까요? setDoc 재실행은 기존의 남은 문서를 지우지 않습니다. 개발 DB에서 재시드·정리 범위는 별도로 검사하세요.

직접 확인할 결과

Node에서 동일 입력·0·상한·평점 범위 확인
실제 DB 저장/인덱스는 별도 확인 필요

검증 범위와 기준일

공식 문서 확인일: 2026-09-13. 웹 SDK 예제는 모듈형 API 기준입니다. 이 글의 코드·구조 정적 검토와 실제 클라우드 인증·저장·배포 검증을 구분합니다. 본인 개발 Firebase 프로젝트의 실제 인증·권한·배포 요청은 이 편집 환경에서 실행하지 않았습니다.

이어서 학습하기

공식 문서

이 글이 도움이 되었나요?

조회 중

읽음 기록

읽음 — / 전체 20개 · 필수 14개

이 글을 쓴 해비

웹사이트를 제작·운영하고, 개인 서비스와 자동화·AI 도구를 만듭니다. 직접 만들며 배운 내용과 문제 해결 과정을 BlogFlow에 기록합니다.

새 글 받아보기

RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.

RSS 피드 구독하기

댓글 남기기