안녕하세요, 개발자 여러분. 모바일 홈 화면에 PWA를 설치했더니 로고가 뭉개져서 나오는 경험, 한 번쯤 있으시죠? 이건 십중팔구 web app manifest의 192px, 512px icon 설정이 꼬여있기 때문입니다. Android는 알아서 딱 맞는 아이콘을 골라주지 않습니다. manifest.json 파일을 아주 엄격하게 읽고 가장 근접한 이미지를 선택할 뿐이죠. 사이즈나 여백(padding) 설정을 잘못하면 바로 그런 참사가 벌어집니다.
Google Lighthouse audit에서는 manifest 파일 내에 192x192 PNG icon과 512x512 PNG icon이 없으면 PWA 검사를 바로 실패시킵니다. 이 숫자들에는 분명한 이유가 있습니다. 192px icon은 홈 화면 바로가기 아이콘의 표준 사이즈이고, 512px icon은 Android에서 앱의 splash screen을 생성할 때 사용합니다. 둘 다 있어야 하며, 완벽하게 세팅되어야 합니다.
이 글에서는 PWA 생태계 전반을 다루지는 않겠습니다. PWA 전반적인 개요가 필요하시다면 저희 Web App Manifest Favicon Guide를 참고해 주세요. 대신, 이 글에서는 192px과 512px icon에만 집중합니다. 왜 깨지는지, 어떻게 올바르게 생성하는지, 그리고 정확히 어떤 JSON 설정이 필요한지 알아보겠습니다.
시작하기 전에: 원본 이미지 준비
리사이징을 하기 전에, 고화질의 원본 파일부터 준비해야 합니다. 16x16 favicon을 가지고 확대(upscale)하려고 하지 마세요. SVG vector 원본 파일이거나 최소 1024x1024 pixel 이상의 PNG 파일이 필요합니다.
래스터 이미지 로고밖에 없다면, 512px까지 키울 때 블러 현상이 발생할 겁니다. 2026년에는 SVG로 작업하는 것이 업계 표준입니다. SVG는 선명도를 한 픽셀도 잃지 않고 무한히 확장할 수 있죠. 만약 로고에 아주 작은 텍스트가 포함되어 있다면, 이건 애초에 타협이 필요한 부분입니다. 작은 사이즈에서는 로고를 단순화하는 것이 필수적입니다. 자세한 이유는 Favicon Design Tips에서 확인해 보세요.
단계별 가이드: Icon 생성 및 설정
이제 실제 구현을 해보겠습니다. 어떤 이미지 에디터를 써도 상관없지만, 빌드 파이프라인에서 자동화할 수 있도록 CLI 툴과 순수 JSON 설정을 사용하는 방식으로 설명하겠습니다.
Step 1: 192px과 512px PNG 내보내기
선호하는 에디터(Figma, Sketch, Adobe XD 등)에서 원본 SVG를 엽니다. 두 개의 PNG 파일로 각각 내보내세요. 파일명은 정확히 icon-192.png와 icon-512.png로 지정합니다. 네이밍 컨벤션은 manifest의 가독성과 디버깅 편의성을 높여주므로 매우 중요합니다.
Vite나 Webpack 같은 빌드 툴을 사용 중이라면 플러그인으로 자동화할 수 있습니다. 하지만 정적 사이트라면 /public/icons/ 디렉토리에 파일들을 넣기만 해도 충분히 동작합니다.
Step 2: Manifest JSON 작성
이제 manifest.json 파일을 엽니다. icons 배열에 두 icon을 명시적으로 선언해야 합니다. 아래 설정을 그대로 복사해서 사용하시면 됩니다.
{
"name": "My Awesome App",
"short_name": "Awesome",
"icons": [
{
"src": "/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/icons/icon-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
}
]
}purpose 필드를 주목해 주세요. any로 설정하면 브라우저에게 이 icon을 어디든 사용할 수 있다고 알려주는 것입니다. 아래 pitfalls 섹션에서 maskable icon에 대해 다룰 텐데, 대부분의 개발자가 바로 이 부분에서 넘어집니다.
Step 3: HTML에 Manifest 연결
브라우저가 manifest 파일의 존재를 모르면 아무 일도 일어나지 않습니다. HTML 문서의 <head>에 다음 한 줄을 추가하세요.
<link rel='manifest' href='/manifest.json'>끝입니다. 배포하고 나면 Android 기기가 이 파일을 읽고 알아서 192px과 512px icon을 가져옵니다.
192px, 512px Icon 설정 시 흔히 겪는 함정들
JSON을 올바르게 작성하는 것은 싸움의 절반에 불과합니다. 대부분의 개발자가 Lighthouse PWA audit에서 불합격하는 이유는 미묘한 디자인이나 설정 실수 때문입니다. 코드 리뷰하면서 자주 발견하는 세 가지 문제점을 짚어보겠습니다.
Pitfall 1: 'purpose' Maskable 함정
Android 8+부터 adaptive icon이 도입되었습니다. icon이 네이티브처럼 보이고 다양한 런처의 원형이나 squircle 모양을 채우려면 maskable icon이 필요합니다. 하지만 기존 192px, 512px PNG에 그냥 purpose: "maskable"을 설정한다고 되는 게 아닙니다.
Maskable icon은 전체 영역을 채우는 배경색과 안전 영역(캔버스 안쪽 80%)에 배치된 로고가 필요합니다. 로고가 영역 끝에 닿으면 Android 런처가 이를 어색하게 잘라버립니다. 여백(padding)을 고려해 별도로 디자인된 버전을 따로 내보내고, 다음과 같이 선언해야 합니다.
{
"src": "/icons/maskable-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
}purpose 값이 다르다면 manifest에 192x192 entry를 여러 개 가질 수 있습니다. 192px과 512px 사이즈 모두에 any 용도와 maskable 용도를 하나씩 만들어 두는 것을 권장합니다.
Pitfall 2: 잘못된 MIME Type 제공
데스크톱에서는 icon이 잘 로드되는데 모바일에서만 실패한다면, 서버 헤더를 확인해 보세요. 일부 엄격한 웹 서버는 PNG를 image/png가 아니라 application/octet-stream으로 제공하기도 합니다.
Android Chrome은 manifest 내의 MIME type에 대해 유독 깐깐합니다. JSON의 type 필드와 서버의 Content-Type header가 일치하지 않으면, OS가 조용히 icon을 거부합니다. Nginx나 Apache 설정에서 .png 파일이 올바르게 매핑되어 있는지 반드시 확인하세요.
Pitfall 3: 디테일이 너무 많은 512px Icon 사용
512x512 캔버스를 쓴다고 해서 회사의 모든 비전과 미션을 아이콘에 쑤셔 넣을 수 있는 건 아닙니다. Android가 512px icon을 알림이나 작은 바로가기로 축소할 때, 그 많은 디테일은 그냥 흙탕물처럼 뭉개집니다.
토스(Toss)나 카카오 같은 국내 앱들의 PWA icon을 보면 이해가 쉽습니다. 단순하고 대비가 강한 마크를 단색 배경 위에 배치합니다. splash screen에서 512px으로 보여질 때나 알림 바에서 48px로 축소되어 보여질 때나 완벽하게 선명하게 보이죠. 심플함이 핵심입니다.
설정 검증하기
배포하고 기도하지 마세요. manifest icon이 제대로 동작하는지 검증해야 합니다. Chrome DevTools를 열고 Application 탭으로 이동한 뒤, Manifest를 클릭하세요. 'Icons' 섹션 아래에 192px과 512px icon이 선명하게 렌더링된 것을 볼 수 있어야 합니다.
깨진 이미지 아이콘 없이 제대로 보인다면 성공입니다. 다른 사이트의 192px이나 512px icon을 빠르게 다운받아 여백 구조를 비교해 보고 싶다면, Mzu favicondl을 사용해 manifest 파일을 직접 가져와 비교해 볼 수 있습니다.
올바른 원본 파일만 있다면 web app manifest icon 192 512 설정은 10분이면 충분합니다. 찍기 없이 정확한 사이즈로 내보내고, 올바른 MIME type을 선언하세요. 그러면 여러분의 PWA도 모든 Android 기기에서 네이티브 앱처럼 보일 겁니다.