1차 공개일 · 8월 18일1차 강의가 모두 공개됩니다
TECH 으로 돌아가기
TECH HACKER NEWS 오늘 6분 읽기 41 READS

작은 JPEG가 크롬에서 유독 다르게 보이는 이유

작은 JPEG가 크롬에서 유독 다르게 보이는 이유
SOURCE IMAGE · HACKER NEWS

같은 이미지가 브라우저마다 다르게 그려진다면 대부분은 렌더링 버그를 의심한다. 개발자 기욤 테셰(Guillaume Técher)도 동료의 화면에서 15px 크기로 표시된 로고가 자신의 화면과 미묘하게 다르게, 더 두껍게 보이는 것을 발견했다. 파이어폭스에서는 원본에 가깝게 얇게 나오는 반면 크롬에서는 획이 굵어져 있었다. 이미지를 SVG로 바꾸자 문제가 사라졌지만, 그는 왜 애초에 이런 차이가 생기는지 파고들었고 결국 이것이 버그가 아니라 크롬이 작은 크기의 JPEG를 그릴 때 쓰는 의도된 최적화 때문이라는 사실을 확인했다.

큰 이미지를 작게 그리는 순진한 방법

일반적으로 JPEG를 작게 표시하려면 이미지를 메모리에서 완전히 압축 해제한 뒤 축소한다. 그런데 2000×2000 픽셀 JPEG를 화면에 20×20으로 보여줘야 한다고 생각해 보자. 압축을 다 풀면 이 비트맵은 약 12MB를 차지하지만, 최종 결과물인 20×20 이미지는 1.2KB 정도면 충분하다. 큰 버전이 담고 있던 정보 대부분은 축소 과정에서 그냥 버려진다. 계산과 메모리를 잔뜩 쓰고도 결과에는 기여하지 않는 낭비가 발생하는 셈이다.

핵심 통찰은 이때 버려지는 정보가 무작위가 아니라는 점이다. 이미지를 크게 줄이면 사라지는 것은 대부분 고주파(high-frequency) 성분, 즉 픽셀마다 빠르게 변하는 미세한 디테일이다. 잎이 무성하고 껍질이 거친 나무를 20×10 크기로 줄이면 위쪽의 초록 덩어리와 아래쪽의 갈색 막대만 남는다. 세밀한 결은 전부 뭉개진다. 반대로 색이 완만하게 변하는 저주파 정보는 작은 크기에서도 살아남아 이미지의 대략적인 형태를 결정한다.

JPEG가 이미 주파수로 저장돼 있다는 점

여기서 JPEG 포맷의 구조가 결정적인 역할을 한다. JPEG는 압축할 때 이미지를 8×8 블록으로 나누고, 각 블록을 DCT(이산 코사인 변환)를 통해 주파수 영역으로 바꾼다. 8×8 블록에서 가장 낮은 성분은 변화가 전혀 없는 평평한 단색, 이른바 상수 성분이고, 가장 높은 성분은 값이 최대로 오르내리는 체커보드 패턴이다. 그 사이의 다양한 패턴들이 기저 함수(basis functions)이며, 각 블록을 주파수 영역으로 바꾼다는 것은 결국 '이 블록에 각 패턴이 얼마나 들어 있는가'를 계수(coefficient)로 표현하는 일이다.

이 구조 덕분에 영리한 지름길이 열린다. 이미지를 8분의 1로 줄인다면 8×8 블록 하나가 축소된 이미지의 픽셀 하나로 대응된다. 그 크기에서는 저주파 정보만 있으면 되므로, 굳이 전체를 압축 해제할 필요 없이 고주파 계수를 건너뛰고 거친 버전에 필요한 계수만 골라 복원하면 된다. 결과 이미지는 더 작고, 상당수의 계수를 생략하기 때문에 압축 해제도 빠르다. 이 기법은 분모가 8인 분수 비율이라면 여러 배율에 적용할 수 있으며, 정식 명칭은 부분 IDCT 스케일링(partial IDCT scaling)이다. 흥미롭게도 같은 원리는 확대에도 쓰일 수 있다.

크롬에서 획이 굵어 보인 진짜 이유

크롬은 이미지 디코딩과 렌더링을 Skia에 맡기고, JPEG의 경우 Skia는 libjpeg-turbo를 사용하는데 여기에 부분 IDCT 스케일링이 구현돼 있다. 즉 크롬/Skia는 항상 전체 이미지를 풀어 나중에 축소하는 것이 아니라, 목표 크기에 가장 가까운 분모 8의 분수를 계산해 그 배율로 디코딩한 뒤 필요하면 전통적인 다운샘플링으로 마무리한다. 테셰의 로고가 두껍게 보인 것은 표시 크기가 워낙 작아 8분의 1 배율로 디코딩됐고, 그 과정에서 주파수 표현 중 상수 성분만 남았기 때문이다. 가장자리를 부드럽게 만들던 그라데이션과 미세한 경계 정보가 애초에 복원되지 않았으니 획이 뭉툭해질 수밖에 없다.

실무자 입장에서 이 사례가 주는 교훈은 분명하다. JPEG는 사진을 위한 포맷이며, 그 최적화들은 사진에 대한 사람의 지각 특성에 맞춰 설계됐다. 로고, 아이콘, 얇은 선이 많은 UI 그래픽처럼 날카로운 경계와 정확한 픽셀이 중요한 요소에 JPEG를 쓰면 브라우저의 디코딩 최적화가 오히려 눈에 띄는 왜곡을 만든다. 같은 결과가 브라우저마다 달라지는 것도 각 엔진이 어떤 배율에서 부분 디코딩을 적용하는지 판단이 다르기 때문이다. 이런 자산은 SVG나 PNG처럼 무손실이고 경계가 보존되는 포맷으로 다루는 편이 안전하다. 포맷 이름 그대로 JPEG는 사진 전문가 그룹(Joint Photographic Experts Group)의 것이라는 점을 기억할 필요가 있다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://guillaumetech.github.io/posts/jpg-scaling-chrome/
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기
처리 중...