이 페이지의 코드가 시작되지 않았습니다.

index.html을 폴더에서 바로 열면 브라우저가 JavaScript 모듈을 막습니다. 그래서 이미지 파일을 골라도 아무 일도 일어나지 않아요. 폴더를 http로 띄워서 여세요:

powershell -ExecutionPolicy Bypass -File serve.ps1

그런 다음 http://localhost:8080/을 여세요.

이미지를 데이터 URI로 — CSS나 HTML에 넣을 base64 인코딩

사진 전체를 텍스트 한 줄로. CSS나 HTML에 그대로 붙여 넣으세요.

언어: 한국어
소스 보기
이미지 파일은 절대 업로드되지 않습니다. 서버가 아예 없으니까요.

인코딩은 내 브라우저가 내 기기의 성능으로 합니다. 페이지가 이미 손에 쥔 바이트를 두고 하는 산술일 뿐이에요. 인코더도, 서버도, 빼놓을 네트워크 단계도 없습니다. 이 도구에는 네트워크 기능이 하나도 없어서 가져올 것도 보낼 것도 없고, 설령 보내려 해도 이 페이지 반대편에는 사진을 받아 줄 서버 자체가 없습니다.

실시간 확인: 확인 중…

오프라인: 확인 중…

그냥 믿지 마시고 직접 확인해 보세요. 개발자 도구의 '네트워크' 탭을 켜 놓고 사진을 넣어 보십시오. 이미지도, 미리보기도, 파일 이름도, 고른 파일의 단 1바이트도 실려 나가는 요청이 없습니다. 아니면 인터넷을 끊고 그냥 인코딩해 보셔도 됩니다.

1 이미지 고르기

2 어디로 갈지 말하기

데이터 URI 자체를 원하는 사람은 드뭅니다. 필요한 건 스타일시트에 들어갈 그 한 줄이죠. 그러니 줄을 고르세요. 사진이 따옴표까지 씌워진 채로 그 안에 담겨 나옵니다. 틀리기 쉬운 데다 SVG에서만 조용히 실패하는 부분이 바로 그 따옴표입니다.

alt 텍스트는 일부러 비워 둡니다. 그 사진이 뜻을 담고 있는지 그냥 장식인지는 넣는 사람만 알고, 파일 이름에서 짐작해 붙인 설명은 화면 낭독기를 쓰는 사람에게 설명이 아예 없는 것보다 나쁘니까요.

SVG도 base64로 기본은 꺼져 있습니다. SVG는 텍스트이고 base64는 바이트를 위한 것이니까요. 퍼센트 인코딩은 스타일시트 안에서 마크업을 읽을 수 있게 남기고 대개 5분의 1쯤 짧습니다. ;base64를 고집하는 드문 도구 체인을 위해서만 켜세요.

SVG

3 복사하기

아직 고른 것이 없습니다. 위에 사진을 놓으면 붙여 넣을 줄이 여기 나타납니다.

Markdown으로 보기

이미지를 데이터 URI로 바꾸는 방법

  1. 이미지를 고릅니다. 선택 영역에 끌어다 놓거나 직접 골라 주세요. 브라우저가 디스크에서 곧바로 읽습니다. 그동안 어디로도 아무것도 나가지 않습니다.
  2. 결과가 어디로 갈지 말합니다. URI만, CSS 규칙, 사용자 지정 속성, <img> 태그, 아니면 마크다운. 어느 쪽이든 URI에 따옴표를 제대로 씌워 줍니다. 인라인 SVG가 동작하느냐 조용히 실패하느냐를 가르는 것이 바로 그 세부니까요.
  3. 대가를 읽습니다. 결과마다 몇 글자가 되었는지, 파일보다 얼마나 커졌는지, 이만한 크기를 인라인으로 넣는 것이 좋은 생각인지가 적힙니다. base64는 3분의 1을 더합니다. 그 3분의 1이 요청 하나를 아낄 값어치가 있는지는 전적으로 크기에 달렸고, 그래서 지금 어느 쪽에 서 있는지를 페이지가 말해 줍니다.
  4. 경고를 확인합니다. 사진에 EXIF나 색 프로파일, XMP가 들어 있으면 그것이 결과의 몇 바이트를 차지하는지와 함께 이름이 적힙니다. 확장자가 실제 형식과 다르면 페이지는 형식을 따르고 그 사실을 알려 줍니다. 브라우저가 결과를 그리지 못해도 그렇다고 말합니다.
  5. 복사하거나 내려받습니다. 결과마다 버튼이 하나씩 있고, 전부 한 번에 처리하는 버튼도 있습니다. 사용자 지정 속성은 :root 블록에 싸여 나오니 스타일시트 맨 위에 바로 붙여 넣으시면 됩니다.

