Firebase CRUD 정말 간단하지만 헷갈린다,,,
그래서 나 보기 좋으라고 정리하는 CRUD
언어는 Java 기준
Firebase 데이터베이스 구조
Firebase는 NoSQL 기반의 실시간 데이터베이스로서 Firestore와 Realtime Database 두 가지 주요 데이터베이스 서비스를 제공하고 있다.
그중 사용한 데이터베이스는 FireStore로, FireStore는 JSON 기반 문서를 사용하여 데이터를 저장하고 쿼리할 수 있다.
FireStore에서는 다음과 같은 기본 요소들로 구성되어 있다.
- Database: 한개의 프로젝트 내에 여러 개의 Firestore 데이터베이스가 포함될 수 있다. 각 데이터베이스는 고유한 ID를 가지고 있다.
- Collection: 컬렉션은 문서들의 그룹을 나타낸다. 컬렉션은 데이터를 구조화하는 주요 수준의 단위.
- Document: 문서는 키-값 쌍으로 구성된 데이터 객체이다. 문서의 키(key)는 고유한 식별자를 가지며, 값(value)은 다양한 데이터 유형을 가질 수 있다.
- Field: 문서 내에서 각 데이터는 필드(field)로 저장된다. 필드는 특정 값(value)을 가지며, 필드의 이름과 해당 값으로 구성된다.
코드 예시
User.java
public class User {
private String id;
private String pw;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date birth;
private List<String> myList;
}
READ
1. 컬렉션에 있는 모든 문서를 읽어오기
// Firestore 인스턴스 가져오기
Firestore firestore = FirestoreClient.getFirestore();
try {
List<User> users = firestore.collection("User")//User컬렉션 참조
.get()// ApiFuture<QuerySnapshot> 가져오기
.get()// QuerySnapshot 가져오기
.getDocuments()// List<QueryDocumentSnapshot> 가져오기
//불러온 documents를 각각 User.class형식으로 매핑
.stream().map(document -> document.toObject(User.class)).toList();
}catch (InterruptedException | ExecutionException e) {
System.err.println("Firestore 데이터 조회 중 오류 발생: " + e);
}
2. 컬렉션에 있는 특정 문서 읽어오기
- 문서 아이디값으로 읽어오기
// Firestore 인스턴스 가져오기
Firestore firestore = FirestoreClient.getFirestore();
User user = firestore.collection("User")//User컬렉션 참조
.document("documentId")// documentId 문서 참조
.get()// ApiFuture<DocumentSnapshot> 가져오기
.get()// DocumentSnapshot 가져오기
.toObject(User.class)// User형식으로 변환해서 가져오기
- 조건에 따라 문서 읽어오기
Firebase Firestore에서는 다양한 조건을 사용하여 문서를 검색할 수 있다.
- whereEqualTo(fieldPath, value) : 특정 필드(fieldPath)의 값이 주어진 값(value)과 정확히 일치하는 문서를 검색한다.
- whereGreaterThan(fieldPath, value) : 특정 필드(fieldPath)의 값이 주어진 값(value)보다 큰 문서를 검색한다.
- whereLessThan(fieldPath, value) : 특정 필드(fieldPath)의 값이 주어진 값(value)보다 작은 문서를 검색한다.
- whereGreaterThanOrEqualTo(fieldPath, value) : 특정 필드(fieldPath)의 값이 주어진 값(value)보다 크거나 같은 문서를 검색한다.
- whereLessThanOrEqualTo(fieldPath, value) : 특정 필드(fieldPath)의 값이 주어진 값(value)보다 작거나 같은 문서를 검색한다.
- whereArrayContains(fieldPath, value) : 특정 필드(fieldPath)가 배열인 경우, 해당 필드의 배열에 주어진 값(value)이 포함된 문서를 검색한다.
- orderBy(fieldPath) : 특정 필드(fieldPath)를 기준으로 결과를 정렬한다. 기본적으로 오름차순이다.
- limit(limit) : 검색 결과의 최대 개수를 제한한다.
ex1) id 필드값이 'yooon'인 Document
// Firestore 인스턴스 가져오기
Firestore firestore = FirestoreClient.getFirestore();
// 가져올 문서가 한개인 경우
User user = firestore.collection("User")//User컬렉션 참조
.whereEqualTo("id", "yooon")
.get()
.get()
.getDocuments().get(0)//조건에 해당하는 첫번째 문서 가져오기
.toObject(User.class);
// 가져올 문서가 여러개인 경우
List<Test> users = firestore.collection("User")//User컬렉션 참조
.whereEqualTo("id", "yooon")
.get()
.get()
.getDocuments()
.stream().map(document -> document.toObject(Test.class)).toList();
ex2) 필드값으로 조건 검색해서 DocumentId 읽어오기
// 가져올 문서가 한개인 경우
String documentId = firestore.collection("User")//User컬렉션 참조
.whereEqualTo("id", "yooon")
.get()
.get()
.getDocuments().get(0)//조건에 해당하는 첫번째 문서 가져오기
.getId();
// 가져올 문서가 여러개인 경우
List<String> documentIds = firestore.collection("User")
.whereEqualTo("id", "yooon")
.get()
.get()
.getDocuments()
.stream() // 문서들을 Stream으로 변환
.map(QueryDocumentSnapshot::getId) // 각 문서의 ID를 추출
.collect(Collectors.toList()); // List로 수집
- 조건결합하기
위의 검색 조건들을 필요에 따라 결합하여 복합적인 쿼리를 만들 수 있다.
ex)
collectionRef.whereEqualTo("department", "IT").orderBy("salary", Query.Direction.DESCENDING);
3. 특정 문서의 하위 컬렉션 문서 읽어오기
// Firestore 인스턴스 가져오기
Firestore firestore = FirestoreClient.getFirestore();
List<Post> posts = firestore.collection("User")// User컬렉션 참조
.document(userId)//DocumentId가 userId인 문서 참조
.collection("Post")//해당 문서의 Post컬렉션 참조
.get()
.get()
.getDocuments()// 문서 가져오기
.stream().map(document -> document.toObject(Post.class))// Post형식으로 매핑
.collect(Collectors.toList());
4. 사진 읽어오기
사진을 읽어올때는 저장한 사진 경로를 데이터베이스에 저장을 해두고 경로에 따라 사진을 읽어왔다.
[Firebase Storage 시작하기]
2024.05.13 - [SpringBoot/Project] - Firebase Storage 시작하기
데이터베이스에 저장되어있는 파일 경로를 이용하여 파일을 불러온다.
해당 코드를 통해 다운로드 URL을 반환받으면 프론트에서
`<img src="다운로드URL" alt="이미지">` 이미지 태그안에 해당 값을 넣어 이미지를 볼 수 있다.
사진을 불러올때는 항상 유효시간을 설정하여 다운로드 링크를 생성한 후 링크를 보내줘야하는데 그렇게되면 링크가 길어지고 복잡해지기 때문에 storage 규칙에서 read는 모든 사용자에게 허용을 해준 후 토큰없이 다음 URL을 통해 불러왔다.
https://firebasestorage.googleapis.com/v0/b/버킷이름.appspot.com/o/<파일경로>?alt=media
URL에 각각 해당하는 값을 넣어주면 token값 없이 사진을 읽을 수 있다.
또한 이미지 파일 경로에 한글이 있으면 깨지기 때문에 utf-8로 인코딩을 해주었다.
public String getFile() throws IOException{
String imagePath = "firebase.png"; // 이미지 파일 경로
String encodedImgPath = URLEncoder.encode(imagePath, "UTF-8");
String encodedURL = "https://firebasestorage.googleapis.com/v0/b/goody-4b16e.appspot.com/o/"+ encodedImgPath + "?alt=media";
return encodedURL;
}
CREATE
데이터 설정
데이터는 User 형식대로 설정하였다.
//Date 데이터 설정을 위한 Calendar 객체 생성
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2002);
calendar.set(Calendar.MONTH, Calendar.APRIL);
calendar.set(Calendar.DAY_OF_MONTH, 24);
// Calendar에서 Date로 변환
Date birthDate = calendar.getTime();
//list
List<String> list = List.of("11", "22");
//데이터 설정
Test data = new Test("yooon","qwe123",birthDate,list);
1. 컬렉션에 새로운 문서 저장
저장할 위치로 이동해 `.add()` 메소드 사용
//데이터 저장
//firebase 초기설정
Firestore firestore = FirestoreClient.getFirestore();
//User 컬렉션 밑에 새로운 문서를 생성하고 저장함
ApiFuture<DocumentReference> result = firestore.collection("User")// User 컬렉션 참조
.add(data);// 데이터 저장
// 작성 결과 가져오기
DocumentReference documentReference = result.get();
// 작성된 문서의 아이디
String docId = documentReference.getId();
2. 특정 문서의 하위 컬렉션에 데이터를 저장
그냥 하위 컬렉션을 참조해서 .add(data)만 해주면 된다.
ex) DocumentID를 모르는 경우 : User 컬렉션에서 id 필드값이 'yooon'인 Document의 컬렉션에 데이터를 저장할때
//컬렉션 밑에 새로운 문서를 생성하고 저장함
ApiFuture<DocumentReference> result = firestore.collection("User")// User 컬렉션 참조
.whereEqualTo("id", "yooon")// 조건
.get().get()// 가져오기
.getDocuments().get(0)// 조회된 결과의 첫번째 문서 참조
.getReference()
.collection("Post")// Post 컬렉션 참조
.add(data);// 데이터 저장
// 작성 결과 가져오기
DocumentReference documentReference = result.get();
// 작성된 문서의 아이디
String docId = documentReference.getId();
ex2) DocumentId를 아는경우
ApiFuture<DocumentReference> result = firestore.collection("User")
.document(documentId)// 문서아이디에 해당하는 문서 참조
.collection("Post")// 해당 문서의 하위 Post 컬렉션 참조
.add(data);// 데이터 저장
3. Firebase에서 사진 저장
firebase에서 사진은 storage에 따로 저장/관리를 한다.
firebase에서 사진을 저장할때는 `bucket.create()` 메서드를 사용한다.
- 첫 번째 파라미터(path + "/" + fileName): 업로드할 파일의 전체 경로와 파일 이름을 지정
- 두 번째 파라미터(new FileInputStream(localFilePath)): 업로드할 파일의 InputStream을 제공
- 세 번째 파라미터("image/png"): 업로드할 파일의 MIME 유형을 지정
예시
* 사진을 저장할때 front에서 multipartFile형식으로 받아와서 사용하는 경우
public String uploadFile(MultipartFile multipartFile) throws IOException{
String path = "Img";//storage 내 이미지를 업로드 할 경로
String bucketName = FirebaseApp.getInstance().getOptions().getStorageBucket(); // Firebase Storage 버킷 이름
Bucket bucket = StorageClient.getInstance().bucket(bucketName);//버킷 가져오기
InputStream content = new ByteArrayInputStream(multipartFile.getBytes());
Blob blob = bucket.create(path+"/"+multipartFile.getOriginalFilename(),content,multipartFile.getContentType());
return blob.getName();
}
* 정해진 경로에 있는 사진을 업로드하는 경우
public String uploadFile() throws IOException{
String path = "Img";//storage 내 이미지를 업로드 할 경로
String bucketName = FirebaseApp.getInstance().getOptions().getStorageBucket(); // Firebase Storage 버킷 이름
Bucket bucket = StorageClient.getInstance().bucket(bucketName);// 버킷 가져오기
// 로컬 파일 경로
String localFilePath = "C:\\Users\\IdeaProjects\\my_project\\src\\main\\resources\\firebase.png";
String fileName = "firebase.png"; // 업로드할 파일 이름
// 파일 업로드
Blob blob = bucket.create(path+"/"+fileName, new FileInputStream(localFilePath), "image/png");
return blob.getName();
}
UPDATE
업데이트 할 데이터를 필드명과 값 쌍을 Map객체에 담아 .update(data) 함수 사용
// 업데이트할 데이터 생성
Map<String, Object> updates = new HashMap<>();
updates.put("userId", newUserId); // 기존 필드명과 새로운 값
updates.put(newFieldKey, newFieldValue); // 새로 추가할 필드명과 값 설정
// 문서의 참조 가져오기
DocumentReference docRef = firestore.collection("User").document(documentId);
// 문서 업데이트
ApiFuture<WriteResult> updateFuture = docRef.update(updates);
updateFuture.get(); // 업데이트 완료를 기다림
System.out.println("문서 업데이트 완료");
DELETE
1. 문서 전체 삭제
DocumentReference docRef = firestore.collection("User").document("yooon");
ApiFuture<WriteResult> future = docRef.delete();
future.get(); // 완료를 기다림
System.out.println("문서 삭제 완료");
2. 문서 내의 특정 필드 삭제
Map<String, Object> updates = new HashMap<>();
updates.put("age", FieldValue.delete()); // age 필드를 삭제하고자 할때
DocumentReference docRef = firestore.collection("User").document("yooon");
ApiFuture<WriteResult> future = docRef.update(updates);
future.get(); // 업데이트 완료를 기다림
System.out.println("문서 삭제 완료");
'SpringBoot > Project' 카테고리의 다른 글
[Springboot/React] #2 웹소켓과 STOMP로 실시간 채팅 구현하기 (0) | 2024.08.12 |
---|---|
Firebase Storage 시작하기 (0) | 2024.05.13 |
[Spring boot/Firebase] Spring boot와 Firebase 연결 (0) | 2024.05.13 |
[Spring boot] Spring boot와 React 이용한 굿즈 중고거래어플 프로젝트 (0) | 2024.05.13 |