프로덕션 로그를 확인하다가 ActionController::RoutingError (No route matches [GET] '/favicon.ico') 에러로 도배된 것을 본 적이 있다면, 현재 ruby on rails favicon 설정에 구멍이 뚫려 있는 것입니다. 브라우저는 매우 고집스럽습니다. HTML 헤더에 어떻게 명시되어 있든 상관없이, 매 방문마다 도메인 루트에 있는 저 특정 파일 경로를 집요하게 찾으려 듭니다.
현존하는 가장 유명한 Rails 애플리케이션 중 하나인 GitHub를 살펴보겠습니다. 그들은 브라우저 탭에 알림 배지를 표시하기 위해 동적 SVG 아이콘을 사용합니다. 하지만 네트워크 트래픽을 검사해보면, 도메인 루트에 하드코딩된 .ico 파일을 여전히 유지하고 있습니다. 이는 최신 HTML 태그를 무시하는 레거시 브라우저나 단순한 웹 크롤러들을 만족시키기 위한 조치일 뿐입니다.
Rails 커뮤니티에서는 아이콘을 public 폴더에 두어야 할지, 아니면 Asset Pipeline(어셋 파이프라인)을 거치게 해야 할지를 두고 자주 논쟁을 벌입니다. 제 입장은 어떨까요? 둘 다 해야 합니다. Rails 뷰 헬퍼에만 의존하면 봇 트래픽으로 인한 404 에러에 무방비 상태가 됩니다. 반대로 정적인 public 폴더에만 의존하면, 브랜드를 리뉴얼할 때 캐시 무효화(Cache-busting) 지문을 활용할 수 없게 됩니다. 우리는 하이브리드 접근법이 필요합니다.
Rails 파비콘 하이브리드 전략
이를 올바르게 설정하려면 정적 자산을 분리해야 합니다. 레거시 봇에게는 그들이 원하는 것을 정확히 제공하고, 실제 사용자에게는 캐시가 무효화된 최신 자산을 제공할 것입니다.
1단계: 루트 요청 에러 침묵시키기
먼저 기본 favicon.ico 파일을 준비합니다. 없다면 Mzu favicondl을 사용하여 생성하세요. 이 파일을 Rails의 public/ 디렉토리에 직접 넣습니다. 절대 app/assets에 넣지 마세요.
public 폴더는 Rails 라우터를 거치지 않고 Puma(또는 프로덕션의 Nginx/Caddy)에 의해 직접 서비스됩니다. 이렇게 하면 라우팅 에러가 즉시 멈춥니다. 이는 RSS 리더나 아주 오래된 버전의 Internet Explorer를 위한 조용한 대비책 역할을 합니다.
2단계: 어셋 파이프라인 통합
다음으로 모던 웹 환경을 처리합니다. 최신 브라우저를 위한 SVG와 iOS 기기를 위한 Apple Touch Icon이 필요합니다. 이 파일들은 app/assets/images/에 위치해야 합니다.
왜일까요? 2026년 현재 Propshaft를 사용하든 레거시 Sprockets를 사용하든, Rails는 어셋 사전 컴파일(precompilation) 단계에서 파일명에 고유한 해시를 추가하기 때문입니다. 마케팅 팀이 로고의 배경색을 약간 수정하기로 결정하면, 컴파일된 파일명(예: icon-a1b2c3d4.svg)이 변경됩니다. 이는 즉시 브라우저 캐시를 무효화하여, 재방문 사용자가 즉시 새로운 로고를 볼 수 있게 보장합니다.
3단계: ERB 헬퍼 작성하기
app/views/layouts/application.html.erb 파일을 엽니다. Rails는 내장된 favicon_link_tag 헬퍼를 제공하지만, 파일 유형에 대해 잘못된 가정을 하지 않도록 명시적으로 설정해야 합니다.
<head>
<!-- public 폴더를 무시하는 브라우저를 위한 기본 대비책 -->
<%= favicon_link_tag 'favicon.ico' %>
<!-- 다크 모드를 지원하는 모던 SVG -->
<%= favicon_link_tag 'icon.svg', rel: 'icon', type: 'image/svg+xml' %>
<!-- iOS 홈 화면을 위한 Apple Touch Icon -->
<%= favicon_link_tag 'apple-touch-icon.png', rel: 'apple-touch-icon', type: 'image/png' %>
</head>모던 포맷에 대해 rel과 type 속성을 명시적으로 정의한 것에 주목하세요. 이를 생략하면 Rails는 기본적으로 rel='icon' type='image/x-icon'을 출력하며, 이는 Chrome과 같이 엄격한 브라우저에서 SVG 렌더링을 깨뜨리는 원인이 됩니다.
4단계: Rails에서 Web App Manifest 처리하기
PWA(Progressive Web App)를 구축 중이라면 manifest.json 파일이 필요합니다. 문제는 public 폴더에 있는 정적 JSON 파일이 지문이 추가된 사전 컴파일된 이미지 경로를 참조할 수 없다는 것입니다.
해결책은 매니페스트를 Rails 라우팅을 통해 서비스하는 것입니다. app/views/pwa/manifest.json.erb에 파일을 생성하고 image_path 헬퍼를 사용하세요:
{
"name": "My Rails App",
"icons": [
{
"src": "<%= image_path('icon-512.png') %>",
"sizes": "512x512",
"type": "image/png"
}
]
}이를 통해 Android 사용자가 앱을 홈 화면에 추가할 때 항상 올바르고 캐시 무효화가 적용된 아이콘을 얻을 수 있습니다.
프로덕션 환경의 일반적인 함정
로컬에서 이를 설정하는 데는 보통 5분밖에 걸리지 않지만, 프로덕션 배포 실패를 디버깅하는 데는 몇 시간이 걸릴 수 있습니다. 다음은 프로덕션 푸시 시 자주 발생하는 문제입니다.
- Vite Ruby 마이그레이션: 팀이 Propshaft에서 Vite Ruby로 마이그레이션했다면 표준 Rails 헬퍼는 작동하지 않습니다.
favicon_link_tag를<link rel='icon' href='<%= vite_asset_path('images/icon.svg') %>'>와 같은 Vite 전용 헬퍼로 교체해야 합니다. - 하드코딩된 ERB 경로: 레이아웃 파일에
<link href='/assets/icon.svg'>를 직접 작성하지 마세요. 개발 환경에서는 작동하지만, 컴파일된 다이제스트 지문이 없기 때문에 프로덕션에서는 404 에러가 발생합니다. 항상 헬퍼를 사용하세요. - 사전 컴파일 누락: 어셋을 사용자 정의 하위 디렉토리(예:
app/assets/images/favicons/)에 구성한 경우, Propshaft 또는 Sprockets 설정이 해당 폴더를 추적하고 있는지 확인하세요. 그렇지 않으면 빌드 단계에서 아이콘이 조용히 누락됩니다.
ruby on rails favicon을 올바르게 설정하는 핵심은 정적 파일과 컴파일된 어셋 간의 균형을 이해하는 것입니다. 레거시 파일은 루트에 두고, 모던 포맷은 어셋 파이프라인이 처리하게 하며, 내장 헬퍼를 사용하여 이 모든 것을 연결하세요. 로그에 남는 파비콘 404 에러에 지쳤다면 이 하이브리드 접근법이 영구적인 해결책이 될 것입니다. app/assets 폴더를 위한 정확한 크기의 아이콘을 생성해야 하나요? 리포지토리가 비대해지는 것을 막으려면 Apple Touch Icon 크기 가이드를 확인하세요.