From e1e18b00f7b695eff8687a49cebed569880a150e Mon Sep 17 00:00:00 2001 From: TtiPo Date: Wed, 10 Jun 2026 19:49:53 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EA=B5=AC=EA=B8=80=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=20=ED=8C=8C=EB=B9=84=EC=BD=98=20=EC=9E=98?= =?UTF-8?q?=EB=A6=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 여백 추가된 favicon.svg 기반으로 PNG/ICO 파비콘 재생성. 로고를 캔버스 중앙 영역에 배치해 구글 원형 마스크에도 안 잘리도록 함. - sharp/png-to-ico 기반 생성 스크립트 추가 (npm run favicon) - SVG 파비콘 링크 추가 (최신 브라우저 우선) Co-Authored-By: Claude Opus 4.8 (1M context) --- frontend/nuxt.config.ts | 2 + frontend/package-lock.json | 677 +++++++++++++++++++++++++-- frontend/package.json | 5 +- frontend/public/apple-touch-icon.png | Bin 14911 -> 5530 bytes frontend/public/favicon-16x16.png | Bin 905 -> 314 bytes frontend/public/favicon-32x32.png | Bin 2082 -> 704 bytes frontend/public/favicon.ico | Bin 6302 -> 15086 bytes frontend/public/favicon.svg | 9 + frontend/scripts/gen-favicon.mjs | 51 ++ 9 files changed, 706 insertions(+), 38 deletions(-) create mode 100644 frontend/public/favicon.svg create mode 100644 frontend/scripts/gen-favicon.mjs diff --git a/frontend/nuxt.config.ts b/frontend/nuxt.config.ts index 5a03708..f3b1539 100644 --- a/frontend/nuxt.config.ts +++ b/frontend/nuxt.config.ts @@ -49,6 +49,8 @@ export default defineNuxtConfig({ link: [ // 파비콘 — 헤더 로고(ITAB) 기반 { rel: 'icon', href: '/favicon.ico', sizes: 'any' }, + // SVG 파비콘 — 최신 브라우저 우선 적용(고해상도) + { rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg' }, { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32x32.png' }, { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon-16x16.png' }, { rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' }, diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e866692..c761667 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -21,6 +21,8 @@ "@types/node": "^24.12.0", "eslint": "^9.18.0", "oxfmt": "^0.42.0", + "png-to-ico": "^3.0.1", + "sharp": "^0.34.5", "typescript": "~6.0.0", "vue-tsc": "^3.2.6" }, @@ -1368,6 +1370,544 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@ioredis/commands": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.10.0.tgz", @@ -1699,26 +2239,6 @@ } } }, - "node_modules/@nuxt/cli/node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@nuxt/cli/node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/@nuxt/devalue": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@nuxt/devalue/-/devalue-2.0.2.tgz", @@ -2043,23 +2563,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nuxt/schema": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/@nuxt/schema/-/schema-4.4.6.tgz", - "integrity": "sha512-7FDMuD+skbFMgfF2ORYKEAKEuEFbu2oS60dln5uVtn94c8DHWCseJSrT3FUHzVUlVwyhztPU6stzB44dEoWAzw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@vue/shared": "^3.5.34", - "defu": "^6.1.7", - "pathe": "^2.0.3", - "pkg-types": "^2.3.1", - "std-env": "^4.1.0" - }, - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, "node_modules/@nuxt/telemetry": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/@nuxt/telemetry/-/telemetry-2.8.0.tgz", @@ -10280,6 +10783,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", @@ -11856,6 +12369,51 @@ "node": ">=4" } }, + "node_modules/png-to-ico": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/png-to-ico/-/png-to-ico-3.0.1.tgz", + "integrity": "sha512-S8BOAoaGd9gT5uaemQ62arIY3Jzco7Uc7LwUTqRyqJDTsKqOAiyfyN4dSdT0D+Zf8XvgztgpRbM5wnQd7EgYwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^22.10.3", + "minimist": "^1.2.8", + "pngjs": "^7.0.0" + }, + "bin": { + "png-to-ico": "bin/cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/png-to-ico/node_modules/@types/node": { + "version": "22.19.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.20.tgz", + "integrity": "sha512-6tELRwSDYWW9EdZhbeZmYGZ1/7Djkt+Ah3/ScEYT9cDord7UJzasR/4D3VONg9tQI5CDp+/CZC1AXj2pCFOvpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/png-to-ico/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.19.0" + } + }, "node_modules/postcss": { "version": "8.5.15", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", @@ -13006,6 +13564,51 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 4333ce0..d3aa192 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,7 +11,8 @@ "postinstall": "nuxt prepare", "typecheck": "nuxt typecheck", "lint": "eslint . --fix", - "format": "oxfmt ." + "format": "oxfmt .", + "favicon": "node scripts/gen-favicon.mjs" }, "dependencies": { "axios": "^1.14.0", @@ -26,6 +27,8 @@ "@types/node": "^24.12.0", "eslint": "^9.18.0", "oxfmt": "^0.42.0", + "png-to-ico": "^3.0.1", + "sharp": "^0.34.5", "typescript": "~6.0.0", "vue-tsc": "^3.2.6" }, diff --git a/frontend/public/apple-touch-icon.png b/frontend/public/apple-touch-icon.png index 70c42517e061935d80c77f3a75daf550c3289793..f14b60f6a616af0050ba392a85288488c611a972 100644 GIT binary patch literal 5530 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 diff --git a/frontend/public/favicon-16x16.png b/frontend/public/favicon-16x16.png index c52d1b6e5489680dd963b3fb88c8e89e4fabfdbc..e394585a6f748f6f638e58b62b06dbc7c3b03bd6 100644 GIT binary patch delta 298 zcmV+_0oDGA2f6}~8Gix*005AYXf^-<010qNS#tmYI}QKbYx`qSCE}y-0XX(0wTXvtmb@%DN wfB#Av=M^{1T_eBk_?j)pusDfGFbFjO0NHb|SQBV5TL1t607*qoM6N<$f*D+uvH$=8 delta 893 zcmV-@1A_dz0*MEZ8Gi-<001BJ|6u?C010qNS#tmY009610096`CB)VM000DINkdQp z1ONe(xB$HX001CkNK#Dz0D2|>0Dy!50Qvv`0D$NK0Cg|`0P0`>06Lfe02gqax=}m; z000DMK}|sb0I`n?{9y$E00QqxL_t(|oQ;xAXjE4efX}&q?|*0JO=c!md?O-u_*|MHXIQk0_hB-?KP0`Y0~*I zR;_Vp*7L_M{vUvV1|Y2>Fs|x;A_oevS2)L9fTVS!bs9?jDJJ;Ax^FfMx=`{T05m~1$XD zBzDwVXAgub>>{9+SKD*k^T)O!^0}4f{qv&v=-ZEVmc(X?e`dZv3&=Q-j?yH|HZCrW zVE(teUox&-Gan)^17n!<+Lw}k2Sm8`_v&kfz4gV;R(H`~U+MyYc_v!_DM$Pl1b9g| Tx~)zM00000NkvXXu0mjf$XK42 diff --git a/frontend/public/favicon-32x32.png b/frontend/public/favicon-32x32.png index 70cf911fa8765a5fc20e9fcc8ab1f2613aaf0989..ed0c3bd26c9f44ff07b26aea1099ebadbaa8d181 100644 GIT binary patch delta 691 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 KMNUMnLSTaX-{SfJ diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico index 6e702fad8650b7de07263a970dc1a1bf94dd6d58..b500a0a4a070809f0028557ba1c55f18e6259a06 100644 GIT binary patch literal 15086 zcmeHN=Tj9|6yHqp2lyr5`H~sO6iuRLl336v#u8&<(Cjff~%P@2SYa(@T!=J9w7Z()ryx@TtJ+r4|wIlp`MmUGX!it>)~ zuF|QKBK{qeneQn|PeoB29GaeEMR}ws>(=e%^9PFJ^uD5W7Inlc!O>JM{%jJNq*~x| z_HioC&!No37&?D=Kb4mh(u)@_DAM19BK+Lx^nrbpy+1*%Z+(-Ml0bPUj!=Ba3Oaiz znJyejrAPOxX!X?59!sO7&Fd&NDvY87yqF(YR!kW| z&z?TDi~np|5}nw$n-1;VLcT(Oea&N9J7S?3NZBP$hW6m7> zlUy7>rmR+c167FCO>6qA?^RONGEbG`(Y-3hwsq+|*6%Uo3tk&hA!x=}S~#Mwrf;DN zvAStZKiV7WHdW;)xOkTJV{JwIE%iqV{|I($sH;`$+jG;Je(-Pbm`0bgGwI6dOo|H$ zWF7FUto7sjK|lO0J=B)|?STvF@U95q`z6v^=ZUNX{nA=Ld=BV`JU!Hwe)w*%J1E5U z7n<9@D?O>NYoQd(zgr;|y0*mqs@LtpY6KbZYD+5X0cdMYdWi{?9h&f`#z zZq#k7{T0`XDIs(f)mA?w=e{4(=0(n|0{Z9n`-EbGe7Nt2`?wP361~)x{sv)djJMLO zdHj8ow*;&DW&cMV_rX1dZ@gNs`Zn7Sf$(8ZrzW!gbLlB9^rK+a)KRqfM@LQHnwf0; zwAFsFp#5>d0jyun$MXBbHwR%~G4GqM>U_k7cKq0*KQSzb;P*Q_ex%MX*7|>&HJ)4t zeELfCV_wJD#vV$NwSIpwE-*Iql4bj`zq@z)7VC-->kpnm*pov4Ca>A5cuW0dV(r7& zIJj+-`rh7~#)dkcW3jKpnul*4>OPG&dd=cz%s+LHA92~KR^2XvGEouX4mGM2J+GA}%vd@kVzwvvH;cObeJ6FfCwOz_h?CvOvX+ z65f~IxR$T(Q=v+hmtM)^SY%cCO_BdAvx!2jd-amwD`t7v>*4}G@`hTuPMZRC6k^Yc zJ@vv7eVXlC5nn?2{DGfQ32x@16z4#Gp^&Z|!#U#~LSKXyKy}K}G#NBM+M_t54VW*(!W5rWbJVnar$iKb# z>uYPsUE~QKR^Dl*t{~?O;{rD1rM2)UhOOax=vQ?*W6RAHT0Pi{A8d$wVN6<5X5uat zf2kP1TKEw=M;mb=wq+FQ!5`*1gKdm_hP+~b_h(G#+chG#tc4$OEr}m}(J0b`AMtOu zLEUNb$bRaDJOFSl8QGu5zZQO+Ws&&HON)$x&v8P?ZEOC4LgWuNh?pXBGq^Aoyu_FW zzsxUb;Xe`^rQ&~3S@Bx%7v-I&fJwu-?*IVWfZPM{C#+w|n6&Wk+tf6E-JH4;awSHQ zp8f-SBR3>-b0wE^RhynnYKrOF!jCmBcp=hFlDMJ7B`uJW00j;~jiE)J1+! zIO?)`hyV5B$J&GZByv^2gNyUZFOg{B$JtBN#kmXF*E$Sd2+)fkc{=2Hah_7*FBI#7 zBrW{%Tmbe07#Bv7Ui_GYmi;`0bIHJuc@gJJBx&J~^7rKSV*P4QeqGA9{@05i{K$Vw zzo*IX`0pI87XClH=P-VZYxsUfQG4)9UjX*Ux@t+b@Z+1U{B% z@;DD?$&a&A2gKQN>@$t*_m(y@?@bGs7BDSfTEMh`X#vv$Z-NEH@gS34qXqs2n=Egr literal 6302 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 + + + + + + + + diff --git a/frontend/scripts/gen-favicon.mjs b/frontend/scripts/gen-favicon.mjs new file mode 100644 index 0000000..9548034 --- /dev/null +++ b/frontend/scripts/gen-favicon.mjs @@ -0,0 +1,51 @@ +// 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) +})