Firexport가이드
Firestore 데이터를 Excel로 내보내는 방법
Excel은 Firestore를 직접 읽을 수 없으므로 어떤 길이든 파일을 거칩니다. Excel에서 여는 CSV이거나, 스크립트가 대신 써 주는 .xlsx입니다. 파일을 얻는 것은 쉬운 부분입니다. Excel이 글자를 깨뜨리거나, 앞자리 0을 떼거나, 모든 것을 한 열에 욱여넣지 않게 여는 것이 대부분의 사람이 막히는 지점이고, 이 가이드는 그것도 다룹니다.
2026년 9월 24일 업데이트. 방법 1의 확장 프로그램 Firexport는 저희가 만든 것입니다. 방법 2에는 필요 없습니다.
짧은 답
- 지금 당장 쿼리 하나의 결과만: 콘솔의 쿼리 빌더(Query builder)에서 브라우저 확장 프로그램으로 CSV를 내보낸 뒤, 데이터 > 텍스트/CSV에서(Data > From Text/CSV)로 가져옵니다. 방법 1
- 컬렉션 전체를, 숫자와 날짜의 형식까지 잡힌 채로: .xlsx 파일을 쓰는 Admin SDK 스크립트. 방법 2
- Excel 대신 Google Sheets: 어느 파일이든 파일 > 가져오기(File > Import)로 가져옵니다. Google Sheets
1. Firebase 콘솔에서 CSV를 내보낸 뒤 Excel에서 열기
Firebase 콘솔의 Firestore 페이지에는 쿼리를 실행해 결과를 표로 보여 주는 쿼리 빌더(Query builder)가 있지만, 그 결과를 내려받을 방법은 없습니다. Firexport는 그 결과 옆에 내보내기 버튼을 추가하는 무료 Chrome 확장 프로그램입니다.
- Chrome 웹 스토어에서 Firexport를 설치합니다.
- Firebase 콘솔에서 Firestore Database를 열고 패널 뷰(Panel view)에서 쿼리 빌더(Query builder)로 전환합니다(데이터 탭의 오른쪽 위).
- 쿼리 범위(Query scope)와 경로(Path)에서 컬렉션을 고르고, 필요하면 필터나 제한을 더한 뒤 실행(Run)을 클릭합니다.
- 결과 위의 내보내기를 클릭합니다. Firexport가 결과의 모든 페이지를 훑어 CSV 파일 하나를 내려받습니다.
- Excel에서 데이터 > 텍스트/CSV에서(Data > From Text/CSV)(데이터 가져오기 및 변환 그룹)로 가서 파일을 고르고, 미리 보기를 확인한 뒤 로드(Load)를 클릭합니다. 미리 보기가 이상하면 아래 표가 어느 설정을 바꿀지 알려 줍니다.

