- reward-products/ 이미지를 리사이즈(메인 1080px, 상세 너비 1440px) + WebP(품질 82)로 변환하는 공용 서비스 추가 (sharp) - Storage 트리거 onRewardImageUploaded(us-central1)로 이후 업로드에도 자동 적용 — 다운로드 토큰을 보존해 기존 URL이 그대로 유효 - 기존 자산 일괄 최적화 스크립트(npm run optimize:reward-images) 추가, 실행 결과 38개 파일 135MB → 5.7MB - 재처리 무한루프는 rewardImageOptimized 메타데이터 플래그로 방지
47 lines
1.9 KiB
TypeScript
47 lines
1.9 KiB
TypeScript
import { onObjectFinalized } from "firebase-functions/storage";
|
|
import { logger } from "firebase-functions";
|
|
import { getStorage } from "firebase-admin/storage";
|
|
import "../firebase";
|
|
import { OPTIMIZED_FLAG, optimizeRewardImage, targetForPath } from "../services/imageOptimizeService";
|
|
|
|
/**
|
|
* reward-products/ 아래에 업로드된 이미지를 리사이즈 + WebP로 변환해 같은 경로에 덮어쓴다.
|
|
* 커스텀 메타데이터(다운로드 토큰 포함)를 보존하므로 기존 URL은 그대로 유효하다.
|
|
* 버킷(US-CENTRAL1)과 같은 리전이어야 Eventarc 트리거가 생성된다.
|
|
*/
|
|
export const onRewardImageUploaded = onObjectFinalized(
|
|
{
|
|
bucket: "mmday-panit.firebasestorage.app",
|
|
region: "us-central1",
|
|
memory: "1GiB",
|
|
timeoutSeconds: 300,
|
|
},
|
|
async (event) => {
|
|
const object = event.data;
|
|
const target = targetForPath(object.name);
|
|
if (!target) return;
|
|
if (!object.contentType?.startsWith("image/")) return;
|
|
if (object.metadata?.[OPTIMIZED_FLAG] === "true") return;
|
|
|
|
const file = getStorage().bucket(object.bucket).file(object.name);
|
|
const [input] = await file.download();
|
|
const output = await optimizeRewardImage(input, target);
|
|
|
|
if (output.data.length >= input.length) {
|
|
// 이미 충분히 작은 파일은 재업로드 없이 플래그만 남긴다(메타데이터 변경은 finalize를 다시 발생시키지 않음).
|
|
await file.setMetadata({ metadata: { [OPTIMIZED_FLAG]: "true" } });
|
|
logger.info(`[rewardImage] skip (already small) ${object.name} ${input.length}B`);
|
|
return;
|
|
}
|
|
|
|
await file.save(output.data, {
|
|
contentType: "image/webp",
|
|
metadata: { metadata: { ...object.metadata, [OPTIMIZED_FLAG]: "true" } },
|
|
});
|
|
logger.info(
|
|
`[rewardImage] optimized ${object.name} ` +
|
|
`${input.length}B -> ${output.data.length}B (${output.width}x${output.height})`,
|
|
);
|
|
},
|
|
);
|