자세한 설명

스타일시트 안에 그림을 넣어야 할 때와 넣지 말아야 할 때 데이터 URI의 대가, base64가 3분의 1을 더하는데 gzip이 그것을 돌려주지 않는 이유, SVG를 절대 base64로 만들면 안 되는 이유, 그리고 인라인 SVG를 조용히 망가뜨리는 따옴표 실수.

자주 묻는 질문

제 이미지가 어딘가로 업로드되나요?

아닙니다. 파일을 읽고 인코딩하는 일은 내 기기에서 도는 내 브라우저가 하고, 브라우저가 이미 갖고 있는 두 함수를 씁니다. 이 도구에는 네트워크 기능이 하나도 없어서 무언가를 가져오지도, 보내지도 않습니다. 이 페이지의 Content-Security-Policy에 연결해도 되는 주소가 전부 적혀 있는데, 그중 이 사이트 것은 하나도 없습니다.

데이터 URI가 무엇인가요?

보통 웹 주소가 들어갈 자리에 파일 전체를 적어 넣는 방법입니다. 브라우저더러 가서 가져오라고 시키는 url("logo.png") 대신, 사진 자체가 들어 있는 url("data:image/png;base64,iVBORw0...")를 씁니다. 브라우저가 그 자리에서 디코딩합니다. 실질적인 효과는 요청 하나가 줄어드는 것입니다. 사진이 스타일시트나 페이지 뒤가 아니라 그것과 함께 도착하니까요.

제 SVG는 왜 base64가 아닌가요?

base64가 SVG에는 맞지 않는 인코딩이기 때문입니다. SVG는 텍스트이고 URL은 이미 텍스트를 실어 나를 수 있습니다. 이스케이프해야 하는 문자도 몇 개뿐이고요. 그것만 퍼센트 인코딩하고 나머지를 그대로 두면 같은 파일을 base64로 만든 것보다 대개 5분의 1쯤 짧은 URI가 나오고, 스타일시트 안에서 여전히 읽을 수 있습니다. 요소 이름도, 색도, viewBox도 그대로 남아 고칠 수 있고요. base64를 고집하는 드문 도구 체인을 위해 강제로 base64를 쓰는 체크박스도 있습니다.

base64를 쓰면 이미지가 얼마나 커지나요?

3분의 1쯤입니다. 파일 3바이트가 base64 4글자가 되니, 앞에 붙는 data:image/png;base64,를 빼고 33%입니다. 그게 바닥이고 피할 수 없습니다. URL이 허용하는 문자만으로 임의의 바이트를 적어 내는 비용이라 그렇습니다. 페이지가 파일 크기 옆에 글자 수를 나란히 보여 주는 것도 같은 이유입니다. 스타일시트를 배포하고 나서 알게 되는 일이 없도록요.

이미지를 인라인으로 넣는 게 실제로 좋은 경우는 언제인가요?

작고, 당장 필요할 때입니다. 모든 페이지가 불러오는 스타일시트에 들어간 2KB짜리 아이콘은 분명한 이득입니다. 왕복이 하나 줄고, CSS가 도착하는 순간 사진도 거기 있으니까요. 10KB쯤을 넘으면 손익이 뒤집힙니다. 인라인된 사진은 더 이상 별개의 파일이 아니라서 따로 캐시될 수 없고, 다른 것과 병렬로 받아 올 수도 없으며, 그것을 감싼 파일이 바뀔 때마다 통째로 다시 내려받습니다. 스타일시트 안의 200KB짜리 사진은 사이트 모든 페이지의 임계 경로에 200KB를 얹는 셈이에요. 각 결과가 그 선의 어느 쪽에 떨어지는지는 페이지가 말해 줍니다.

gzip을 쓰면 base64가 더한 만큼이 상쇄되나요?

사람들이 기대하는 것보다는 훨씬 덜합니다. 이미 압축된 파일, 그러니까 PNG도 JPEG도 WebP도 다 그런데, 그런 파일의 base64는 잘 압축되지 않습니다. 압축기가 찾아낼 중복이 거의 남아 있지 않으니까요. 대개 base64가 더한 3분의 1 가운데 10분의 1쯤을 돌려받지, 전부를 돌려받지는 못합니다. 퍼센트 인코딩한 SVG는 반대입니다. 여전히 텍스트라서 예전만큼 잘 압축되고, 그것 또한 SVG를 base64로 만들지 않는 이유입니다.

