JavaScript로 파비콘 관리하기
HTML 파일마다 파비콘 코드를 넣으면 경로 하나 바꿀 때도 전부 수정해야 한다. JavaScript로 한 곳에서 관리하면 된다.
파비콘 이미지가 아직 없다면 Favicon Generator로 생성할 수 있다.
HTML 파비콘
<link rel="icon" href="../images/favicon.png" />
오래된 글에서 rel="shortcut icon"을 쓰는 경우가 있다. shortcut은 IE 호환용 비표준 키워드고 현대 브라우저는 무시한다. rel="icon"만 쓰면 된다.
JavaScript로 설정
<head>에 동적으로 <link> 태그를 삽입한다.
function setFavicons(favImg) {
let head = document.querySelector("head");
let favicon = document.createElement("link");
favicon.setAttribute("rel", "icon");
favicon.setAttribute("href", favImg);
head.appendChild(favicon);
}
setFavicons("https://spemer.com/img/favicon/favicon.png");
함수 하나로 모든 페이지에 적용된다.
배열로 여러 아이콘 타입 처리
배열에 rel 값을 넣고 반복문으로 돌리면 icon과 apple-touch-icon을 한번에 처리할 수 있다.
function setFavicons(favImg) {
let head = document.querySelector("head");
let favIcons = [
{ rel: "icon" },
{ rel: "apple-touch-icon" },
];
favIcons.forEach(function (favIcon) {
let link = document.createElement("link");
link.setAttribute("rel", favIcon.rel);
link.setAttribute("href", favImg);
head.appendChild(link);
});
}
setFavicons("https://spemer.com/img/favicon/favicon.png");
Apple touch icon
예전에는 152x152, 167x167, 180x180을 각각 넣어야 했다. 지금은 180x180 하나면 된다. iOS가 알아서 다운스케일한다.
function setAppleFavicon() {
let head = document.querySelector("head");
let link = document.createElement("link");
link.setAttribute("rel", "apple-touch-icon");
link.setAttribute("sizes", "180x180");
link.setAttribute("href", "../apple-touch-icon.png");
head.appendChild(link);
}
setAppleFavicon();
180x180 PNG 하나로 iOS가 홈화면 아이콘을 알아서 축소한다. 단 색상 프로파일은 sRGB로 내보내야 색이 틀어지지 않고, 투명 배경은 흰색으로 치환된다. 디자인 시 배경색도 같이 고려해야 한다.
SVG 파비콘
SVG 파비콘은 벡터 기반이라 어떤 크기에서도 선명하고, CSS prefers-color-scheme으로 다크 모드 대응도 가능하다. 모던 파비콘 최소 구성은 SVG + PNG 폴백 + Apple touch icon 세 가지다.
PNG 폴백이 필요한 이유는 구형 브라우저와 iOS 홈화면 때문이다. 브라우저는 rel="icon" 링크 중 자기가 처리할 수 있는 포맷만 선택하므로, SVG와 PNG를 같이 넣어도 중복 적용되지는 않는다.
function setFavicons() {
let head = document.querySelector("head");
// SVG 파비콘 (모던 브라우저)
let svgIcon = document.createElement("link");
svgIcon.setAttribute("rel", "icon");
svgIcon.setAttribute("type", "image/svg+xml");
svgIcon.setAttribute("href", "../favicon.svg");
head.appendChild(svgIcon);
// PNG 폴백
let pngIcon = document.createElement("link");
pngIcon.setAttribute("rel", "icon");
pngIcon.setAttribute("type", "image/png");
pngIcon.setAttribute("sizes", "32x32");
pngIcon.setAttribute("href", "../favicon-32x32.png");
head.appendChild(pngIcon);
// Apple touch icon
let appleIcon = document.createElement("link");
appleIcon.setAttribute("rel", "apple-touch-icon");
appleIcon.setAttribute("sizes", "180x180");
appleIcon.setAttribute("href", "../apple-touch-icon.png");
head.appendChild(appleIcon);
}
setFavicons();
파비콘은 브라우저 캐시가 공격적이어서 파일을 교체해도 반영이 안 될 때가 많다. 배포 후 캐시 갱신이 필요하면 href 끝에 ?v=2 같은 쿼리 스트링을 붙여 강제 갱신하는 게 가장 간단하다.
Android / PWA
같은 방식으로 Android용 사이즈도 추가할 수 있다.
<link rel="icon" href="../favicon-48.png" sizes="48x48" type="image/png" />
<link rel="icon" href="../favicon-192.png" sizes="192x192" type="image/png" />
JavaScript 한 줄 수정하면 전체 페이지에 반영된다. 동적 파라미터를 쓰면 배지 표시나 다크 모드 아이콘 전환도 가능하다.
파비콘 이미지가 없다면 Favicon Generator에서 필요한 사이즈를 한번에 뽑을 수 있다.