첫 번째 Astro 사이트를 배포한 뒤, 브라우저 탭에 여전히 기본 Astro 로고가 나타나는 걸 확인하셨을 겁니다. 해결책은 한 군데에 있습니다. 바로 Astro favicon public 폴더 설정입니다.

Next.js나 Nuxt와 달리, Astro는 public 폴더를 다르게 취급합니다. 이 폴더 안의 파일들은 Vite의 빌드 파이프라인을 우회하고 최종 출력 디렉터리로 그대로 복사됩니다. 이는 favicon 자산에 있어 정확히 원하는 동작이지만, 그렇기 때문에 무작정 파일을 추가하기 전에 그 동작 원리를 먼저 이해할 필요가 있습니다.

Astro Favicon Public 폴더의 동작 원리

Astro 프로젝트 구조 문서에 따르면, public 폴더는 빌드 과정에서 별도 처리가 필요하지 않은 파일들을 위한 공간입니다. favicon 자산은 바로 이 범주에 해당합니다. Vite가 해시를 적용하거나, 변환하거나, 최적화하길 원치 않기 때문입니다. 브라우저가 파일을 찾을 수 있도록 예측 가능한 URL로 서브되길 원할 뿐입니다.

/public에 어떤 파일이든 넣으면, 배포된 사이트의 루트 경로에서 해당 파일에 접근할 수 있습니다. public/에 favicon.svg를 두면, 해당 파일은 https://yoursite.com/favicon.svg에 위치하게 됩니다. import도, 번들러 해석도, 별도의 처리도 필요 없습니다.

사전 준비 사항

1단계: Favicon 파일 생성하기

public 폴더를 건드리기 전에, 자산을 먼저 준비해야 합니다. 대부분의 프로젝트에서는 네 가지 파일이 필요합니다.

수동으로 크기를 조절하지 않고도 필요한 모든 크기를 한 번에 생성하려면 Mzu favicondl을 사용하면 됩니다.

2단계: Public 폴더에 파일 넣기

프로젝트 루트를 열고 public/ 디렉터리를 찾습니다. 준비한 favicon 파일들을 그 안에 직접 복사합니다. 폴더 구조는 다음과 같이 구성되어야 합니다.

your-astro-project/
├── public/
│   ├── favicon.svg
│   ├── favicon-32x32.png
│   ├── apple-touch-icon.png
│   └── favicon.ico
├── src/
└── astro.config.mjs

파일명은 소문자와 하이픈을 사용해 일관되게 유지하는 것이 좋습니다. 브라우저는 대소문자를 구분하지 않지만, 배포 서버의 운영체제에 따라 서빙되는 파일이 달라질 수 있으므로 한 가지 규칙을 고수하는 편이 안전합니다.

3단계: 레이아웃에 Link 태그 추가하기

public/에 들어 있는 파일들은 자동으로 HTML에 표시되지 않습니다. <link> 태그로 직접 참조해야 합니다. 메인 레이아웃 컴포넌트(주로 src/layouts/Layout.astro)를 열고 <head> 안에 다음 블록을 추가합니다.

<link rel='icon' href='/favicon.svg' type='image/svg+xml'>
<link rel='icon' href='/favicon-32x32.png' sizes='32x32' type='image/png'>
<link rel='apple-touch-icon' href='/apple-touch-icon.png' sizes='180x180'>
<link rel='shortcut icon' href='/favicon.ico'>

이 구성은 rel='icon'에 관한 HTML 명세를 따릅니다. 최신 브라우저는 SVG를 우선적으로 사용하고, 구형 브라우저는 PNG로 폴백하며, ICO는 레거시 환경을 잡아냅니다.

4단계: 다크 모드 대응(Optional)

밝은 색상의 favicon은 다크 테마 브라우저 chrome 위에서 자칫 묻힐 수 있습니다. 색상을 반전한 두 번째 SVG를 추가하고, media 쿼리로 두 아이콘을 교체하도록 설정합니다.

<link rel='icon' href='/favicon.svg' type='image/svg+xml'>
<link rel='icon' href='/favicon-dark.svg' type='image/svg+xml' media='(prefers-color-scheme: dark)'>

두 SVG 모두 public/에 위치시킵니다. media 속성은 사용자의 시스템 테마에 따라 브라우저가 어느 아이콘을 로드할지 결정하도록 지시합니다. JavaScript는 필요하지 않습니다.

5단계: 빌드 출력 확인하기

배포 전에 프로덕션 빌드를 실행하고 결과를 점검합니다. public 폴더 내용이 dist/에 그대로 반영되어 있어야 합니다.

npm run build
ls dist/

favicon.svg, favicon-32x32.png 등 모든 파일이 dist/의 루트에 그대로 위치해야 합니다. 누락되었다면 public/assets/ 같은 하위 디렉터리 안으로 잘못 넣은 것은 아닌지 확인합니다. 그렇게 하면 파일이 루트가 아닌 /assets/favicon.svg에 위치하게 됩니다.

자주 겪는 함정

favicon을 src/assets/에 두는 경우. 해당 위치의 파일들은 Vite에 의해 처리되고, 해시가 적용되며, 번들링됩니다. 그 결과 예측 가능한 URL을 잃게 됩니다. favicon 파일은 항상 public/에 두어야 합니다.

브라우저 캐시를 비우지 않는 경우. 배포 후에는 강제 새로 고침(Ctrl+Shift+R)을 수행하거나 시크릿 창에서 테스트합니다. 브라우저는 favicon을 적극적으로 캐시하며, 캐시 유지 기간이 며칠에 달하는 경우도 많습니다. 사용자 브라우저 전반에 강제 업데이트를 적용해야 한다면 favicon 캐시 무효화 모범 사례 가이드를 참고하시기 바랍니다.

sizes 속성을 누락하는 경우. 이 속성이 없으면 브라우저는 16x16을 기본값으로 가정하고 PNG를 업스케일하기 때문에 아이콘이 흐릿하게 보일 수 있습니다. 실제 크기를 항상 명시해야 합니다.

대문자 확장자를 사용하는 경우. Favicon.PNG는 macOS에서는 동작하지만, 대소문자를 구분하는 Linux 서버에서는 문제가 발생합니다. 소문자(favicon.png)로 일관되게 유지하시기 바랍니다.

마무리

이로써 Astro favicon public 폴더 설정이 완료되었습니다. public 디렉터리는 빌드 도구와 충돌 없이 안정적이고 예측 가능한 URL을 제공하며, 이는 favicon이 필요로 하는 그대로의 동작입니다. 파일을 넣고, link 태그를 연결하고, 출력을 확인하면 모든 브라우저에서 깔끔한 탭 아이콘을 확인할 수 있습니다.

Next.js, Gatsby, Hugo 등 정적 사이트 생성기 전반에 걸친 favicon 전략에 대한 더 넓은 관점을 원하실 경우, 정적 사이트 생성기용 favicon 가이드를 참고하시기 바랍니다. 배포 후에도 아이콘이 표시되지 않는 경우, 해결책은 일반적으로 생각보다 단순합니다.