2022. 3. 3. 15:29ㆍFirebase
Cloud Function이 뭔지 잘 모르겠다던가 프로젝트에 세팅하는 방법을 알고 싶다면 아래 포스트를 참고하길 바란다.
위 포스트에서 언급했듯이 Cloud Function은 어떤 이벤트에 의해 발동되는데 이 이벤트를 트리거(trigger)라고 한다.
트리거 종류는 공식문서에 따르면 아래와 같다.
이 중에서 오늘은 공식문서에 가장 첫번째에 계시되어 있는 Cloud Firestore 트리거에 대해 알아보도록 하겠다.
이미 예상했겠지만 해당 트리거를 설정시, 특정 문서나 컬렉션에 변화가 있으면 지정된 클라우드 함수가 호출되는 방식이다.
예를 들어서, 새로운 사용자가 데이터베이스에 추가되었을 때 환영 이메일을 보낸다던지, 주문 상태가 완료로 바뀌었을 때 사용자에게 인앱 알림을 보낸다던지 할 수가 있다.
물론 클라우드 함수를 쓰지않고 데이터베이스에 문서를 변경시킬 때 클라이언트 측에서 같이 작업을 해도 되는 경우도 많지만, 그러다 보면 코드 로직도 복잡해질 수 있고 데이터베이스 작업이 아직 완료되지도 않았는데 후속 작업이 진행될 수도 있기 때문에 Firestore 트리거를 사용해 이를 분리해주면 관리가 편하다.
이벤트 유형트리거
onCreate | 문서를 처음으로 기록할 때 트리거됩니다. |
onUpdate | 이미 존재하는 문서에서 값이 변경되었을 때 트리거됩니다. |
onDelete | 데이터가 있는 문서가 삭제되면 트리거됩니다. |
onWrite | onCreate, onUpdate 또는 onDelete가 트리거될 때 트리거됩니다. |
출처: 파이어베이스 공식문서
이런 식으로 트리거가 존재하는데 어떤 변화에 반응해서 함수를 실행할 건지 정한 뒤 functions 폴더의 index.js에 클라우드 함수 작성 후 배포하면 된다.
추가, 업데이트, 삭제 모두 수신대기를 해야 하는 경우 onWrite를 써주면 되지만 데이터베이스에 추가되거나 삭제되는 것만 수신하면 되는 상황이라면 onCreate 랑 onDelete 두 개 작성을 해도 상관없다.
일단은 트리거 설정 방법에 대해 자세히 일아보자. (폴더 구조는 저번에 올린 초기 세팅 방법을 참고하길 바란다)
// request.js
// 요청 관련 (데이터베이스 trigger)
const functions = require("firebase-functions");
exports.onRequestUpdate = functions.firestore
.document("트리거 연결할 문서 또는 문서그룹 라우트")
.onUpdate((change, context) => {
// 실행할 함수 로직
});
여기서 중요한 건 document의 인수와 onUpdate 콜백의 인수인 change와 context다.
document의 인수로는 트리거를 연결할 문서 또는 문서 그룹을 지정해주면 된다.
단일 문서의 변화를 수신대기하려고 한다면 (특정 유저의 문서를 수신대기)
.document("users/4LB7GTTwtaTBfk8oRKq085MMKEp1")
이런 식으로 문서의 id를 그대로 넣어주면 된다.
하지만 보통 이렇게 쓰는 경우보다는 특정 문서 그룹 (컬렉션)의 변화를 수신대기해야 할 상황이 더 많을 것이다.
이럴 때는 와일드카드를 사용하면 된다.
.document("users/{uid}")
이런 식으로 작성해주면 유저 컬렉션의 모든 문서들의 변화를 수신대기할 수가 있다. 그리고 트리거를 발동한 문서의 uid를 함수 내에서 참조하고 싶다면 onUpdate 콜백의 두 번째 인수인 context를 통해 할 수 있다 (context.params.uid).
첫 번째 인수인 change는 트리거를 발생한 문서의 데이터를 객체 형식으로 가지고 있다. onCreate, onDelete에서는 snap이라 하고 onUpdate, onWrite에서는 change라고 작명하는 이유는 후자는 변경 전 데이터, 변경 후 데이터 모두 조회할 수 있기 때문이다.
const prevData = change.prev.data(); // 변경 전 데이터
const updatedData = change.after.data(); // 변경 후 데이터
필자는 견적 요청 문서에 업데이트가 있을 경우 (requested 상태에서 proposed 상태로 변경되었을 경우) 일 때 해당 고객에게 견적이 도착했다는 웹앱 알림과 카카오 알림 톡을 보냈기 때문에 아래와 같이 작성했다.
const functions = require("firebase-functions");
const admin = require("firebase-admin");
exports.onRequestUpdate = functions.firestore
.document("requests/{uid}/tasks/{taskId}")
.onUpdate(async (change, context) => {
const { uid, taskId } = context.params;
const prevStatus = change.before.data().status;
const status = change.after.data().status;
// 요청 상태가 제안 되었을 경우 알림 컬렉션에 알림 문서 추가 (클라이언트에서 requested -> proposed 상태 변경)
if (prevStatus==="requested" && status === "proposed") {
try {
const notiRef = db
.collection("users")
.doc(uid)
.collection("Notification");
await notiRef.add({
isRead: false,
timeStamp: admin.firestore.FieldValue.serverTimestamp(),
type: "request",
link: `/organization/${uid}/${taskId}`,
uid,
});
// 추가로 알림톡 전송하는 로직
} catch (err) {
console.error(err);
}
}
});
중요한 포인트는 수정전 문서의 필드가 requested인걸 꼭 확인해줘 여한다. 그렇지 않으면 다른 필드 변화에도 반응하기 때문에 견적 요청이랑 전혀 관련 없는 필드를 수정했는데 고객에게 알림이 갈 수도 있기 때문에 항상 전 데이터와 비교해 어떤 필드에 수신대기할 것인지 명확히 해야 한다.
onUpdate 트리거 설정하는 방법을 알았다면 onCreate랑 onDelete도 별 어려움 없이 사용이 가능할 것이다.
달라지는 건 좀 전에 언급했듯이 변경 전 데이터, 변경 후 데이터가 아닌 현재 (onCreate 면 추가된, onDelete 면 삭제된) 데이터 문서만 조회가 가능하다.
const functions = require("firebase-functions");
exports.onSomethingCreated = functions.firestore
.document("트리거 연결할 문서 또는 문서그룹 라우트")
.onCreate((snap, context) => {
const currentData = snap.data() // 추가된 데이터
});
onWrite를 사용해서 모든 데이터베이스 변화에 수신대기를 하고 싶다면 아래와 같은 방법으로 조건문 처리로 각각 상황에 맞게 대응해주면 된다.
exports.onUserWrite = functions
.region('asia-northeast3')
.firestore.document('User/{uid}')
.onWrite((change, context) => {
// 추가
if (!change.before.exists) {
// 새로운 유저가 추가되었을때 실행할 코드
}
// 삭제
if (!change.after.exists) {
// 유저가 삭제되었을때 실행할 코드
}
// 유저가 수정되었을때
});
'Firebase' 카테고리의 다른 글
[Firebase 웹] Cloud Function으로 RESTful API 만들기 (feat. Express) (2) | 2022.03.27 |
---|---|
[Firebase 웹] 지정된 시간마다 Cloud Function 직접 호출 (2) | 2022.03.06 |
[Firebase 웹] Cloud Function이란? 초기 세팅하기 (0) | 2022.03.01 |
[Firebase 웹] 파이어스토어에서 데이터 불러오고 쓰기 feat. React (0) | 2022.02.25 |
[Firebase 웹] 파이어베이스 시작하기 - 웹 앱 초기설정 (0) | 2022.02.23 |