지난 글에서 DOM 조작으로 meta 태그를 변경하는 방식과 React helmet async 라이브러리를 사용하는 방법에 대해 시도해 보았다.
그러나 내 프로젝트는 Firebase로 배포한 것이기 때문에 해당 방법들은 적합하지 않았다.
문제 해결을 위해 Firebase Functions를 도입했다.
Functions는 무료 요금제인 Spark 요금제에서는 사용이 불가능하고,
종량제 요금제인 Blaze 요금제로 변경해야 한다.
여기서 주의해야 할 점이 하나 있다.
Firebase Functions는 ECMAScript가 아니라 CommonJS를 사용한다.
그래서 import 대신에 require 문을 사용해야 한다.
블로그에서와는 달리 cp가 작동하지 않아서 직접 html을 복사해 넣어줬다.
이후 fs.readFile 메서드를 사용해 해당 html을 불러와서 교체해 주어야 하는데,
참고한 블로그에서와는 달리, < 같은 이스케이프 표기법을 쓰면 안 되고 < 와 같이 직접 적어 주어야 했다.
const express = require('express');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const fs = require('fs');
admin.initializeApp();
const app = express();
app.get('/:alias', async (req, res) => {
const { alias } = req.params;
try {
const snapshot = await admin.database().ref(`/pages/${alias}`).once('value');
const dbData = snapshot.val();
const title = dbData?.headerText;
const description = dbData?.invitation?.join(' ');
const imageUrl = `/images/gallery/${dbData.background}`;
const url = `https://happy-ever-after.site/${alias}`;
const themeColor = dbData?.color;
fs.readFile('./index.html', 'utf8', (err, htmlString) => {
if (err) {
console.error('Error reading HTML file:', err);
res.status(500).send('Internal Server Error');
return;
}
const replacements = [
{ pattern: /<title>(.*?)<\/title>/, replacement: `<title>${title} | Happy Ever After</title>` },
{
pattern: /<meta name="description" content=['"](.*?)['"]\/>/,
replacement: `<meta name="description" content="${description}"/>`,
},
//중략
{
pattern: /<meta property="og:description" content=['"](.*?)['"]\/>/,
replacement: `<meta property="og:description" content="${description}"/>`,
},
];
let replacedHTML = htmlString;
replacements.forEach(({ pattern, replacement }) => {
replacedHTML = replacedHTML.replace(pattern, replacement);
});
res.set('Content-Type', 'text/html');
res.send(Buffer.from(replacedHTML));
});
} catch (e) {
console.error(e);
res.status(500).send('Internal Server Error');
}
});
exports.dynamicMetatag = functions.https.onRequest(app);
그리고 build 후 index.html이 복사되었는지 꼭 확인해야 한다.
만약 복사되지 않았거나 기존 파일 상태라면 새로운 index.html을 집어넣어 주어야 한다.