본문으로 건너뛰기 Firebase 완벽 가이드 | Authentication·Firestore

Firebase 완벽 가이드 | Authentication·Firestore

Firebase 완벽 가이드 | Authentication·Firestore

이 글의 핵심

Firebase로 풀스택 앱을 구축하는 완벽 가이드. Authentication, Firestore, Storage, Cloud Functions, Hosting, Analytics까지 실전 예제로 정리. Start now.

이 글의 핵심

Firebase로 풀스택 앱을 구축하는 완벽 가이드입니다. Authentication, Firestore, Storage, Cloud Functions, Hosting, Analytics까지 실전 예제로 정리했습니다.

실무 경험 공유: 스타트업 MVP를 Firebase로 구축하면서, 백엔드 개발 없이 2주 만에 출시하고 초기 인프라 비용을 제로로 만든 경험을 공유합니다.

들어가며: “백엔드 개발이 부담돼요”

실무에서 마주치는 문제들

인증 구현이 복잡해요

JWT, 세션, OAuth를 직접 구현해야 합니다. Firebase는 내장되어 있습니다. 데이터베이스 설정이 번거로워요

PostgreSQL 설치, 스키마 설계가 필요합니다. Firestore는 즉시 사용 가능합니다. 파일 업로드 서버가 필요해요

S3 설정이 복잡합니다. Firebase Storage는 간단합니다.

1. Firebase란?

핵심 특징

Firebase는 Google의 백엔드 서비스 플랫폼입니다. 주요 서비스

  • Authentication: 인증

  • Firestore: NoSQL 데이터베이스

  • Storage: 파일 저장소

  • Cloud Functions: 서버리스 함수

  • Hosting: 정적 호스팅

  • Analytics: 사용자 분석 가격

  • Spark (무료): 50K reads/day

  • Blaze (종량제): $0.06 / 100K reads


2. 프로젝트 설정

Firebase 프로젝트 생성

  1. https://console.firebase.google.com/
  2. “프로젝트 추가” 클릭
  3. 프로젝트 이름 입력

SDK 설치

npm install firebase

초기화

// src/lib/firebase.ts
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
import { getStorage } from 'firebase/storage';
const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "your-app.firebaseapp.com",
  projectId: "your-project-id",
  storageBucket: "your-app.appspot.com",
  messagingSenderId: "123456789",
  appId: "1:123456789:web:abcdef",
};
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const db = getFirestore(app);
export const storage = getStorage(app);

3. Authentication

이메일/비밀번호

import { auth } from './lib/firebase';
import {
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  signOut,
  onAuthStateChanged,
} from 'firebase/auth';
// 회원가입
async function signUp(email: string, password: string) {
  const userCredential = await createUserWithEmailAndPassword(auth, email, password);
  return userCredential.user;
}
// 로그인
async function signIn(email: string, password: string) {
  const userCredential = await signInWithEmailAndPassword(auth, email, password);
  return userCredential.user;
}
// 로그아웃
async function logout() {
  await signOut(auth);
}
// 인증 상태 감지
onAuthStateChanged(auth, (user) => {
  if (user) {
    console.log('Logged in:', user.email);
  } else {
    console.log('Logged out');
  }
});

Google 로그인

import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
const provider = new GoogleAuthProvider();
async function signInWithGoogle() {
  const result = await signInWithPopup(auth, provider);
  return result.user;
}

4. Firestore

데이터 추가

import { db } from './lib/firebase';
import { collection, addDoc, doc, setDoc } from 'firebase/firestore';
// 자동 ID
const docRef = await addDoc(collection(db, 'users'), {
  name: 'John',
  email: 'john@example.com',
  createdAt: new Date(),
});
// 커스텀 ID
await setDoc(doc(db, 'users', 'user123'), {
  name: 'John',
  email: 'john@example.com',
});

데이터 조회

import { collection, getDocs, doc, getDoc, query, where, orderBy, limit } from 'firebase/firestore';
// 전체 조회
const querySnapshot = await getDocs(collection(db, 'users'));
querySnapshot.forEach((doc) => {
  console.log(doc.id, doc.data());
});
// 단일 조회
const docSnap = await getDoc(doc(db, 'users', 'user123'));
if (docSnap.exists()) {
  console.log(docSnap.data());
}
// 쿼리
const q = query(
  collection(db, 'posts'),
  where('published', '==', true),
  orderBy('createdAt', 'desc'),
  limit(10)
);
const snapshot = await getDocs(q);

실시간 리스너

