RETROSPECTIVE · 회고
웹 SDK가 안 알려주는 문서 생성 시각: 예전 랭킹에 날짜 붙이기
Backend
모든 게임 랭킹에 '달성 일자'를 넣기로 했다. 새 기록은 저장할 때 날짜를 넣으면 되지만, 몇 년 동안 쌓인 예전 기록에는 날짜 필드가 아예 없었다.
새 기록: 서버 시각만 허용
클라이언트 시계는 믿을 수 없어서 serverTimestamp()로 넣고, 보안 규칙에서 서버 시각과 같은지 검사했다. 필드가 없는 요청도 통과시켜서, 규칙을 먼저 배포해도 예전 클라이언트가 깨지지 않게 했다.
function validCreatedAt() {
return !('createdAt' in request.resource.data)
|| request.resource.data.createdAt == request.time;
}
예전 기록: 문서 메타데이터에 답이 있었다
Firestore 문서는 필드와 별개로 생성 시각(createTime)을 갖고 있다. 하지만 웹 SDK의 getDocs는 이 값을 돌려주지 않는다. Admin SDK로 일괄 마이그레이션하는 방법도 있지만, 랭킹 컬렉션은 누구나 읽을 수 있으니 REST API의 batchGet으로 해당 문서들의 createTime만 받아오기로 했다.
// 날짜가 없는 문서만, 필드 없이(mask) 메타데이터만 요청
fetch(`https://firestore.googleapis.com/v1/${base}:batchGet?key=${API_KEY}`, {
method: "POST",
body: JSON.stringify({
documents: missing.map((r) => `${base}/${path}/${r.id}`),
mask: { fieldPaths: ["name"] },
}),
});
실패하면 날짜 칸만 비워 두고 랭킹은 그대로 보여 준다. 날짜가 있는 기록이 늘어날수록 이 요청은 자연히 줄어든다.
배운 점
- 클라이언트 SDK가 감춘 정보도 플랫폼에는 남아 있을 수 있다. 마이그레이션 전에 이미 가진 메타데이터부터 확인한다.
- 새 필드를 추가할 때는 '규칙 먼저 배포 → 클라이언트 배포' 순서에서도, 그 반대 순서에서도 깨지지 않게 하위 호환을 고려한다.
- 날짜는 클라이언트가 아니라 서버가 찍게 하고, 규칙으로 강제한다.