이미지를 데이터 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를 쓰기로 했다면
- 먼저 이미지를 최대한 줄입니다. 이미지 압축 도구에서 표시될 크기로 줄이고 형식을 정합니다. 여기서 줄인 만큼이 33% 증가의 기준이 됩니다.
- 결과 크기를 확인합니다. 파일 인코더로 변환하면 문자열이 얼마나 길어지는지 바로 보입니다.
- 넣을 위치를 정합니다. 자주 수정하는 파일이라면 다시 생각해 보는 편이 좋습니다.
- 여러 개를 넣는다면 합계를 봅니다. 개별로는 작아도 스무 개가 모이면 코드 파일이 크게 무거워집니다.
1번을 건너뛰고 원본을 그대로 감싸는 경우가 가장 흔한 실수입니다. 압축하지 않은 이미지를 33% 부풀려 코드에 넣는 셈입니다.
바꿨는데 체감이 나빠졌을 때
| 증상 | 원인 | 조치 |
|---|---|---|
| 첫 화면이 늦게 뜸 | 스타일시트가 무거워짐 | 큰 이미지를 별도 파일로 되돌리기 |
| 재방문이 느려짐 | 캐시 이득이 사라짐 | 자주 쓰는 이미지를 파일로 분리 |
| 코드 수정 후 매번 느림 | 이미지가 코드와 함께 다시 받아짐 | 이미지를 코드에서 분리 |
| 문자열이 지나치게 김 | 원본을 압축하지 않음 | 압축 후 다시 변환 |
| 일부 환경에서 안 보임 | 데이터 URI 차단 | 해당 환경에서 미리 확인 |
데이터 URI를 남용하게 되는 이유
요청 수만 지표로 봅니다. 요청 수는 줄이기 쉬워 성과가 눈에 보이지만, 용량과 캐시 손실은 숫자로 드러나지 않습니다.
압축 없이 원본을 감쌉니다. 늘어나는 33%는 감싸는 대상의 크기에 비례합니다. 대상을 먼저 줄여야 합니다.
한 번 정한 방식을 전부에 적용합니다. 작은 아이콘에서 이득을 봤다고 큰 이미지까지 같은 방식으로 바꾸면 어느 지점부터 손해로 뒤집힙니다.
여러 페이지에서 쓰는 이미지를 심습니다. 페이지마다 같은 문자열이 반복되어 들어갑니다.
결과를 측정하지 않습니다. 바꾸기 전과 후의 실제 로딩 시간을 비교하지 않으면 뒤집혔는지 알 수 없습니다.
파일 크기가 판단 기준입니다
데이터 URI는 좋고 나쁨의 문제가 아니라 어느 크기까지인가의 문제입니다. 작으면 이득, 커지면 손해이고 그 경계는 생각보다 낮습니다.
확실하지 않다면 별도 파일이 안전한 기본값입니다. 데이터 URI는 파일 하나로 완결되어야 하거나 외부 이미지가 차단되는 환경처럼, 속도가 아닌 다른 이유가 있을 때 꺼내는 선택지에 가깝습니다.
자주 묻는 질문
요청 수를 줄이면 무조건 빠른 것 아닌가요?
예전에는 요청 하나하나의 비용이 컸지만 지금은 한 연결에서 여러 요청을 동시에 처리하는 방식이 일반적이라 이득이 줄었습니다. 반면 파일이 33% 커지는 비용과 캐시를 못 쓰는 비용은 그대로 남습니다. 그래서 작은 파일에서만 이득이 남습니다.
캐시가 안 된다는 것이 무슨 뜻인가요?
이미지를 별도 파일로 두면 브라우저가 그 이미지만 따로 저장해 두고 다음 방문에 다시 받지 않습니다. 데이터 URI는 코드 안에 문자열로 들어가므로 그 코드 파일과 운명을 같이합니다. 코드를 한 글자만 고쳐도 이미지까지 통째로 다시 내려받게 됩니다.
몇 KB까지가 적당한가요?
고정된 기준은 없지만 대체로 수 KB 이하의 작은 아이콘에서만 이득이 남습니다. 수십 KB를 넘으면 늘어난 용량과 캐시 손실이 요청 하나를 아끼는 이득보다 커지는 경우가 많습니다. 확실하지 않으면 별도 파일이 안전한 기본값입니다.
이메일 서명에 넣는 이미지는 어떤가요?
그 경우는 데이터 URI가 유리한 대표적인 상황입니다. 외부 이미지를 차단하는 메일 환경이 많아서, 파일 주소를 참조하면 이미지가 표시되지 않습니다. 다만 메일 클라이언트에 따라 데이터 URI도 차단하는 경우가 있어 미리 확인이 필요합니다.