자바스크립트로 이미지 파일 크기(용량) 추정하기: Canvas.toDataURL 실전 예제
브라우저의 <img> 요소에서 로드된 이미지의 정확한 전송 파일 크기를 반환하는 표준 API는 없습니다.
대신 JavaScript와 Canvas를 이용하면 브라우저에 렌더된 픽셀 데이터를 바탕으로 대략적인 이미지 용량(파일 크기 추정치)을 계산해 사용자에게 보여줄 수 있습니다.
이 가이드에서는 img onload 이벤트와 Canvas.toDataURL()을 활용해, 단계별로 이미지 용량을 추정하는 방법을 설명합니다. 핵심은 "자바스크립트로 이미지 파일 크기(용량) 추정하기: Canvas.toDataURL 실전 예제"라는 접근으로 실제 구현 예제까지 제공합니다.
중요: 이 방식은 서버에서 전달된 원본 파일의 바이트 수와는 다를 수 있습니다. 브라우저에서 생성된 데이터의 근사치임을 염두에 두세요.
1. 왜 JavaScript로 이미지 용량(파일 크기)을 체크해야 할까?
프론트엔드에서 이미지 무게를 바로 확인하면 여러 상황에서 즉각적인 가치를 제공합니다.
- 사용자가 게시물이나 에디터에 지나치게 큰 이미지를 업로드하려 할 때 사전 안내를 하기 위해
- 모바일 데이터 사용을 줄이기 위한 UX 결정을 내릴 때
- 이미지 최적화를 통해 페이지 로드 속도와 Core Web Vitals를 개선하려 할 때
- 갤러리나 썸네일 뷰에서 각 이미지의 용량을 바로 보여줄 때
서버측 확인이 가장 정확하지만, 업로드 전에 또는 외부 이미지를 바로 보여줘야 하는 상황에서는 클라이언트 측 추정치만으로도 충분히 유용합니다.
2. HTML 구성: onload 이벤트로 이미지 로드 완료 감지
이미지를 완전히 불러온 뒤에만 계산을 시작하려면 <img>의 onload 핸들러를 사용하세요.
로드 직후의 이미지 크기(추정치)를 안전하게 얻을 수 있습니다.
2-1. 기본 HTML 코드
<!-- 이미지가 로드되면 checkImageSize 함수에 해당 이미지 객체(this)를 전달 -->
<img
src="https://example.com/image.png"
onload="checkImageSize(this)"
alt="예제 이미지">
<!-- 결과 출력용 엘리먼트 -->
<p id="result-output">이미지 용량 체크 대기 중...</p>
src를 고정하지 말고, 파일 업로드 미리보기나 에디터에서 선택한 이미지 URL을 연결해 사용하세요.
3. JavaScript 구현: Canvas로 이미지 용량 추정하기
핵심 개념은 단순합니다. 이미지를 캔버스에 그린 뒤, toDataURL로 얻은 Base64 길이를 바이트 수로 환산하는 방식입니다. 이 방식은 "자바스크립트로 이미지 파일 크기(용량) 추정하기: Canvas.toDataURL 실전 예제"에서 소개하는 전형적인 접근입니다.
- 1단계: 이미지를 로드한 뒤 캔버스에 그린다.
- 2단계:
canvas.toDataURL("image/png")로 Base64 인코딩된 문자열을 얻는다. - 3단계: Data URL의 Base64 부분을 분리해
atob()로 디코딩한다. - 4단계: 디코딩된 문자열의 길이를 바이트 수로 간주한다.
3-1. JavaScript 코드 전체
function checkImageSize(img) {
// Canvas 기반으로 이미지 용량(추정치)을 계산
var imageSizeInBytes = calculateImageSizeInBytes(img);
// 결과를 출력할 엘리먼트 찾기
var resultElement = document.getElementById("result-output");
var message = "이미지 용량 (추정치): " + formatBytes(imageSizeInBytes);
if (resultElement) {
resultElement.innerText = message;
} else {
console.log(message);
}
}
/**
* Canvas를 사용하여 이미지 픽셀 데이터의 바이트 크기를 추정합니다.
* - 실제 서버 원본 파일 크기와 100% 일치하지 않을 수 있음
*/
function calculateImageSizeInBytes(img) {
// 1. Canvas 생성 및 크기 설정
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
// 2. 2D 컨텍스트에 이미지 그리기
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// 3. 캔버스를 Base64 인코딩된 Data URL (PNG 형식)로 변환
var dataUrl = canvas.toDataURL("image/png");
// 4. "data:image/png;base64,..." 중 Base64 데이터 부분만 추출
var base64Data = dataUrl.split(",")[1];
// 5. Base64 디코딩 후 바이너리 문자열 길이를 바이트 크기로 간주
var binary = atob(base64Data);
return binary.length;
}
/**
* 바이트 단위를 KB, MB 등으로 보기 쉽게 포맷합니다.
*/
function formatBytes(bytes) {
if (bytes < 1024) {
return bytes + " 바이트";
} else if (bytes < 1048576) {
return (bytes / 1024).toFixed(1) + " KB";
} else if (bytes < 1073741824) {
return (bytes / 1048576).toFixed(1) + " MB";
} else {
return (bytes / 1073741824).toFixed(1) + " GB";
}
}
4. HTML + JavaScript 전체 예제
한 파일 안에 모든 로직을 넣은 테스트용 예제입니다. 로컬에 저장해 이미지 URL만 교체하면 바로 확인할 수 있습니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>JavaScript 이미지 용량 체크 예제</title>
</head>
<body>
<h1>이미지 용량 체크 예제</h1>
<img
src="https://example.com/image.png"
onload="checkImageSize(this)"
alt="예제 이미지">
<p id="result-output">이미지 용량 체크 대기 중...</p>
<script>
function checkImageSize(img) {
var imageSizeInBytes = calculateImageSizeInBytes(img);
var resultElement = document.getElementById("result-output");
var message = "이미지 용량 (추정치): " + formatBytes(imageSizeInBytes);
if (resultElement) {
resultElement.innerText = message;
} else {
console.log(message);
}
}
function calculateImageSizeInBytes(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var dataUrl = canvas.toDataURL("image/png");
var base64Data = dataUrl.split(",")[1];
var binary = atob(base64Data);
return binary.length;
}
function formatBytes(bytes) {
if (bytes < 1024) {
return bytes + " 바이트";
} else if (bytes < 1048576) {
return (bytes / 1024).toFixed(1) + " KB";
} else if (bytes < 1073741824) {
return (bytes / 1048576).toFixed(1) + " MB";
} else {
return (bytes / 1073741824).toFixed(1) + " GB";
}
}
</script>
</body>
</html>
이 코드를 복사해 로컬에 저장한 뒤 이미지 주소만 바꿔 테스트해 보세요. 외부 이미지는 CORS 설정에 따라 동작이 달라질 수 있습니다.
5. CORS, 정확도 등 주의해야 할 점
5-1. CORS(교차 출처) 문제
도메인이 다른 이미지를 캔버스에 그리면 보안 정책 때문에 캔버스가 오염(tainted)되어 toDataURL() 호출 시 예외가 발생할 수 있습니다.
외부 이미지를 사용해야 한다면 서버에서 적절한 Access-Control-Allow-Origin 헤더를 설정하세요.
- 가능하면 같은 도메인의 이미지를 사용하세요.
- 외부 리소스를 써야 하면 서버 측에서 CORS를 허용하도록 구성합니다.
5-2. 실제 파일 크기와의 차이
이 방법은 브라우저가 생성한 이미지 데이터를 기준으로 용량을 추정합니다. 그래서 전송된 원본 파일 크기와 다를 수 있습니다. 그럼에도 불구하고 사용자에게 ‘대략적인 무게’를 알려주기에는 충분히 실용적입니다.
6. 자주 묻는 질문 (FAQ)
Q1. JavaScript로 계산한 이미지 용량이 실제 파일 크기와 완전히 같은가요?
아니요. Canvas + toDataURL() 기반 추정은 픽셀 데이터와 인코딩 결과를 바탕으로 하므로 서버에서 전송된 원본 바이트 수와 일치하지 않을 수 있습니다.
그러나 업로드 전 검증이나 사용자 안내 용도로는 충분히 유용합니다.
Q2. toDataURL() 사용 시 성능 이슈는 없나요?
고해상도 이미지를 반복적으로 처리하면 CPU와 메모리 사용량이 증가합니다. 가능하면 축소한 썸네일로 처리하거나 최대 처리 크기를 제한하세요. 필요하다면 Web Worker로 작업을 오프로드하는 것도 고려할 수 있습니다.
Q3. 업로드 전에 이미지 용량을 체크할 수도 있나요?
네. FileReader로 로컬 파일을 미리보기 이미지로 만든 뒤 캔버스에 그려 위와 같은 방식으로 추정치를 계산하면, 업로드 전 경고를 표시할 수 있습니다.
함께 보면 좋은 엔터프라이즈 사례
🚀 이 주제, 우리 서비스에 어떻게 적용할까요?
자바스크립트로 이미지 파일 크기(용량) 추정하기: Canvas.toDataURL 실전 예제를 실제 서비스와 조직에 녹여보고 싶다면, 현재 아키텍처와 운영 방식을 한 번 점검해 보는 것부터 시작해 보세요. 팀 위키나 기술 블로그, 사내 스터디 주제로도 아주 좋습니다.
이 글이 도움이 됐다면, 비슷한 엔터프라이즈 사례 글들도 함께 살펴보면서 우리 조직에 맞는 운영 상용구를 정의해 보세요.
댓글
댓글 쓰기