이 과정에서 제 이미지가 조금이라도 바뀌나요?

아닙니다. 여기 있는 다른 도구들과 일부러 다르게 만든 점입니다. 픽셀로 디코딩했다가 다시 인코딩하는 일이 없습니다. 디스크에서 나온 바이트가 그대로 URI로 들어갑니다. JPEG는 화질도 크기도 그대로인 바로 그 JPEG로 남습니다. 결과를 사본이 아니라 같은 파일이라고 말할 수 있는 이유입니다.

그러면 EXIF와 GPS 정보도 스타일시트로 들어가나요?

들어갑니다. 붙여 넣기 전에 한 번 생각해 볼 대목이에요. 다시 인코딩하지 않으므로 카메라가 쓴 모든 것이 사진과 함께 갑니다. 위치, 촬영 시각, 카메라 일련번호까지요. 휴대폰 사진이라면 그것만 30KB가 되기도 하는데, base64로는 40KB가 되어 페이지의 임계 경로에 얹히고, 게다가 저장소에 커밋될 무언가에 집 주소가 들어갑니다. 이 페이지는 JPEG, PNG, WebP에 메타데이터가 얼마나 들었는지 읽어 알려 줍니다. 먼저 빼내려면 EXIF 확인 및 제거를 쓰세요.

왜 제 파일 확장자와 다른 타입을 썼나요?

확장자는 틀릴 수 있지만 바이트는 틀릴 수 없기 때문입니다. logo.png라는 이름으로 실제로는 JPEG로 내보낸 파일은 어느 이미지 도구든 감당해야 할 만큼 흔합니다. 그런데 타입을 잘못 적은 데이터 URI는 그냥 그려지지 않습니다. 대체 수단도 없고 읽어 볼 만한 오류 메시지도 없어요. 그래서 타입은 파일의 첫 몇 바이트에서 읽습니다. 여기서 다루는 모든 형식에서 그 바이트가 무엇인지를 분명히 말해 주고, 둘이 어긋나면 페이지가 알려 줍니다.

미리보기가 비어 있습니다. 무엇이 잘못됐나요?

URI 쪽은 아마 멀쩡합니다. HEIC와 TIFF는 완벽히 올바른 데이터 URI를 만들지만 Safari 말고는 어떤 브라우저도 그리지 않습니다. 그러니 붙여 넣는 곳에서도 사진은 보이지 않을 거예요. 이미지 압축이나 이미지 크기 조절로 먼저 PNG나 JPEG, WebP로 바꾸세요. 형식이 평범한 것이라면 파일 자체가 손상됐을 가능성이 큽니다. 미리보기는 이 페이지가 만든 URI에서 그려지므로, 비어 있다는 것은 사진이 디코딩되지 않았다는 뜻이니까요.

데이터 URI에 크기 제한이 있나요?

CSS나 <img> 태그에서 마주칠 만한 제한은 없습니다. 요즘 브라우저는 거기에 현실적인 상한을 두지 않습니다. 브라우저가 제한하는 것은 주소창에 데이터 URI를 입력하는 쪽인데, 대부분 웬만한 길이는 거부합니다. 이 용도와는 무관한 보안상의 이유고요. 진짜 제한은 위에서 말한 그것입니다. 기술적으로 무엇이 깨지기 훨씬 전에, 그 페이지는 평범한 이미지 파일을 썼을 때보다 이미 느려져 있습니다.

무료인가요? 가입해야 하나요?

무료이고 계정도, 로그인도, 체험판도, 워터마크도 없습니다. 파일 개수나 용량 제한도 없습니다. 그 값을 치를 서버가 없으니까요. 작업은 내 기기에서 일어납니다. 이 사이트는 광고로 유지되는데, 그 광고에도 내 이미지에 관한 것은 넘어가지 않습니다.

오프라인에서도 되나요?

됩니다. 페이지를 한 번 불러온 다음 인터넷을 끊어도 계속 동작합니다. 아무것도 업로드되지 않는다는 가장 간단한 증명이기도 하고요. 이미지를 어딘가로 보내서 인코딩하는 도구라면 선을 뽑는 순간 멈춰 버릴 테니까요.