Vite 앱 배포 후 브라우저 탭에 회색 사각형 아이콘만 떠 있는 상황을 경험해 본 적이 있다면 그 답답함을 잘 알 겁니다. 이건 버그가 아니라 설정 누락입니다. Create React App 에서 이전 프레임워크로 이동하는 개발자들이 자주 겪는 문제죠. 구형 프레임워크에서는 HTML 파일을 직접 수정하기도 했지만, Vite 는 엄격한 파일 기반 컨벤션에 의존하기 때문에 설정을 놓치기 쉽습니다.

카카오페이나 토스 같은 국내 핀테크 기업들이 브랜딩을 업데이트할 때를 생각해 보세요. 단순히 이미지 파일 하나만 교체한 게 아닙니다. 16x16 탭 아이콘부터 512x512 PWA 아이콘에 이르기까지 모든 해상도가 최적화되었는지 확인합니다. Vite 앱이 카카오페이 대시보드처럼 프로페셔널해지려면, 추측을 멈추고 현대적인 표준을 따라야 합니다.

Vite 가 아이콘을 다르게 처리하는 이유

Vite 는 public 폴더를 정적 자산 루트로 간주합니다. 이 폴더에 배치된 파일은 처리 없이 그대로 제공됩니다. 하지만 마법은 파일 이름을 올바르게 지정했을 때 발생합니다. Vite 는 favicon.ico 또는 favicon.svg 같은 특정 파일명을 자동으로 감지하여 빌드 시 필요한 HTML 태그를 주입합니다.

이 방식은 복잡한 플러그인이나 index.html에 수동으로 <link> 태그를 추가할 필요를 없앱니다. 깔끔하고 의견이 반영된 워크플로우지만, 정확성이 요구됩니다. 파일 이름을 철자 실수만 해도 브라우저가 아이콘을 찾지 못해 dreaded 회색 사각형이 남게 됩니다.

1 단계: 소스 파일 준비

코드를 건드리기 전에 올바른 자산을 준비해야 합니다. 2026 년 기준 단일 PNG 파일로는 부족합니다. 확장성을 위한 SVG 와 레거시 브라우저 지원을 위한 다중 해상도 ICO 가 필요합니다. 로고만 있다면 Mzu favicondl을 사용해 즉시 필요한 크기를 생성하세요.

SVG 는 최적화되어 있어야 합니다. 숨겨진 레이어와 불필요한 메타데이터를 제거하세요. 16x16 픽셀 아이콘이라 하더라도 무거운 SVG 는 초기 렌더링을 늦출 수 있습니다. ICO 파일에는 16x16, 32x32, 48x48 크기를 단일 컨테이너에 포함시키세요.

2 단계: Public 디렉토리에 파일 배치

프로젝트 루트로 이동하세요. public이라는 폴더가 보일 겁니다. 정적 자산이 존재하는 유일한 곳입니다. favicon.svg와 favicon.ico를 이 폴더로 직접 드래그 앤 드롭하세요.

이 파일들을 src/assets에 넣지 마세요. 그곳에 넣으면 빌드 과정에서 Vite 가 파일명에 해시값을 추가합니다 (예: favicon.a1b2c3.svg). 이는 자동 감지 메커니즘을 무효화합니다. public 폴더는 파일명이 그대로 유지되어야 하는 파일들의 안전지대입니다.

3 단계: 설정 확인

npm run dev로 개발 서버를 실행하세요. 브라우저에서 페이지 소스를 확인하세요. 다음과 유사한 라인이 표시되어야 합니다:

<link rel="icon" type="image/svg+xml" href="/favicon.svg" />

이것이 보인다면 Vite 가 아이콘을 성공적으로 감지한 것입니다. 보이지 않는다면 파일 확장자를 확인하세요. Vite 는 대소문자를 구분합니다. Favicon.svg는 작동하지 않으며 반드시 favicon.svg여야 합니다. 이는 수 시간의 디버깅 시간을 낭비하게 하는 흔한 함정입니다.

다크 모드 및 Apple Touch Icon 처리

프로페셔널한 설정은 기본 탭 아이콘을 넘어섭니다. 현대 사용자는 사이트가 시스템 환경설정에 적응하기를 기대합니다. 브랜드가 다크 배경을 사용한다면, 다크 모드에서 흰색 로고가 사라질 수 있습니다. 이를 위한 전용 SVG 변형이 필요합니다.

다크 모드 지원 구현

favicon-dark.svg라는 두 번째 SVG 파일을 생성하세요. index.html(src가 아닌 public 폴더 내부) 에 조건부 링크 태그를 추가하세요. 이는 브라우저가 prefers-color-scheme 미디어 쿼리에 따라 아이콘을 교체하도록 지시합니다.

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

이 간단한 추가는 사용자의 OS 설정과 관계없이 브랜드가 선명하고 세련되게 유지되도록 보장합니다. 이는 고품질 엔지니어링을 알리는 작은 디테일입니다.

Apple Touch Icon 설정

iOS 모바일 사용자는 다른 아이콘이 필요합니다. 홈 화면에 추가할 때 브라우저는 180x180 PNG 를 기대합니다. public 폴더에 apple-touch-icon.png라는 파일을 배치하세요. Vite 는 브라우저가 요청할 때 이 파일을 자동으로 제공합니다.

매니페스트 파일을 잊지 마세요. public 폴더에 manifest.json을 생성하고 index.html에 링크하세요. 이 파일은 Android 와 iOS 에게 앱을 독립적인 PWA 로 표시하는 방법을 알려줍니다. 매니페스트 구조에 대한 자세한 내용은 Web App Manifest Favicon 가이드를 확인하세요.

흔한 함정 및 해결책

설정이 정확하더라도 문제가 발생할 수 있습니다. 가장 빈번한 문제는 캐싱입니다. 브라우저는 favicon 캐싱에 매우 공격적입니다. 아이콘을 업데이트했는데도 이전 것이 보인다면 버그가 아니라 캐시된 버전을 보고 있는 것입니다.

업데이트를 강제하려면 index.html의 링크 태그에 쿼리 문자열을 추가하세요. 예를 들어 href="/favicon.svg?v=2"처럼요. 이는 브라우저가 새 파일을 가져오도록 속입니다. 또는 브라우저 캐시를 지우거나 시크릿 창을 사용하여 변경 사항을 확인하세요.

또 다른 문제는 콘솔의 404 오류입니다. 브라우저 콘솔에 /favicon.ico에 대한 404 오류가 표시된다면 public 폴더에서 파일이 누락된 것입니다. SVG 를 사용하더라도 일부 브라우저는 여전히 레거시 ICO 파일을 요청합니다. 이러한 오류를 침묵시키기 위해 항상 대체 ICO 파일을 제공하세요.

마지막으로, Vite 빌드 출력물이 dist 폴더로 간다는 점을 기억하세요. 배포할 때 서버가 public 디렉토리의 파일을 올바르게 제공하는지 확인하세요. Vercel 이나 Netlify 같은 정적 호스팅을 사용한다면 자동으로 처리됩니다. 커스텀 서버를 사용한다면 라우팅 설정을 점검하세요.

Vite 앱에 favicon 을 설정하는 것이 복잡할 필요는 없습니다. 파일 기반 컨벤션을 존중하고 올바른 포맷을 제공하면 모든 기기에서 앱이 프로페셔널하게 보이도록 보장할 수 있습니다. 이는 취미 프로젝트와 프로덕션 준비 완료 애플리케이션의 차이입니다.