팀프로젝트로 웹 서비스를 만들었을 때 백엔드로 Firebase를 활용했던 기억이 난다.
난 그때 프론트엔드와 팀장으로서 전체 관리가 주 업무였다.
그래서 Firebase가 정확히 어떻게 돌아가는지 잘 몰랐는데 이번에 간단하게나마 배우게 된 게 꽤 좋다.
생기는 의문
위는 강의를 들으며 생성한 컬렉션과 그 문서들이다.
지금이야 데이터가 몇개 없으니 컬렉션 내의 전체 문서를 가져오는데 문제가 없다.
문서 ID가 무작위 알파벳 배열인 것도 전혀 문제가 되지 않는다.
하지만 데이터가 정말 많다면?
필요한 데이터만 골라내야 한다면?
이런 의문이 들었다.
필요한 데이터만 뽑아오기
찾아보니 역시 다 방법이 있었다.
그전에 가장 중요한 것은 `데이터 구조를 제대로 정의하는 것`이었다.
위 이미지를 보면 content
, date
, image
, title
의 4개의 필드가 있고,
나머지 문서들도 저 형식을 지키고 있다.
컬렉션 내의 문서 ID 명명 규칙도 지정할 수 있지만, 데이터의 구조를 잘 지키는 것이 중요하다.
그래야 필요한 데이터를 쉽게 가져올 수 있다.
1. 컬렉션 쿼리
가장 기본적인 방법.
where()
, orderBy()
, limit()
, startAt()
, endAt()
와 같은 쿼리 옵션을 활용하여 데이터를 조작할 수 있다.
// 특정 카테고리의 게시글만 가져오기
db.collection('posts')
.where('category', '==', 'tech')
.orderBy('createdAt', 'desc')
.limit(10) // 최신 10개만 가져옴
.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
const post = doc.data();
console.log(post);
});
})
.catch(error => {
console.error(error);
});
2. 커서
이터레이터를 사용하여 자료구조를 탐색하던 것을 떠올리면 이해가 쉽다.
// 컬렉션의 모든 문서를 순환하며 가져오기
let cursor = null;
db.collection('users')
.startAt(cursor)
.limit(10) // 한 번에 10개씩 가져옴
.get()
.then(querySnapshot => {
const lastDoc = querySnapshot.docs[querySnapshot.docs.length - 1];
cursor = lastDoc.id; // 다음 요청을 위한 커서 설정
querySnapshot.forEach(doc => {
const user = doc.data();
console.log(user);
});
if (querySnapshot.docs.length === 10) {
// 더 많은 데이터가 있는 경우 다음 요청
setTimeout(() => {
getMoreUsers();
}, 1000);
}
})
.catch(error => {
console.error(error);
});
function getMoreUsers() {
db.collection('users')
.startAt(cursor)
.limit(10)
.get()
// ... (querySnapshot 처리 동일)
}
3. 페이징
윈도우를 지정하고 그 범위 내의 데이터만 확인한다.
확인이 끝나면 윈도우를 이동하며 탐색을 반복한다.
커뮤니티 게시판에서 페이지를 이동하는 것과 같다.
// 컬렉션의 데이터를 페이지 단위로 가져오기
let page = 1;
const pageSize = 10;
db.collection('products')
.orderBy('price', 'asc')
.limit(pageSize)
.startAt((page - 1) * pageSize) // 페이지 번호에 따라 시작 문서 설정
.get()
.then(querySnapshot => {
const lastDoc = querySnapshot.docs[querySnapshot.docs.length - 1];
const nextPage = page + 1;
// 데이터 표시 및 다음 페이지 버튼 활성화/비활성화 처리
if (querySnapshot.docs.length === pageSize) {
// 다음 페이지 버튼 활성화
document.getElementById('nextPageButton').disabled = false;
} else {
// 다음 페이지 버튼 비활성화
document.getElementById('nextPageButton').disabled = true;
}
})
.catch(error => {
console.error(error);
});
document.getElementById('nextPageButton').addEventListener('click', () => {
page++;
getMoreProducts();
});
function getMoreProducts() {
db.collection('products')
// ... (페이징 처리 동일)
}
4. Batch
컬렉션 내의 데이터를 일괄로 가져오는 것이다.
여기선 user1 / 2 / 3
에 대한 문서를 배치로 가져온다.
// 여러 문서를 한 번에 가져오기
const docIds = ['user1', 'user2', 'user3'];
db.collection('users')
.whereIn('uid', docIds)
.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
const user = doc.data();
console.log(user);
});
})
.catch(error => {
console.error(error);
});
5. Watch
데이터가 변경될 때 마다 콜백을 호출하여 업데이트한다.
Firestore의 실시간 업데이트 기능을 십분 활용할 수 있는 방식이다.
// 컬렉션의 데이터 변경 사항을 실시간으로 감지
db.collection('chats')
.onSnapshot(querySnapshot => {
querySnapshot.docChanges().forEach(change => {
if (change.type === 'added') {
const chat = change.doc.data();
console.log('새로운 채팅:', chat);
}
});
});
이 외에도 다양한 쿼리 방식이 있다.
NoSQL은 아마존의 DynamoDB만 사용해 봤는데,
Firestore가 사용하기 훨씬 편한 것 같다.
'Camp > T.I.L.' 카테고리의 다른 글
[TIL #6] Github Page로 웹페이지 배포 (0) | 2024.06.24 |
---|---|
[WIL #1] 첫 주를 돌아보며 (0) | 2024.06.21 |
[TIL #4] API Fetch (0) | 2024.06.20 |
[TIL #3] 게임 서버에 대한 질문 (0) | 2024.06.19 |
[TIL #2] 웹개발 2주차: JS와 jQuery (0) | 2024.06.18 |