스크린샷과 에셋8 분 읽기

180픽셀 아이콘 안에 60픽셀 그림이 라이브로 나가 있었습니다

viewBox가 있어도 래스터라이저는 SVG의 intrinsic size를 그대로 지키고 남는 캔버스를 패딩으로 채웁니다. 파일 크기도 해상도도 정상으로 보이므로, 한 번 눈으로 열어 보기 전에는 어떤 검사도 잡지 못했습니다.

#screenshots#verification#static-sites#automation#gotchas
개념 도식: 180 캔버스 좌상단에 60 크기로 렌더된 아이콘과 캔버스를 채운 정상 버전 비교
글 내용을 요약한 개념 도식.

사이트 아이콘 자산을 정리하다가, 홈 화면 아이콘(apple-touch-icon.png)을 열어 봤습니다. 파일은 180×180이었습니다. 그림은 좌상단 60×60에만 있었습니다.

불투명 bbox (2,2,62,62) · 채움 33%

이 파일은 iOS 홈 화면 아이콘이자 구조화 데이터의 조직 로고로 쓰입니다. 그 상태로 라이브에 있었습니다.

질문 하나 드리겠습니다. 당신의 자산 검사는 파일이 "있는지 · 크기가 맞는지"를 봅니까, 아니면 "무엇이 그려져 있는지"를 봅니까?

1. 원인은 소스 SVG의 한 줄이었습니다

<svg width="64" height="64" viewBox="0 0 64 64">

viewBox가 있어도 래스터라이저는 intrinsic size를 그대로 지키고, 남는 캔버스를 패딩으로 채웁니다.

macOS의 썸네일 CLI로 재현했습니다. 360 캔버스를 요청해도 64 크기 그림 + 흰 배경이 나옵니다. 라이브 파일도 이 경로로 만들어진 것으로 보입니다.

2. 그런데 브라우저 canvas는 안 그럽니다

drawImage(img, 0, 0, n, n)은 목표 크기로 스케일합니다.

그래서 브라우저에서 만든 아이콘은 정상이고 CLI 도구로 만든 것만 깨집니다. 같은 SVG에서 두 가지 결과가 나옵니다.

파일 크기도 해상도도 정상으로 보이므로 한 번 눈으로 보지 않으면 안 걸립니다. 저는 크기 · 해상도 · 존재 여부만 검사하고 있었습니다.

3. 당신이라면 이걸 어떻게 잡으시겠습니까

  • (a) 파일 크기와 해상도를 검사한다
  • (b) 파일 해시를 고정해 회귀를 막는다
  • (c) 불투명 픽셀의 bbox와 채움 비율을 잰다

(a)는 지금 하던 것이고, 통과했습니다. (b)는 지금 상태를 정답으로 굳힙니다. 답은 (c)입니다. **"상수가 있다 ≠ 적용됐다"**와 같은 부류입니다. 자산에서는 "파일이 있다 ≠ 그림이 있다"입니다.

4. 정본은 변환기에 목표 크기를 명시하는 것입니다

cairosvg.svg2png(url=src, write_to=dst, output_width=n, output_height=n,
                 background_color=None)            # 탭 아이콘: 라운드 코너 투명 유지
cairosvg.svg2png(..., background_color="#050403")   # 홈 화면 아이콘: 코너까지 불투명
  • 홈 화면 아이콘은 투명을 두면 안 됩니다. iOS가 투명 영역을 검게 합성합니다. 배경색은 SVG의 풀블리드 사각형 fill을 그대로 씁니다.
  • .ico는 가장 큰 프레임에서 저장합니다. 이미지 라이브러리에 16×16을 주고 sizes=[(16,16),(32,32),(48,48),(64,64)]를 넘기면 16 하나만 들어갑니다. 64로 만든 뒤 저장해야 4프레임이 생깁니다. file이 "4 icons"로 표시하는지, 라이브러리에서 프레임 목록을 다시 읽어 확인합니다.
  • 판정은 렌더 한 장으로. 사이즈별 프레임을 NEAREST로 확대해 한 장에 붙여 눈으로 봅니다.

5. 고쳐도 최대 30일은 옛 아이콘이 나갑니다

⚠️ 엣지 규칙이 PNG를 30일 물고 있어서 파일만 갈아치우면 캐시가 가립니다.

참조에 ?v=YYYYMMDD를 붙여 HTML과 함께 내보내야 하고, 구조화 데이터의 로고 URL도 같이 갈아야 합니다. 엣지 캐시가 배포를 가리던 이야기의 연장이고, 내 브라우저에서만 멀쩡해 보이던 이야기와도 같은 계열입니다.

같은 배치의 테마 아이콘이 통 사각형이던 이야기가 자매편입니다. 아이콘 자산이 조용히 틀리는 두 방식입니다.

6. 곁가지 함정 하나 — git add는 전부 아니면 전무입니다

git add a b c는 경로 하나가 없으면 전부 스테이징되지 않습니다.

9개 앱을 도는 루프에서 매니페스트 파일이 없는 앱 하나만 조용히 커밋이 비었습니다. 출력 첫 줄이 On branch main이라 성공처럼 보였습니다.

루프 커밋은 사후에 git status --porcelain으로 확인해야 합니다. 여기서도 판정은 명령의 성공 여부가 아니라 결과 상태입니다.

아직 모르는 것

  • 이 파일이 언제부터 그 상태였는지 모릅니다. 자산 생성이 여러 경로로 이루어졌고 기록이 없습니다.
  • 그래서 "몇 명이 잘린 아이콘을 봤는가"도 못 씁니다.

자가진단 3가지

  1. 아이콘 PNG를 마지막으로 열어 본 게 언제입니까? 크기 검사는 그림이 없어도 통과합니다.
  2. SVG에 width/height가 박혀 있습니까? viewBox가 있어도 CLI 래스터라이저는 그 값을 지킵니다.
  3. 아이콘을 교체하고 참조 URL에 버전을 붙였습니까? 안 붙이면 30일간 옛 그림이 나갑니다.

솔직한 부분

이건 디버깅이 아니라 그냥 파일을 열어 본 것입니다. 그런데 저는 몇 달 동안 그 파일을 안 열어 봤습니다. 검사 스크립트가 초록이었으니까요.

자산은 코드보다 이 함정에 약합니다. 코드는 틀리면 대체로 죽는데, 이미지는 틀려도 정상적인 크기의 정상적인 파일로 남습니다.

지금 딱 하나만 해 보세요. 당신 사이트의 apple-touch-icon.png를 브라우저에서 직접 열어 보십시오. 그림이 캔버스를 채우고 있는지만 보시면 됩니다. 10초입니다.

관련 글