개발·데이터

이미지를 데이터 URI로 심었더니 오히려 느려지는 경우와 판단 기준

요청 수를 줄이려고 이미지를 코드에 직접 넣었는데 체감 속도가 나빠질 때가 있습니다. 어떤 크기와 쓰임에서 이득이 뒤집히는지 정리했습니다.

최종 수정일 읽는 데 약 4

핵심 요약

  • 데이터 URI는 요청을 줄이는 대신 파일이 33% 커지고 따로 캐시되지 않습니다.
  • 이미지가 코드에 박히면 그 코드 파일 전체가 캐시 단위가 되어 재방문 이득이 사라집니다.
  • 수 KB짜리 아이콘 한두 개는 이득이지만 수십 KB를 넘으면 대체로 손해입니다.
  • 여러 페이지에서 쓰는 이미지일수록 별도 파일로 두는 편이 유리합니다.

페이지 로딩을 빠르게 하려고 아이콘 이미지들을 데이터 URI로 바꿔 CSS에 직접 넣었습니다. 요청 수는 줄었는데 체감 속도는 오히려 나빠진 것 같습니다.

느낌 탓이 아닐 수 있습니다. 결론부터 말하면 데이터 URI는 요청 하나를 아끼는 대신 두 가지 비용을 새로 만들고, 파일이 조금만 커져도 그 비용이 이득을 넘습니다.

데이터 URI가 만드는 두 가지 비용

첫째, 파일이 커집니다. 데이터 URI는 이미지를 Base64 문자열로 감싸 코드에 넣는 방식입니다. Base64는 3바이트를 4글자로 바꾸므로 약 33% 늘어납니다. 10KB짜리 아이콘이 13KB 남짓한 문자열이 되어 CSS 안에 들어갑니다.

둘째, 따로 캐시되지 않습니다. 이쪽이 더 중요합니다.

이미지를 별도 파일로 두면 브라우저가 그 이미지만 저장해 두었다가 다음 방문에 다시 받지 않습니다. 반면 데이터 URI는 코드 안의 문자열이므로 그 코드 파일과 한 몸입니다. CSS를 한 줄만 고쳐도 그 안에 들어 있는 이미지 전부를 다시 내려받게 됩니다.

여기에 하나가 더 있습니다. 스타일시트는 페이지를 그리기 전에 먼저 받아야 하는 파일입니다. 그 안에 이미지가 잔뜩 들어가 파일이 커지면, 첫 화면이 그려지기까지의 시간이 함께 늘어납니다.

이득이 남는 경우와 뒤집히는 경우

상황판단이유
수 KB 아이콘 한두 개이득요청 절약이 33% 증가보다 큼
수십 KB 이상 이미지손해늘어난 용량이 코드 파일을 무겁게 함
여러 페이지에서 쓰는 이미지손해별도 파일이면 한 번만 받으면 됨
한 페이지에서만 쓰는 장식조건부작으면 무난
자주 바뀌는 코드 안손해코드 수정마다 이미지도 다시 받음
이메일 서명·첨부 문서이득외부 이미지가 차단되는 환경
오프라인으로 배포하는 단일 HTML이득파일 하나로 완결됨

마지막 두 줄은 속도가 아니라 파일 하나로 완결되어야 하는 요구에서 나옵니다. 이런 경우에는 용량 증가를 감수할 이유가 분명합니다.

데이터 URI를 쓰기로 했다면

  1. 먼저 이미지를 최대한 줄입니다. 이미지 압축 도구에서 표시될 크기로 줄이고 형식을 정합니다. 여기서 줄인 만큼이 33% 증가의 기준이 됩니다.
  2. 결과 크기를 확인합니다. 파일 인코더로 변환하면 문자열이 얼마나 길어지는지 바로 보입니다.
  3. 넣을 위치를 정합니다. 자주 수정하는 파일이라면 다시 생각해 보는 편이 좋습니다.
  4. 여러 개를 넣는다면 합계를 봅니다. 개별로는 작아도 스무 개가 모이면 코드 파일이 크게 무거워집니다.

