API 대부분의 지연시간이 800ms ~ 1500ms 정도이며 일부 API 의 경우에는 2500ms 까지 측정되었습니다.
Loading Indicator 를 넣더라도 사용자 체감상 최악의 사용자 경험이라고 생각합니다. 프로젝트를 시작했던 초기 Firebase Cloud function 에서 제공하는 Region 은 매우 소수였고 마땅한 지역이 없어, 기본값인 아이오와 us-central1를 이용했습니다
다음 주 서비스 출시 전 Region 에 대해 검색했을 때, 서울 리전이 추가된 것을 확인했습니다
(새로 추가된 것인지, 저번에 못 찾았던 것인지..?)
But, 서울의 경우 Tier2 가격으로 책정된다고 합니다.
무료 사용량이 있기 때문에, 실제로 Tier2가 얼마나 청구될 지 모르지만 Firebase 에서 제공하는 가이드로는 40% 더 비싼 것으로 되어 있습니다.
아직 서비스 사용량이 많아 과금이 무섭진 않지만, 곧 사용자가 많아질거라는 김칫국을 마시며 서울 대신 도쿄 리전을 선택했습니다.
Region 변경
Firebase 가이드에 따르면 기존 functions 냅두고 다른 리젼에 새로운 function 을 배포하고 기존 functions 를 삭제하라고 합니다.
iOS, Android native 에서 Cloud function을 HTTP가 아니라 Firebase SDK 를 사용했을때만 가능한 방법입니다.
lazy var functions = Functions.functions()
JavaScript
복사
하지만 Cloud function 을 사용하는 모든 분들은 HTTP로 사용하겠죠..? (나만그런가..?)
결론은,
하위 호환성을 위해 '새로운 Region 에 새로운 함수 이름으로 배포해야 한다' 입니다.
왜냐면, HTTP 를 사용하는 경우 Region 이 API host에 포함되어 있기 때문입니다. Region 이 바뀌면 Client 입장에서는 Host 가 통째로 바뀌어버리는 상황이 생깁니다
결국 기존에 사용하면 api 라는 function 이름은 사용하지 못하게 되었네요
(황금번호 느낌 좋았는데)
아쉽지만 api 대신 rest 를 사용하기로 했습니다.
AS-IS
exports.api = functions
.https.onRequest(app);
exports.userInfoCleanUp = functions
.auth.user().onDelete((user) => {
firestore.collection('users').doc(user.uid).delete();
});
exports.sendPushByMessage = functions
.firestore
.document('/messages/{messageID}')
.onCreate((snap, context) => {
const newMessage = snap.data();
const payload = {
notification: {
title: "수업지구대",
body: '쪽지가 도착했어요 ~📮'
}
};
firestore.collection('users').where('uid', '==', newMessage.to)
.get()
.then(snapshot => {
if (snapshot.empty) {
return;
}
snapshot.forEach(doc => {
var user = doc.data()
if (newMessage.to == null) {
return;
}
admin.messaging().sendToDevice(user.fcmToken, payload);
});
})
.catch(function (error) {
console.log(error);
});
});
JavaScript
복사
TO-BE
exports.rest = functions
.region('asia-northeast1') <- Region 추가
.https.onRequest(app);
exports.userInfoCleanUpTrigger = functions
.region('asia-northeast1') <- Region 추가
.auth.user().onDelete((user) => {
firestore.collection('users').doc(user.uid).delete();
});
exports.sendPushByMessageTrigger = functions
.region('asia-northeast1') <- Region 추가
.firestore
.document('/messages/{messageID}')
.onCreate((snap, context) => {
const newMessage = snap.data();
const payload = {
notification: {
title: "수업지구대",
body: '쪽지가 도착했어요 ~📮'
}
};
firestore.collection('users').where('uid', '==', newMessage.to)
.get()
.then(snapshot => {
if (snapshot.empty) {
return;
}
snapshot.forEach(doc => {
var user = doc.data()
if (newMessage.to == null) {
return;
}
admin.messaging().sendToDevice(user.fcmToken, payload);
});
})
.catch(function (error) {
console.log(error);
});
});
JavaScript
복사
새로운 이름으로 functions 와 trigger 를 등록, 배포합니다.
이제 기존 us-central1 에서 제공하는 functions 와 tokyo 의 functions 총 2벌의 functions 가 생겼습니다.
Tokyo 얼마나 빨라졌는가?
Region 을 변경하고자 했던 목표는 응답시간 입니다. 안빨라졌으면 아무 의미 없겠죠.
AS-IS 800ms ~ 1500ms
TO-BE 250ms ~ 500ms
개선된 속도가 로딩 인디케이터가 필요없을 정도로 빠른 수치는 아니지만, 사용성 부분에서 많은 개선 포인트가 있었습니다.
Tokyo 마저 느리다면 seoul 로 개선하려고 했는데, 우선 이정도면 충분하고 과금 상황을 봐서 Seoul 도 도전해보도록 하겠습니다.
아름다운 사람은 머문 자리도 아름답습니다
us-central1 에서 사용하는 functions 는 어떻게 해야할까요?
하위 호환성을 위해 서비스를 접을때까지 평생 유지해야할까요?
순리는, us-central1 의 사용자 유입을 측정하고 사용자가 없을 때 삭제하는 것입니다. 다행히 us-central1 에 직접 이벤트를 추가해 줄 필요 없이 Firebase 플랫폼 차원에서 사용량을 제공하고 있습니다.
시간이 지나 많은 사용자가 앱 업데이트를 통해 더이상 us-central1 에 request 가 없을 때 안전하게 제거해주시면 되겠습니다.
마무리
결론으로, Firebase Cloud funtions 를 사용할 예정이라면 region 을 tokyo 로 설정해주세요
아쉬운 부분은 functions 의 region 을 변경해도 firestore 의 region 은 변경이 불가하여 속도 최적화에 한계가 있다는 것.