Firebase 연동 — 인증, Firestore, 스토리지
Firebase는 인증, 데이터베이스, 스토리지, 푸시 알림까지 BaaS(Backend as a Service)로 빠르게 백엔드를 구축할 수 있게 해줍니다.
별도의 서버 없이 앱을 만들거나 프로토타입을 빠르게 구현할 때 Firebase는 매우 유용합니다.
설치 (@react-native-firebase)
# 핵심 모듈
npm install @react-native-firebase/app
# 인증
npm install @react-native-firebase/auth
# Firestore
npm install @react-native-firebase/firestore
# Storage
npm install @react-native-firebase/storage
# iOS
cd ios && pod install
Authentication — 사용자 인증
import auth from '@react-native-firebase/auth';
// 이메일/비밀번호 회원가입
async function signUp(email: string, password: string) {
try {
const userCredential = await auth().createUserWithEmailAndPassword(email, password);
console.log('가입 완료:', userCredential.user.uid);
} catch (error: any) {
switch (error.code) {
case 'auth/email-already-in-use': Alert.alert('이미 사용 중인 이메일입니다'); break;
case 'auth/weak-password': Alert.alert('비밀번호가 너무 약합니다'); break;
case 'auth/invalid-email': Alert.alert('유효하지 않은 이메일입니다'); break;
}
}
}
// 로그인
async function signIn(email: string, password: string) {
try {
await auth().signInWithEmailAndPassword(email, password);
} catch (error: any) {
if (error.code === 'auth/invalid-credential') {
Alert.alert('이메일 또는 비밀번호가 올바르지 않습니다');
}
}
}
// 로그아웃
async function signOut() {
await auth().signOut();
}
// 인증 상태 감지 (실시간)
function useAuthState() {
const [user, setUser] = useState(auth().currentUser);
const [loading, setLoading] = useState(true);
useEffect(() => {
const unsubscribe = auth().onAuthStateChanged((firebaseUser) => {
setUser(firebaseUser);
setLoading(false);
});
return unsubscribe;
}, []);
return { user, loading };
}
Firestore — 데이터베이스
import firestore from '@react-native-firebase/firestore';
// 문서 추가
async function addPost(title: string, body: string) {
await firestore().collection('posts').add({
title,
body,
authorId: auth().currentUser?.uid,
createdAt: firestore.FieldValue.serverTimestamp(),
likes: 0,
});
}
// 문서 조회 (단일)
async function getPost(postId: string) {
const doc = await firestore().collection('posts').doc(postId).get();
if (doc.exists) {
return { id: doc.id, ...doc.data() };
}
return null;
}
// 컬렉션 조회 (목록)
async function getPosts() {
const snapshot = await firestore()
.collection('posts')
.orderBy('createdAt', 'desc')
.limit(20)
.get();
return snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
}
// 실시간 구독
function useRealtimePosts() {
const [posts, setPosts] = useState([]);
useEffect(() => {
const unsubscribe = firestore()
.collection('posts')
.orderBy('createdAt', 'desc')
.onSnapshot((snapshot) => {
const data = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setPosts(data);
});
return unsubscribe;
}, []);
return posts;
}
// 문서 수정
await firestore().collection('posts').doc(postId).update({
title: '수정된 제목',
updatedAt: firestore.FieldValue.serverTimestamp(),
});
// 문서 삭제
await firestore().collection('posts').doc(postId).delete();
Storage — 파일 저장
import storage from '@react-native-firebase/storage';
// 이미지 업로드
async function uploadImage(localUri: string, path: string) {
const reference = storage().ref(path);
await reference.putFile(localUri);
const downloadUrl = await reference.getDownloadURL();
return downloadUrl;
}
// 업로드 진행률 추적
function uploadWithProgress(localUri: string, path: string) {
const reference = storage().ref(path);
const task = reference.putFile(localUri);
task.on('state_changed', (snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log(`업로드: ${progress.toFixed(0)}%`);
});
return task.then(async () => {
return reference.getDownloadURL();
});
}
// 파일 삭제
await storage().ref('images/photo.jpg').delete();
실전: 프로필 이미지 + Firestore 연동
async function updateProfilePhoto(userId: string, imageUri: string) {
// 1. Storage에 이미지 업로드
const path = `profiles/${userId}/avatar.jpg`;
const downloadUrl = await uploadImage(imageUri, path);
// 2. Firestore 프로필 문서 업데이트
await firestore().collection('users').doc(userId).update({
photoUrl: downloadUrl,
updatedAt: firestore.FieldValue.serverTimestamp(),
});
// 3. Auth 프로필 업데이트
await auth().currentUser?.updateProfile({
photoURL: downloadUrl,
});
return downloadUrl;
}
보안 규칙
// Firestore 보안 규칙 (Firebase Console에서 설정)
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// 인증된 사용자만 읽기/쓰기
match /posts/{postId} {
allow read: if true;
allow create: if request.auth != null;
allow update, delete: if request.auth.uid == resource.data.authorId;
}
// 본인 프로필만 수정
match /users/{userId} {
allow read: if true;
allow write: if request.auth.uid == userId;
}
}
}
정리
- Firebase는 인증, 데이터베이스, 스토리지 를 통합적으로 제공합니다
onAuthStateChanged로 인증 상태를 실시간 감지할 수 있습니다- Firestore의
onSnapshot으로 ** 실시간 데이터 동기화 **가 가능합니다 - ** 보안 규칙 **을 반드시 설정하세요 — 기본 설정은 모든 접근을 허용합니다
- 프로덕션에서는 비용 관리를 위해 ** 쿼리 최적화와 인덱싱 **에 신경 써야 합니다
댓글 로딩 중...