// favicon.svg → 검색엔진/브라우저용 PNG·ICO 파비콘 일괄 생성 스크립트 // 사용법: node scripts/gen-favicon.mjs import sharp from 'sharp' import pngToIco from 'png-to-ico' import { readFile, writeFile } from 'node:fs/promises' import { fileURLToPath } from 'node:url' import { dirname, resolve } from 'node:path' const __dirname = dirname(fileURLToPath(import.meta.url)) const publicDir = resolve(__dirname, '../public') const svgPath = resolve(publicDir, 'favicon.svg') // 흰 배경으로 평탄화 — 투명 영역이 iOS/검색결과에서 검게 보이는 문제 방지 const WHITE = { r: 255, g: 255, b: 255, alpha: 1 } // 주어진 한 변 길이로 PNG 버퍼 생성 async function render(svg, size) { return sharp(svg, { density: 384 }) .resize(size, size, { fit: 'contain', background: WHITE }) .flatten({ background: WHITE }) .png() .toBuffer() } async function main() { const svg = await readFile(svgPath) // 개별 PNG 파비콘 생성 const targets = [ { name: 'favicon-16x16.png', size: 16 }, { name: 'favicon-32x32.png', size: 32 }, { name: 'apple-touch-icon.png', size: 180 }, ] for (const { name, size } of targets) { const buf = await render(svg, size) await writeFile(resolve(publicDir, name), buf) console.log(`생성: ${name} (${size}x${size})`) } // favicon.ico — 16/32/48 멀티 사이즈 포함 const icoSizes = [16, 32, 48] const icoPngs = await Promise.all(icoSizes.map((s) => render(svg, s))) const ico = await pngToIco(icoPngs) await writeFile(resolve(publicDir, 'favicon.ico'), ico) console.log(`생성: favicon.ico (${icoSizes.join('/')})`) } main().catch((err) => { console.error(err) process.exit(1) })