이번 팀프로젝트에서는 GPS 기반의 채팅앱을 제작하게 되었다.
지난주에는 authentication을 응용하여 로그인 연동을 하려고 했다가
작업의 복잡성을 고려하여 단순하게 DB에 회원정보를 저장하고
불러오는 과정을 통해 로그인 기능을 구현하기로 했다.
firebase는 데이터를 저장할 수 있는 공간으로 활용이 가능하며 아래와 같은 장점들이 있다.
Firestore
- NoSQL 기반 데이터베이스
- 실시간 동기화 가능(값이 업데이트 되면 다시 데이터 달라고 요청할 필요 없이 감지할 수 있음)
- 오프라인 지원(오프라인에서 수정, 삭제, 읽기 등 작업을 하면 온라인으로 전환될 때 동기화함)
- 다양한 조건으로 검색 가능(’한달 이내의 포스트 데이터만 주세요~’ 가능)
NoSQL 이란?
- Not only SQL
- 기존의 데이터베이스는 일정한 형식(예를 들어서 제목, 내용, 작성자) 를 정해놓고 사용하고 항상 이 형식을 사용해야 했음
- NoSQL은 JSON 형태로 데이터가 들어가기 때문에 형식 정해놓고 저장 안해도됨. 자유로움
강의에서 배운 바로는 CRUD 기능을 구현할 수 있다고 하여 자세히 알아보았다.
📚 CRUD
- CREATE, READ, UPDATE, DELETE
firebase를 편리하게 사용할 수 있는 도구인 firebase CLI를 설치하는 것이 좋다.
(Firebase 연동 편리하게 해주는 명령줄도구)
설치페이지 - https://firebase.google.com/docs/cli
맥의 경우 터미널에서 curl -sL https://firebase.tools | bash 를 입력하면 된다.
그러고나서 firebase login을 입력하여 로그인한 후
dart pub global activate flutterfire_cli를 입력하여 연동도구를 활성화한다.
그 다음으로 flutterfire configure를 입력하면 프로젝트에 firebase가 자동으로 구성된다.
그리고 flutter pub add firebase_core를 입력하여 패키지를 추가하면 된다.
main 함수에서 firebase 초기화 코드는 아래와 같다.
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_firebase_blog_app/firebase_options.dart';
import 'package:flutter_firebase_blog_app/ui/pages/home/home_page.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
// ProviderScope 로 앱을 감싸서 RiverPod이 ViewModel 관리할 수 있게 선언
runApp(const ProviderScope(child: MyApp()));
}
이후에는 ios/Podfile에서 IOS 최소지원버전을 13으로 수정해야 사용이 가능하다.
콘솔 웹에서 앱 개요보기에 프로젝트가 추가된것을 확인한 후
flutter pub add cloud_firestore를 입력하여 패키지를 추가한다.
컬렉션 내 문서 전체 조회
Future<void> getAll() async {
// 1. FirebaseFirestore 객체 가지고오기
FirebaseFirestore firestore = FirebaseFirestore.instance;
// 2. FirebaseFirestore 객체에서 collection 메서드를 통해 posts 컬렉션에 대한 참조 가지고 오기
// 여기까지는 아무런 통신이 이루어 지지 않고 단순히 posts 컬렉션에 대한 참조만 저장!!
// (posts 컬렉션을 가지고 올거야 하고만 알려주는 단계)
CollectionReference collectionRef = firestore.collection('posts');
// 3. 컬렉션 참조에서 모든 문서(Document) 가지고오기
// 이 때 Firestore에서 데이터 가지고옴
// 결과가 QuerySnapshot 타입으로 전달됨
QuerySnapshot snapshot = await collectionRef.get();
// 4. QuerySnapshot객체 내에 docs 필드에 조회된 문서들의 결과가 들어있는데
// QueryDocumentSnapshot 라는 타입임. 즉 문서 조회 결과
List<QueryDocumentSnapshot> documentSnaphots = snapshot.docs;
// 5. QueryDocumentSnapshot에서 data 메서드를 통해 진짜 데이터 가지고올 수 있음
for (var docSnapshot in documentSnaphots) {
print(docSnapshot.data());
}
}
컬렉션 내 문서 특정 문서 조회
Future<void> getOneById() async {
// 1. FirebaseFirestore 객체 가지고오기
FirebaseFirestore firestore = FirebaseFirestore.instance;
// 2. FirebaseFirestore 객체에서 collection 메서드를 통해 posts 컬렉션에 대한 참조 가지고 오기
// 여기까지는 아무런 통신이 이루어 지지 않고 단순히 posts 컬렉션에 대한 참조만 저장!!
CollectionReference collectionRef = firestore.collection('posts');
// 3. 컬렉션 참조에서 문서 ID에 대한 문서(Document) 참조 만들기
// 파라미터로 아까 만들때 생성된 ID 값 넣으면 됨
// ID는 중복되면 안됨!!!!!
DocumentReference documentRef = collectionRef.doc('문서 ID');
// 4. 문서 참조의 정보를 기반으로 파이어스토어에서 문서 가지고옴!!!
// DocumentSnapshot 타입. 문서 조회결과
DocumentSnapshot documentSnaphot = await documentRef.get();
// 5. DocumentSnapshot의 data 메서드를 통해 진짜 데이터 가지고올 수 있음
print(documentSnaphot.data());
}
문서 생성
Future<void> insert() async {
// 1. FirebaseFirestore 객체 가지고오기
FirebaseFirestore firestore = FirebaseFirestore.instance;
// 2. FirebaseFirestore 객체에서 collection 메서드를 통해 posts 컬렉션에 대한 참조 가지고 오기
// 여기까지는 아무런 통신이 이루어 지지 않고 단순히 posts 컬렉션에 대한 참조만 저장!!
CollectionReference collectionRef = firestore.collection('posts');
// 3. 컬렉션 참조에서 문서(Document) 참조 만들기
// ID를 파라미터로 넣지 않으면 문서 생성 시 새로운 ID 부여!
DocumentReference documentRef = collectionRef.doc();
// 4. 문서에 넣을 데이터를 Map 타입으로 생성
Map<String, dynamic> data = {
'writer': '홍길동',
'title': '블로그 타이틀',
'content': '내용입니다',
'createdAt': DateTime.now().toIso8601String(),
};
// 5. 문서 참조의 set 메서드 안에 생성할 데이터 전달해주면 이때 생성!!!
await documentRef.set(data);
}
문서 수정
Future<void> udpate() async {
// 1. FirebaseFirestore 객체 가지고오기
FirebaseFirestore firestore = FirebaseFirestore.instance;
// 2. FirebaseFirestore 객체에서 collection 메서드를 통해 posts 컬렉션에 대한 참조 가지고 오기
// 여기까지는 아무런 통신이 이루어 지지 않고 단순히 posts 컬렉션에 대한 참조만 저장!!
CollectionReference collectionRef = firestore.collection('posts');
// 3. 컬렉션 참조에서 문서(Document) 참조 만들기
DocumentReference documentRef = collectionRef.doc('수정할 문서의 ID');
// 4. 수정할 데이터를 Map 타입으로 생성
Map<String, dynamic> data = {
'writer': '오상구',
};
// 5. 문서 참조의 set 메서드 안에 생성할 데이터 전달해주면 이때 수정!!!
await documentRef.set(data);
}
문서 삭제
Future<void> delete() async {
// 1. FirebaseFirestore 객체 가지고오기
FirebaseFirestore firestore = FirebaseFirestore.instance;
// 2. FirebaseFirestore 객체에서 collection 메서드를 통해 posts 컬렉션에 대한 참조 가지고 오기
// 여기까지는 아무런 통신이 이루어 지지 않고 단순히 posts 컬렉션에 대한 참조만 저장!!
CollectionReference collectionRef = firestore.collection('posts');
// 3. 컬렉션 참조에서 문서(Document) 참조 만들기
DocumentReference documentRef = collectionRef.doc('삭제할 문서의 ID');
// 4. 참조하고 있는 문서 삭제!!!
await documentRef.delete();
}