Nuxt 앱을 배포했는데 아직도 탭에 기본 favicon이 표시되고 있나요? 더 나쁜 것은 마케팅 팀이 결제 페이지와 관리자 대시보드에 각각 다른 아이콘을 원한다는 것입니다. link 태그를 하드코딩하는 것으로는 충분하지 않습니다. Nuxt는 app.head 설정과 useHead 컴포저블을 통해 프로그래밍 방식으로 제어할 수 있는 방법을 제공하며, 이 둘을 이해하는 것이 프레임워크와 싸우는 것과 프레임워크가 알아서 동작하게 하는 것의 차이를 만듭니다.

이 가이드는 파일 기반 메타데이터 접근 방식이 아닌 Nuxt의 head 구성 시스템을 통해 favicon을 관리하는 데 초점을 맞춥니다. 파일 기반 방식에 대한 내용은 Nuxt favicon 가이드를 참조하세요. 페이지별 아이콘, 다크 모드 전환 또는 런타임 교체가 필요하다면 head API가 바로 그 해답입니다.

사전 요구 사항

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를 통해 구현됩니다.

일반적인 함정

마무리

app.head 설정은 기본값을 처리하고 useHead는 모든 동적 요소를 처리합니다. 이 둘을 함께 사용하면 단일 정적 아이콘에서 페이지별 교체, 반응형 배지에 이르기까지 Nuxt 앱에서 일반적으로 필요한 모든 favicon 시나리오를 처리할 수 있으며, 타사 head 플러그인에 의존하거나 Nuxt의 기본값과 싸울 필요가 없습니다.

아직 아이콘 파일을 생성하지 않았다면 Mzu favicondl에서 전체 다중 해상도 패키지(SVG, PNG, ICO, Apple Touch)를 한 번의 클릭으로 생성할 수 있습니다. 파일을 public/에 넣고 app.head에 연결하면 몇 분 안에 탭이 전문적으로 보일 것입니다.