안녕하세요 😊 지난 글에서는 Firebase 프로젝트 만들기와 앱 등록 방법을 아주 자세히 배웠죠? 이제 그다음 단계로, Firebase Realtime Database(RTDB) 를 Flutter 앱에서 직접 사용해보는 시간이에요! 이번 글에서는 데이터를 만들고(Create), 읽고(Read), 수정하고(Update), 삭제(Delete) 하는 방법을 아주 쉽게 알려드릴게요.
아주아주 쉬운 예시와 함께, 프로그래밍 초보자분들도 “아~ 이거 이렇게 쓰는 거구나!” 하고 이해할 수 있도록 설명드릴게요 😊
📌 Firebase Realtime Database란?
먼저 간단히 RTDB가 뭔지부터 짚고 갈게요! Realtime Database는 이름 그대로 데이터를 실시간(Real-time) 으로 저장하고 불러올 수 있는 Firebase의 데이터 저장소예요. 예를 들어, 어떤 유저가 앱에서 데이터를 바꾸면 실시간으로 다른 사람의 앱에도 바로바로 반영돼요!
예를 들면 우리가 카카오톡에서 메세지를 보냈을 때 그 데이터가 DB에 저장되는데 이 저장된 메세지가 다른 사람 앱에서도 실시간으로 바로 새로운 메세지가 온 게 보여요!
(이걸 실시간 동기화라고 해요)
👦🏻 "엄마, 나 점수 올렸어!"
👩🏻 "앱에 바로 반영되네~?"
이게 바로 Realtime Database의 매력이에요 😊
1. Firebase 프로젝트 & Flutter 연결하기
RTDB를 쓰려면 먼저 패키지를 설치하고 Firebase 연결을 해야 해요. 혹시 아직 Firebase와 Flutter를 연결하지 않았다면, 먼저 아래 글을 참고해서 설정해주세요. 👇
📌 Firebase 프로젝트 만들고 Flutter 앱에 연결하기
연결이 끝났다면 이제 본격적으로 RTDB를 사용해볼까요?
2. Firebase Realtime Database 설정하기
이제 Firebase 콘솔에서 RTDB를 활성화해야 해요. Firebase console에 들어가서 좌측의 빌드 탭에서 Realtime Database를 선택해주세요.
그리고 "데이터 베이스 만들기" 버튼을 클릭하세요.
DB위치는 기본값인 미국(us-central1)로 그대로 진행하면 돼요.
보안 규칙은 테스트모드로 진행하면 돼요. 대신 한달 동안만 사용할 수 있는 규칙으로 기본 설정되기 때문에 그 이후에 사용하기 위해서는 보안 규칙을 나중에 수정해주셔야 해요.
짜쟌! 이제 DB가 생성이 완료되었습니다.
3. Flutter 프로젝트에서 RTDB 패키지 추가하기
이제 Firebase RTDB를 사용하려면 관련 패키지를 추가해야 해요. pubspec.yaml 파일을 열고 firebase_database를 추가해주세요.
(저장하면 자동으로 설치되지만, 안되는 경우에는 터미널에서 flutter pub get을 실행해주세요.)
4. CRUD 기능 구현하기
4-1. 데이터 추가하기 (Create)
예를 들어, 사용자 정보를 Firebase에 저장하고 싶다면? 아래처럼 "users" 라는 경로에 데이터를 저장할 수 있어요.
import 'package:firebase_database/firebase_database.dart';
final databaseRef = FirebaseDatabase.instance.ref(); // RTDB 참조
void createUser() {
databaseRef.child("users").push().set({
"name": "홍길동",
"age": 25,
"email": "hong@example.com"
});
}
- .child("users") → users 폴더 안에 데이터 저장
- .push() → 랜덤한 키값을 생성해서 저장
- .set({...}) → 데이터를 저장하는 함수
4-2. 데이터 불러오기 (Read)
저장된 데이터를 가져오는 방법도 아주 쉬워요!
void readUsers() {
databaseRef.child("users").onValue.listen((DatabaseEvent event) {
final data = event.snapshot.value;
print("불러온 데이터: $data");
});
}
- .onValue.listen() → 데이터가 변경될 때마다 자동 업데이트
- event.snapshot.value → 현재 저장된 데이터 가져오기
4-3. 데이터 수정하기 (Update)
void updateUser(String userId) {
databaseRef.child("users/$userId").update({
"age": 30
});
}
- .update({...}) → 일부 필드만 수정할 때 사용
- 기존 name, email 값은 그대로 두고 age 값만 변경됨!
4-4. 데이터 삭제하기 (Delete)
마지막으로 데이터를 삭제하는 방법도 알아볼게요.
void deleteUser(String userId) {
databaseRef.child("users/$userId").remove();
}
- .remove() → 특정 데이터 삭제
- users 안에 있는 해당 userId 데이터만 삭제됨
5. 데모 앱 구현해보기
기본 Flutter 코드를 기반으로 수정해서 Firebase RTDB를 테스트해볼 수 있는 데모 앱 코드를 공유해드릴게요. main.dart를 다음과 같이 수정해주세요.
// main.dart
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter_demo/firebase_options.dart';
import 'package:flutter_demo/realtime_database.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
void _incrementCounter() {
setState(() {
createUser();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text("Firebase RTDB CRUD Demo"),
),
body: StreamBuilder(
stream: listenUsers(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text("Error: ${snapshot.error}"));
}
if (snapshot.hasData) {
var data = snapshot.data!.snapshot.value;
if (data is Map<Object?, Object?>) {
var convertedData = convertMap(data);
var users = convertedData.values.toList();
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
Map<String, dynamic> user = users[index];
return Row(
children: [
Expanded(
child: ListTile(
title: Text(user['name'] ?? '이름 없음'),
subtitle: Text(
'Age: ${user['age'] ?? '나이 없음'} / Email: ${user['email'] ?? '이메일 없음'}',
),
),
),
SizedBox(
width: 80,
height: 20,
child: ElevatedButton(
onPressed: () {
deleteUser(convertedData.keys.toList()[index]);
},
child: Text("삭제"),
),
),
],
);
},
);
}
}
return Center(child: Text("데이터가 없습니다"));
},
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
그리고 realtime_database.dart 라는 파일을 main.dart와 같은 폴더에 만들고 아래 내용을 입력해보세요.
// realtime_database.dart
import 'dart:async';
import 'package:firebase_database/firebase_database.dart';
final databaseRef = FirebaseDatabase.instance.ref(); // RTDB 참조
// Create - 데이터 생성
void createUser() {
databaseRef.child("users").push().set({
"name": "홍길동",
"age": 25,
"email": "hong@example.com",
});
}
// Read - 데이터 읽기 (실시간 업데이트)
Stream<DatabaseEvent> listenUsers() {
return databaseRef.child("users").onValue;
}
// Read - 데이터 읽기 (한번만)
void getUser(String userId) {
databaseRef.child("users/$userId").get().then((DataSnapshot snapshot) {
final data = snapshot.value;
print("읽어온 데이터: $data");
});
}
// Update - 데이터 수정
void updateUser(String userId) {
databaseRef.child("users/$userId").update({"age": 30});
}
// Delete - 데이터 삭제
void deleteUser(String userId) {
databaseRef.child("users/$userId").remove();
}
Map<String, dynamic> convertMap(Map<Object?, Object?> map) {
return map.map((key, value) {
if (value is Map<Object?, Object?>) {
value = convertMap(value);
} else if (value is List) {
value = convertList(value);
}
return MapEntry(key.toString(), value);
});
}
List convertList(List items) {
return items.map((item) {
if (item is Map<Object?, Object?>) {
return convertMap(item);
} else if (item is List) {
return convertList(item);
}
return item;
}).toList();
}
위 내용들을 복사하고 실행하면, 다음과 같은 앱이 실행돼요. + 버튼을 누르면 createUser 함수가 호출되고, /users reference에 있는 유저 목록을 보여주는 앱이에요.
"+" 버튼을 눌러서 유저를 추가하거나 "삭제" 버튼을 눌러서 유저를 삭제해볼 수 있어요! update는 직접 수정할 수 있는 버튼 Widget을 추가해서 구현해보시면 좋을 것 같아요.
유저를 삭제하거나 추가하면서, Firebase Console에서 데이터가 실시간으로 변하는 것을 확인할 수 있어요. 앱에서는 Firebase에 저장되어 있는 데이터를 listen해서 stream으로 받고 있기 때문에 삭제된 정보가 실시간으로 반영되서 유저 목록이 바로바로 갱신되는 거에요.
마무리 – Firebase RTDB로 CRUD 완성!
우리는 오늘 Firebase Realtime Database에서
- 데이터를 추가(Create)하고,
- 불러오고(Read),
- 수정(Update),
- 삭제(Delete)하는 방법을 배웠어요!
샘플 앱 코드도 중간에 있으니 실행해보면서 Realtime Database가 어떻게 작동하는지 쉽게 실습해볼 수 있어요. 여러 개의 시뮬레이터나 기기에서 앱을 실행해보면 모든 앱에서 데이터 변경사항이 실시간으로 반영되는 것을 확인할 수 있을 거에요.
이제 기본적인 데이터베이스 활용은 충분히 할 수 있게 되었어요. 이제 다음 글에서는 Realtime Database의 reference개념과, reference에서 사용할 수 있는 CRUD 관련된 함수 전체를 톺아보면서 어떤 때에 어떤 함수를 어떻게 써야하는지 상세하게 알아보고, 그리고 RTDB를 사용할 때의 꿀팁과 주의 사항에 대해서 알아볼게요. 🔥 꿀팁 대방출이에요!
혹시 궁금한 점이 있다면 댓글로 질문해 주세요! 😊 그럼 다음 글에서 또 만나요! 🙌
'1인 개발' 카테고리의 다른 글
Firebase Realtime Database 데이터 설계하는 법 – 처음부터 깔끔하게! (0) | 2025.03.30 |
---|---|
Flutter + Firebase Realtime Database 심화 CRUD 완전 분석! (0) | 2025.03.30 |
Firebase 프로젝트 만들고 Flutter 앱에 등록하기 (기초부터 찬찬히 알려드려요) (0) | 2025.03.23 |
혼자 앱 만들 때 딱! 클라우드 DB 완벽 비교 (Firebase, Supabase, PocketBase 등) (0) | 2025.03.16 |
앱 개발 혼자 할 때 꼭 알아야 할 클라우드 데이터베이스 (0) | 2025.03.16 |