주말 사이드 프로젝트를 위해 SVG 아이콘을 한 시간 들여 싹 멋지게 디자인했습니다. 프로젝트 폴더에 파일을 넣고, 로컬 개발 서버를 실행했는데... 브라우저 탭에는 기본 아이콘만 덩그러니 나옵니다. localhost에서 favicon이 안 보이는 문제로 골머리를 앓고 계시다면, 혼자만의 일은 아닙니다. 개발을 하다 보면 누구나 한 번쯤 겪는 흔한 문제입니다.
로컬 개발 서버의 묘한 동작 방식을 깊게 파고들기 전에, 일단 지금 당장 아이콘이 보이게 만드는 빠른 해결책부터 적용해 보겠습니다.
가장 빠른 해결책: 상대 경로 대신 절대 경로 사용하기
메인 HTML 파일이나 layout template을 열어보세요. favicon link tag를 찾습니다. 만약 href='favicon.ico'나 href='./favicon.png'처럼 되어 있다면, 범인은 바로 녀석입니다. Vite, Webpack Dev Server, 혹은 Django의 runserver 같은 로컬 개발 서버는 중첩된 라우트에서 페이지를 제공할 때가 많아, 상대 경로가 꼬이기 쉽습니다.
해당 tag를 web root 기준의 절대 경로로 변경해 보세요.
<link rel='icon' href='/favicon.ico' type='image/x-icon' />앞에 붙은 슬래시가 핵심입니다. 현재 어떤 sub-route를 보고 있든 상관없이 브라우저가 서버의 root(예: http://localhost:3000/favicon.ico)를 바라보게 만듭니다. 브라우저를 새로고침하면 아이콘이 바로 나타날 것입니다.
Localhost에서 Favicon이 깨지는 이유
빠른 해결책으로도 해결되지 않았다면, 로컬 환경이 정적 자원을 어떻게 제공하는지 살펴봐야 합니다. Localhost는 꽤 까다로운 녀석입니다. 실제 서버를 흉내 내지만, 표준 caching 동작을 건너뛰거나 MIME type을 다르게 처리하는 경우가 많습니다.
1. Base URL Routing의 함정
예를 들어 대시보드 앱을 개발 중이고 http://localhost:3000/users/profile을 보고 있다고 가정해 봅시다. HTML에 href='favicon.ico'로 적어두면, 브라우저는 이를 현재 경로에 그대로 이어 붙입니다. 결국 http://localhost:3000/users/profile/favicon.ico를 요청하게 되죠. 서버는 404를 반환하고 탭은 계속 비어 있게 됩니다. 로컬 아이콘이 보이지 않는 가장 흔한 이유이며, 로컬 routing 중에만 발생한다는 점에서 일반적인 file path errors와는 구별됩니다.
3. 브라우저의 과도한 Caching
브라우저는 favicon을 무척 공격적으로 caching 합니다. 정말 말도 안 되게요. 경로를 수정해도 Chrome이나 Firefox는 종종 '아이콘 없음' 상태를 놓아주질 않습니다. 경로가 맞는데도 탭이 비어 있다면 강력 새로고침을 해보세요. Chrome에서는 DevTools를 열고 새로고침 버튼을 우클릭한 뒤 'Empty Cache and Hard Reload'를 선택하면 됩니다.顽固한 cache를 지우는 방법에 대해 더 자세히 알고 싶다면 favicon cache clearing 가이드를 참고해 보세요.
실무 개발자들은 로컬 아이콘을 어떻게 다룰까?
Naver나 Kakao 같은 국내 대형 서비스, 혹은 GitHub 같은 글로벌 서비스들이 로컬 개발 환경을 어떻게 구성하는지 살펴보세요. 그들은 마법에 의존하지 않습니다. 빌드 도구를 활용해 완전한 favicon 패키지를 생성하고, 절대 경로를 자동으로 주입합니다. GitHub는 특히 dark mode 지원을 위해 최적화된 SVG favicon을 사용하며, root 정적 디렉토리에서 이를 제공합니다.
우리도 같은 방식을 따라야 합니다. 단일 ICO 파일을 프로젝트 root에 수동으로 끌어다 놓는 방식은 그만두세요. 도구를 사용해 필요한 모든 크기와 포맷을 생성하고, public 디렉토리에 넣은 뒤 root 기준으로 참조하세요.
앞으로의 Localhead 골칫거리 예방하기
로컬 개발 탭을 깔끔하게 유지하기 위한 간단한 체크리스트입니다:
- 항상 root 기준 절대 경로 사용:
./favicon.svg대신/favicon.svg를 사용하세요. - 정적 폴더 확인: Vite나 Next.js 같은 빌드 도구가 아이콘 폴더를 실제로 output 디렉토리로 복사하는지 확인하세요.
- MIME type 확인: SVG를 제공하는 경우, 로컬 서버가 일반 텍스트 대신
image/svg+xml을 반환하도록 설정하세요. - cache-buster 활용: 개발 중에는 favicon 경로에
?v=2같은 query string을 붙여 브라우저가 항상 최신 버전을 가져가도록 만드세요.
로컬 아이콘이 누락되는 문제는 결국 개발 서버가 파일을 어떻게 routing 하는지 이해하면 해결됩니다. 절대 경로를 사용하고,顽固한 브라우저 cache를 비우고, 정적 미들웨어 설정을 확인해 보세요. 그러면 브라우저 탭도 드디어 프로페셔널하게 보일 것입니다.