Nuxt 앱을 배포했는데 아직도 탭에 기본 favicon이 표시되고 있나요? 더 나쁜 것은 마케팅 팀이 결제 페이지와 관리자 대시보드에 각각 다른 아이콘을 원한다는 것입니다. link 태그를 하드코딩하는 것으로는 충분하지 않습니다. Nuxt는 app.head 설정과 useHead 컴포저블을 통해 프로그래밍 방식으로 제어할 수 있는 방법을 제공하며, 이 둘을 이해하는 것이 프레임워크와 싸우는 것과 프레임워크가 알아서 동작하게 하는 것의 차이를 만듭니다.
이 가이드는 파일 기반 메타데이터 접근 방식이 아닌 Nuxt의 head 구성 시스템을 통해 favicon을 관리하는 데 초점을 맞춥니다. 파일 기반 방식에 대한 내용은 Nuxt favicon 가이드를 참조하세요. 페이지별 아이콘, 다크 모드 전환 또는 런타임 교체가 필요하다면 head API가 바로 그 해답입니다.
사전 요구 사항
- Nuxt 3.x 또는 4.x 프로젝트
- 생성된 favicon 파일(PNG, SVG, ICO) — 어떤 파일이 필요한지 잘 모르겠다면 favicon 크기 가이드를 확인하세요.
- Vue 3
<script setup>블록에 대한 기본적인 이해
1단계: app.head로 기본 Favicon 설정
nuxt.config.ts의 app.head 속성은 프레임워크 전체의 기본값입니다. 여기에 정의된 내용은 페이지에서 재정의하지 않는 한 모든 페이지의 <head>에 주입됩니다.
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
link: [
{ rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg' },
{ rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32x32.png' },
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' }
]
}
}
})
아이콘 파일을 public/ 디렉토리에 배치하면 Nuxt가 루트에서 파일을 제공합니다. Nuxt SEO 및 메타 문서에 따르면 link 배열은 내부적으로 사용되는 unhead 엔진이 허용하는 형태와 동일하며, 이는 html.spec.whatwg.org의 WHATWG rel="icon" 사양과 일치합니다.
2단계: useHead로 페이지별 Favicon 재정의
특정 라우트에 다른 아이콘을 사용하고 싶을 때가 있습니다. useHead 컴포저블을 사용하면 해당 페이지에서만 전역 설정을 재정의하는 항목을 추가할 수 있습니다.
<script setup lang="ts">
useHead({
link: [
{ rel: 'icon', type: 'image/svg+xml', href: '/icons/admin-favicon.svg' }
]
})
</script>
<template>
<div>Admin Dashboard</div>
</template>
<script setup> 블록 상단에서 useHead()를 호출하세요. Nuxt가 SSR 주입을 처리하므로 초기 HTML에 재정의가 포함되어 하이드레이션 시 잘못된 아이콘이 잠깐 표시되는 문제가 없고 클라이언트 측 패치가 필요하지 않습니다.
3단계: 상태에 따라 Favicon 동적으로 교체
알림 수나 테마 변경에 따라 favicon이 반응하도록 하시겠습니까? useHead를 반응형 ref 또는 computed와 결합하세요.
<script setup lang="ts">
const cartCount = useCartCount()
useHead({
link: [
{
rel: 'icon',
type: 'image/svg+xml',
href: computed(() =>
cartCount.value > 0
? `/icons/cart-${cartCount.value}.svg`
: '/favicon.svg'
)
}
]
})
</script>
computed href는 cartCount가 변경될 때마다 업데이트됩니다. Nuxt의 useHead는 반응성을 추적하고 <link> 태그를 제자리에서 다시 작성합니다. 전체 페이지를 다시 로드하거나 수동으로 DOM을 조작할 필요가 없습니다. 캔버스 기반 배지로 더 확장하려면 동적 favicon JavaScript 가이드에서 기본 패턴을 다룹니다.
4단계: 다크 모드 Favicon 지원
최신 브라우저는 아이콘 링크의 media 속성을 지원합니다. 이를 useHead와 결합하면 JavaScript 없이도 테마를 인식하는 아이콘을 얻을 수 있습니다.
useHead({
link: [
{ rel: 'icon', type: 'image/svg+xml', href: '/favicon-light.svg', media: '(prefers-color-scheme: light)' },
{ rel: 'icon', type: 'image/svg+xml', href: '/favicon-dark.svg', media: '(prefers-color-scheme: dark)' }
]
})
브라우저는 사용자의 시스템 기본 설정에 따라 올바른 아이콘을 선택합니다. 이는 favicon 다크 모드 가이드에서 설명한 것과 동일한 패턴이지만, 원시 HTML 대신 Nuxt의 head API를 통해 구현됩니다.
일반적인 함정
- 깊이 중첩된 하위 컴포넌트에서
useHead를 호출하는 경우. 작동은 하지만 SSR 타이밍이 예측 불가능해지고 중복 태그가 발생할 수 있습니다. 페이지 레벨의<script setup>에 유지하세요. type속성을 잊는 경우. 여러rel="icon"링크가 동일한 경로나 파일 이름을 공유하면 브라우저가 잘못된 파일을 제공할 수 있습니다. 명확성을 위해 항상type을 설정하세요.- 파일 기반 메타데이터와
useHead를 혼합하는 경우. Nuxt의 파일 기반 아이콘(app/또는public/디렉토리)은 명시적인app.head항목과 충돌하여 중복된<link>태그를 생성할 수 있습니다. 프로젝트당 하나의 접근 방식을 선택하세요. - 하드코딩된 절대 경로.
/favicon.svg와 같은 루트 상대 경로를 사용하여 라우트, 서브도메인, 리버스 프록시 뒤에서도 아이콘이 올바르게 로드되도록 하세요.
마무리
app.head 설정은 기본값을 처리하고 useHead는 모든 동적 요소를 처리합니다. 이 둘을 함께 사용하면 단일 정적 아이콘에서 페이지별 교체, 반응형 배지에 이르기까지 Nuxt 앱에서 일반적으로 필요한 모든 favicon 시나리오를 처리할 수 있으며, 타사 head 플러그인에 의존하거나 Nuxt의 기본값과 싸울 필요가 없습니다.
아직 아이콘 파일을 생성하지 않았다면 Mzu favicondl에서 전체 다중 해상도 패키지(SVG, PNG, ICO, Apple Touch)를 한 번의 클릭으로 생성할 수 있습니다. 파일을 public/에 넣고 app.head에 연결하면 몇 분 안에 탭이 전문적으로 보일 것입니다.