1번을 건너뛰고 원본을 그대로 감싸는 경우가 가장 흔한 실수입니다. 압축하지 않은 이미지를 33% 부풀려 코드에 넣는 셈입니다.

바꿨는데 체감이 나빠졌을 때

증상원인조치
첫 화면이 늦게 뜸스타일시트가 무거워짐큰 이미지를 별도 파일로 되돌리기
재방문이 느려짐캐시 이득이 사라짐자주 쓰는 이미지를 파일로 분리
코드 수정 후 매번 느림이미지가 코드와 함께 다시 받아짐이미지를 코드에서 분리
문자열이 지나치게 김원본을 압축하지 않음압축 후 다시 변환
일부 환경에서 안 보임데이터 URI 차단해당 환경에서 미리 확인

데이터 URI를 남용하게 되는 이유

요청 수만 지표로 봅니다. 요청 수는 줄이기 쉬워 성과가 눈에 보이지만, 용량과 캐시 손실은 숫자로 드러나지 않습니다.

압축 없이 원본을 감쌉니다. 늘어나는 33%는 감싸는 대상의 크기에 비례합니다. 대상을 먼저 줄여야 합니다.

한 번 정한 방식을 전부에 적용합니다. 작은 아이콘에서 이득을 봤다고 큰 이미지까지 같은 방식으로 바꾸면 어느 지점부터 손해로 뒤집힙니다.

여러 페이지에서 쓰는 이미지를 심습니다. 페이지마다 같은 문자열이 반복되어 들어갑니다.

결과를 측정하지 않습니다. 바꾸기 전과 후의 실제 로딩 시간을 비교하지 않으면 뒤집혔는지 알 수 없습니다.

파일 크기가 판단 기준입니다

데이터 URI는 좋고 나쁨의 문제가 아니라 어느 크기까지인가의 문제입니다. 작으면 이득, 커지면 손해이고 그 경계는 생각보다 낮습니다.

확실하지 않다면 별도 파일이 안전한 기본값입니다. 데이터 URI는 파일 하나로 완결되어야 하거나 외부 이미지가 차단되는 환경처럼, 속도가 아닌 다른 이유가 있을 때 꺼내는 선택지에 가깝습니다.

자주 묻는 질문

요청 수를 줄이면 무조건 빠른 것 아닌가요?

예전에는 요청 하나하나의 비용이 컸지만 지금은 한 연결에서 여러 요청을 동시에 처리하는 방식이 일반적이라 이득이 줄었습니다. 반면 파일이 33% 커지는 비용과 캐시를 못 쓰는 비용은 그대로 남습니다. 그래서 작은 파일에서만 이득이 남습니다.

캐시가 안 된다는 것이 무슨 뜻인가요?

이미지를 별도 파일로 두면 브라우저가 그 이미지만 따로 저장해 두고 다음 방문에 다시 받지 않습니다. 데이터 URI는 코드 안에 문자열로 들어가므로 그 코드 파일과 운명을 같이합니다. 코드를 한 글자만 고쳐도 이미지까지 통째로 다시 내려받게 됩니다.

몇 KB까지가 적당한가요?

고정된 기준은 없지만 대체로 수 KB 이하의 작은 아이콘에서만 이득이 남습니다. 수십 KB를 넘으면 늘어난 용량과 캐시 손실이 요청 하나를 아끼는 이득보다 커지는 경우가 많습니다. 확실하지 않으면 별도 파일이 안전한 기본값입니다.

이메일 서명에 넣는 이미지는 어떤가요?

그 경우는 데이터 URI가 유리한 대표적인 상황입니다. 외부 이미지를 차단하는 메일 환경이 많아서, 파일 주소를 참조하면 이미지가 표시되지 않습니다. 다만 메일 클라이언트에 따라 데이터 URI도 차단하는 경우가 있어 미리 확인이 필요합니다.