Firexport의 CSV는 UTF-8 바이트 순서 표시로 시작하므로 파일을 그냥 더블클릭해도 Excel이 영어가 아닌 글자를 제대로 읽습니다. 다만 더블클릭하면 Excel이 구분 기호와 형식을 추측하므로, 가져오기 대화상자가 더 안전한 길입니다. 무료 버전에서는 타임스탬프가 콘솔에 표시되는 대로 나오고(예: “August 24, 2026 at 1:16:09 PM UTC+9”) Excel은 그것을 텍스트로 둡니다. 1회 구매 라이선스인 Firexport Advanced는 Excel이 날짜로 바꿀 수 있는 ISO 8601 타임스탬프를 쓰고, 콘솔이 “…”로 잘라 버린 긴 맵과 배열을 복원합니다.
다음 Firestore 쿼리를 콘솔에서 바로, Excel에서 깔끔하게 열리는 CSV로 내보내 보세요.
Excel이 CSV를 망가뜨릴 때
어떤 방법으로 내보냈든 모든 CSV에서 생기는 일입니다. 해결책은 전부 텍스트/CSV에서(From Text/CSV) 미리 보기의 설정에 있습니다.
| 보이는 증상 | 이유 | 해결 |
|---|---|---|
| 악센트 문자나 비라틴 문자가 깨짐: “José Müller”가 “José Müller”로 보임 | CSV가 바이트 순서 표시(BOM) 없는 UTF-8이라 Excel이 시스템의 기본 인코딩으로 읽음 | BOM으로 시작하는 CSV를 쓰거나(Firexport의 CSV가 그렇습니다) 파일 원본(File Origin)을 65001: 유니코드(UTF-8)로 설정 |
| 모든 행이 A열 하나에 들어감 | 사용 지역의 목록 구분 기호가 세미콜론인데(유럽에서 흔함) 파일은 쉼표를 씀 | 구분 기호(Delimiter)를 쉼표로 설정 |
| “00123”이 123이 되고, 20자리 ID가 1.23457E+19가 됨 | Excel은 숫자처럼 보이는 것을 전부 숫자로 바꾸고, 숫자는 15자리까지만 유지함 | 데이터 형식 검색을 데이터 형식을 검색하지 않음(Do not detect data types)으로 설정해 모든 열이 텍스트로 들어오게 함 |
| 타임스탬프가 날짜가 아니라 텍스트로 정렬됨 | 바로 열면 Excel은 2026-08-24T04:16:09Z 같은 ISO 8601 텍스트를 텍스트로 둠. 형식 검색을 끄면 모든 열이 텍스트임 | 데이터 변환(Transform Data)에서 그 열의 형식을 날짜/시간/표준 시간대로 바꿈 |
맵과 배열은 셀 하나에 텍스트로 들어옵니다. 셀 하나에는 값 하나가 들어가기 때문입니다. 그 필드를 열로 펼쳐야 한다면 데이터 변환(Transform Data)에서 그 열을 선택하고 구문 분석 > JSON(Parse > JSON)을 쓴 뒤 확장합니다. 그러려면 모든 셀이 유효한 JSON이어야 하는데, Firexport Advanced와 아래 스크립트는 늘 그렇게 쓰고, 무료 버전은 값을 JSON으로 되읽을 수 없을 때 콘솔의 텍스트를 씁니다.
2. Admin SDK 스크립트로 .xlsx 파일 쓰기
스크립트는 CSV 단계를 건너뛰고 Excel 통합 문서를 바로 쓸 수 있습니다. 셀마다 처음부터 올바른 형식으로, 숫자는 숫자로, 타임스탬프는 날짜로, ID는 텍스트로 들어가서 앞자리 0이 사라지지 않습니다. Node.js와 Firestore를 읽을 수 있는 계정이 필요합니다. 프로젝트 소유자나 편집자, 또는 Cloud Datastore 뷰어 역할입니다.
- Admin SDK와 ExcelJS 설치:
npm install firebase-admin exceljs - 로컬 사용자 인증 정보로 로그인:
gcloud auth application-default login. 서버에서는 대신GOOGLE_APPLICATION_CREDENTIALS가 서비스 계정 키를 가리키게 합니다. - 아래 스크립트를
export-to-excel.mjs로 저장하고your-project-id를 바꾼 뒤node export-to-excel.mjs users를 실행합니다.
// Usage: node export-to-excel.mjs users → writes users.xlsx
import ExcelJS from 'exceljs';
import { initializeApp } from 'firebase-admin/app';
import {
getFirestore,
FieldPath,
Timestamp,
GeoPoint,
DocumentReference,
} from 'firebase-admin/firestore';
initializeApp({ projectId: 'your-project-id' });
const db = getFirestore();
const collection = process.argv[2];
if (!collection) throw new Error('Usage: node export-to-excel.mjs <collection>');
// Read the collection 1,000 documents at a time, so large collections don't time out.
const docs = [];
let last;
while (true) {
let query = db.collection(collection).orderBy(FieldPath.documentId()).limit(1000);
if (last) query = query.startAfter(last);
const page = await query.get();
if (page.empty) break;
docs.push(...page.docs);
last = page.docs[page.docs.length - 1];
}
// Firestore types become plain values: timestamps as ISO 8601, references as paths.
function plain(value) {
if (value instanceof Timestamp) return value.toDate().toISOString();
if (value instanceof DocumentReference) return value.path;
if (value instanceof GeoPoint) return { latitude: value.latitude, longitude: value.longitude };
if (value instanceof Uint8Array) return Buffer.from(value).toString('base64');
if (Array.isArray(value)) return value.map(plain);
if (value && typeof value === 'object') {
return Object.fromEntries(Object.entries(value).map(([key, v]) => [key, plain(v)]));
}
return value;
}
// A timestamp field becomes a real Excel date (in UTC). A cell holds one value, so maps and arrays
// go in as JSON text. Strings stay strings, so IDs like "00123" keep their leading zeros.
function cell(value) {
if (value instanceof Timestamp) return value.toDate();
const v = plain(value);
return v !== null && typeof v === 'object' ? JSON.stringify(v) : v;
}
const rows = docs.map((doc) => ({ documentId: doc.id, ...doc.data() }));
// Documents in one collection can have different fields, so the columns are all of them.
const columns = [...new Set(rows.flatMap((row) => Object.keys(row)))];
const workbook = new ExcelJS.Workbook();
const sheet = workbook.addWorksheet(collection.slice(0, 31), { views: [{ state: 'frozen', ySplit: 1 }] });
sheet.columns = columns.map((key) => ({ header: key, key, width: 20 }));
sheet.getRow(1).font = { bold: true };
for (const row of rows) {
const added = sheet.addRow(Object.fromEntries(columns.map((key) => [key, cell(row[key])])));
added.eachCell((c) => {
if (c.value instanceof Date) c.numFmt = 'yyyy-mm-dd hh:mm:ss';
});
}
await workbook.xlsx.writeFile(`${collection}.xlsx`);
console.log(`Wrote ${rows.length} documents to ${collection}.xlsx`);- 통합 문서에는 컬렉션 이름을 딴 시트 하나가 있고, 굵은 글씨의 고정된 머리글 행이 있습니다.
documentId열, 그다음 필드마다 열 하나입니다. - 타임스탬프는
yyyy-mm-dd hh:mm:ss로 표시되는 Excel 날짜이고 UTC입니다. 맵·배열·지오포인트는 JSON 텍스트, 참조는 문서 경로입니다. - Excel 시트 하나에는 1,048,576행이 들어가고, 스크립트는 파일을 쓸 때까지 모든 행을 메모리에 둡니다. 더 큰 컬렉션은 CSV 가이드의 gcloud와 BigQuery 경로를 쓰세요.
Google Sheets
Google Sheets는 두 파일을 모두 엽니다. 파일 > 가져오기(File > Import)로 가서 CSV나 .xlsx를 올리고, 어디에 넣을지(새 스프레드시트, 새 시트, 현재 시트) 고릅니다.
- CSV라면 구분자를 쉼표로 설정합니다(또는 자동 감지로 둡니다).
- 데이터에 앞자리 0이 있는 ID·전화번호·코드가 있다면 텍스트를 숫자, 날짜, 수식으로 변환(Convert text to numbers, dates, and formulas)의 체크를 풉니다. 그러지 않으면 Sheets가 “00123”을 123으로 바꿉니다.
- 스프레드시트 하나에는 모든 시트를 합쳐 총 1,000만 개의 셀이 들어갑니다.
FAQ
Excel이 Firestore에 직접 연결할 수 있나요?
기본 커넥터로는 안 됩니다. Excel의 데이터 가져오기에는 Firestore 원본이 없습니다. 이 가이드처럼 먼저 파일을 내보냅니다. Excel이 가져오는 CSV이거나 스크립트가 쓰는 .xlsx입니다.
CSV에서 Excel이 “José” 같은 깨진 글자를 보여 주는 이유는 무엇인가요?
파일이 UTF-8이지만 바이트 순서 표시가 없어서 Excel이 시스템의 기본 인코딩으로 읽기 때문입니다. BOM으로 시작하는 CSV를 쓰거나(Firexport의 CSV가 그렇습니다), 데이터 > 텍스트/CSV에서(Data > From Text/CSV)로 가져오면서 파일 원본(File Origin)을 65001: 유니코드(UTF-8)로 설정하세요.
Excel이나 Google Sheets에는 행이 몇 개까지 들어가나요?
Excel 워크시트 하나에는 1,048,576행이 들어가고, 셀 하나에는 최대 32,767자가 들어갑니다. Google Sheets 스프레드시트 하나에는 총 1,000만 개의 셀이 들어갑니다. 더 큰 컬렉션은 gcloud와 BigQuery로 CSV를 내보내고 거기서 데이터를 다루세요.
Firestore 데이터를 내보내면 비용이 드나요?
어떤 방법이든 내보내는 문서마다 최소 한 번은 읽고, Firestore는 그것을 문서 읽기로 과금합니다. 일일 무료 할당량 안에서는 비용이 없습니다.