import { onSnapshot } from 'firebase/firestore';
const unsubscribe = onSnapshot(collection(db, 'posts'), (snapshot) => {
  const posts = snapshot.docs.map((doc) => ({
    id: doc.id,
    ...doc.data(),
  }));
  console.log('Posts:', posts);
});
// 구독 해제
unsubscribe();

5. Storage

파일 업로드

import { storage } from './lib/firebase';
import { ref, uploadBytes, getDownloadURL } from 'firebase/storage';
async function uploadFile(file: File) {
  const storageRef = ref(storage, `uploads/${Date.now()}-${file.name}`);
  
  const snapshot = await uploadBytes(storageRef, file);
  const downloadURL = await getDownloadURL(snapshot.ref);
  
  return downloadURL;
}

React 예제

import { useState } from 'react';
function FileUpload() {
  const [url, setUrl] = useState(');
  const [uploading, setUploading] = useState(false);
  const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    setUploading(true);
    const downloadURL = await uploadFile(file);
    setUrl(downloadURL);
    setUploading(false);
  };
  return (
    <div>
      <input type="file" onChange={handleUpload} disabled={uploading} />
      {uploading && <p>Uploading...</p>}
      {url && <img src={url} alt="Uploaded" />}
    </div>
  );
}

6. Cloud Functions

설치

npm install -g firebase-tools
firebase login
firebase init functions

함수 작성

// functions/src/index.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();
// HTTP 함수
export const helloWorld = functions.https.onRequest((request, response) => {
  response.json({ message: 'Hello from Firebase!' });
});
// Firestore 트리거
export const onUserCreate = functions.firestore
  .document('users/{userId}')
  .onCreate(async (snap, context) => {
    const user = snap.data();
    console.log('New user:', user);
    // 환영 이메일 전송 등
    await admin.firestore().collection('emails').add({
      to: user.email,
      subject: 'Welcome!',
      body: 'Thanks for signing up!',
    });
  });
// 스케줄 함수
export const dailyCleanup = functions.pubsub
  .schedule('0 0 * * *')  // 매일 자정
  .onRun(async (context) => {
    console.log('Running daily cleanup');
    // 정리 작업
  });

배포

firebase deploy --only functions

7. Hosting

배포

# 초기화
firebase init hosting
# 빌드
npm run build
# 배포
firebase deploy --only hosting

firebase.json

{
  "hosting": {
    "public": "dist",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "headers": [
      {
        "source": "**/*.@(jpg|jpeg|gif|png|webp)",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "max-age=31536000"
          }
        ]
      }
    ]
  }
}

8. Security Rules

Firestore Rules

// firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 공개 읽기, 인증된 사용자만 쓰기
    match /posts/{postId} {
      allow read: if true;
      allow write: if request.auth != null;
    }
    // 본인 데이터만 접근
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

Storage Rules

// storage.rules
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /uploads/{userId}/{fileName} {
      allow read: if true;
      allow write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

취업·면접과 연결하기

Firestore 규칙·Auth·Functions는 BaaS·보안 질문으로 잘 이어집니다. 기술 면접 완벽 대비 가이드와, 이력서에 서비스 규모·기능을 쓰는 법은 개발자 이력서·서류·면접 가이드를 보세요.

정리 및 체크리스트

핵심 요약

  • Firebase: Google의 BaaS 플랫폼
  • Authentication: 간편한 인증
  • Firestore: 실시간 NoSQL DB
  • Storage: 파일 저장소
  • Cloud Functions: 서버리스
  • Hosting: 정적 호스팅

구현 체크리스트

  • Firebase 프로젝트 생성
  • Authentication 구현
  • Firestore CRUD 구현
  • Storage 파일 업로드
  • Cloud Functions 작성
  • Security Rules 설정
  • Hosting 배포

같이 보면 좋은 글


이 글에서 다루는 키워드

Firebase, BaaS, Authentication, Firestore, Cloud Functions, Google Cloud

자주 묻는 질문 (FAQ)

Q. Firebase vs Supabase, 어떤 게 나은가요?

A. Firebase는 더 성숙하고 기능이 많습니다. Supabase는 오픈소스이고 PostgreSQL을 사용합니다. 빠른 개발은 Firebase, SQL이 필요하면 Supabase를 권장합니다.

Q. 비용이 얼마나 나오나요?

A. 무료 플랜으로 시작 가능합니다. 트래픽이 늘면 종량제로 전환하세요. 대부분의 스타트업은 월 $25 미만입니다.

Q. 프로덕션에서 사용해도 되나요?

A. 네, Duolingo, The New York Times 등 많은 앱이 Firebase를 사용합니다.

Q. 오프라인 지원이 되나요?

A. 네, Firestore는 오프라인 캐싱을 지원합니다.