웹 인프라

작은 사진 파일이 브라우저를 멈추게 한 이유

작은 사진 파일도 펼치면 큰 픽셀 배열이 돼요. 해상도를 직접 바꿔 보고, 파일 압축과 메모리 절약이 다른 이유를 알아봐요.

이 글의 목차파일을 열면 픽셀 작업대가 펼쳐진다5
  1. 파일을 열면 픽셀 작업대가 펼쳐진다
  2. 웹은 더 작은 사진 형식을 찾아왔다
  3. 브라우저 안에서 먼저 다듬는 이유
  4. 화면이 부드러운 것과 메모리가 넉넉한 것은 다르다
  5. 사진 한 장이 가르쳐 준 두 크기

진공 포장한 이불은 옷장 한 칸에 들어가지만 봉투를 열어 펴는 순간 방바닥을 넓게 차지해요. 보관할 때의 부피와 손질할 때 필요한 공간은 다른 값이에요.

사진 파일이 그래요. 브라우저에서 사진을 그리거나 줄이는 동안에는 압축을 푼 픽셀을 다루는데, 이때 필요한 공간은 저장된 파일 크기보다 해상도와 처리 방식에 크게 좌우돼요. 업로드 화면이 파일 선택 직후에 멈추는 현상을 네트워크로 설명할 수 없는 이유가 여기 있어요.

압축 바이트와 픽셀 메모리의 차이 파일 크기는 압축 방식이, 작업 메모리는 펼친 픽셀 수가 결정한다. 개념 도해 압축 바이트와 픽셀 메모리의 차이 저장된 표현과 그릴 표현 ① 저장 · 전송 압축 파일 압축된 바이트 압축 해제 ② 화면에 그릴 때 픽셀 비트맵 가로 × 세로 × 색상 채널 크기를 결정하는 값 파일 크기 압축 방식 + 사진 내용 저장된 바이트 가변 작업 메모리 가로 픽셀 × 세로 픽셀 × 색상 채널 펼친 픽셀 공간 파일 크기는 압축 방식이, 작업 메모리는 펼친 픽셀 수가 결정한다. SOSHIN · DEV NOTES
사진을 줄이는 동안에는 압축 해제, 픽셀 축소, 재압축이라는 서로 다른 일이 이어져요.

파일을 열면 픽셀 작업대가 펼쳐진다

JPEG, HEIC, WebP 같은 이미지 형식은 비슷한 색과 무늬를 묶어 보관과 전송에 필요한 바이트를 줄여요. 브라우저가 그 사진을 직접 그리거나 고치려면 압축을 풀어 비트맵(bitmap)으로 만들어요. 비트맵은 가로와 세로의 모든 점에 색상값을 놓은 픽셀 지도예요.

가장 흔한 8비트 RGBA 형식에서는 한 픽셀에 빨강·초록·파랑·투명도를 각각 1바이트씩 써요. 그래서 픽셀 배열 하나의 크기는 가로 × 세로 × 4바이트로 계산할 수 있어요. MDN의 ImageData 설명도 이 기본 형식과 다른 픽셀 형식을 구별해요. 파일 크기가 같아도 해상도가 다르면 펼쳤을 때 필요한 공간은 달라져요.

가로와 세로를 각각 두 배로 늘려 보세요. 한 줄에 들어가는 점도 두 배, 줄 수도 두 배가 되니 전체 픽셀은 네 배가 돼요. 아래 계산은 압축 파일의 크기가 아니라 이 픽셀 배열 하나만 다뤄요.

가로·세로 두 배, 픽셀은 네 배

해상도를 바꿔 펼쳐진 픽셀 배열의 크기를 비교해 보세요.

전체 픽셀 750,000개

픽셀 배열 하나 3 MB

1,000 × 750은 75만 픽셀, 약 3 MB예요. 가로·세로를 두 배로 키운 2,000 × 1,500은 300만 픽셀, 약 12 MB가 돼요.

8비트 RGBA의 픽셀당 4바이트, 1 MB는 100만 바이트로 계산해요. 압축 파일 크기나 브라우저 전체 메모리 사용량이 아니에요.

처리 단계에 따른 이미지 메모리 겹침 변환 중에는 원본 Blob 위에 비트맵·Canvas·인코딩 버퍼가 겹쳐, 저장된 파일 크기보다 최고 메모리가 커진다. 개념 도해 처리 단계에 따른 이미지 메모리 겹침 이미지 변환 경로 ① 원본 Blob 압축 파일 ② 디코딩 펼친 비트맵 ③ Canvas 축소 작업대 ④ 인코딩 버퍼 재압축 중 ⑤ 결과 Blob 출력 파일 처리 시점별 동시 메모리 점유 동시 점유 공간 처리 시점 원본 Blob 점유선 원본 Blob 선택 직후 원본 디코딩 비트맵 Canvas 인코딩 버퍼 여러 공간 겹침 축소·인코딩 중 결과 Blob 완료 뒤 변환 중에는 원본 Blob 위에 비트맵·Canvas·인코딩 버퍼가 겹쳐, 저장된 파일 크기보다 최고 메모리가 커진다. SOSHIN · DEV NOTES
원본 파일과 디코딩된 픽셀, Canvas와 결과 파일은 처리 중 잠시 함께 존재할 수 있어요.

원본 파일, 디코딩된 비트맵, 축소를 위한 Canvas, 새로 압축 중인 결과가 한꺼번에 남아 있으면 최고 메모리는 더 커져요. 파일 하나가 작아 보인다는 사실만으로 여러 장을 동시에 안전하게 다룰 수 있다고 판단하기 어려운 이유예요.

웹은 더 작은 사진 형식을 찾아왔다

웹 초창기의 대표 이미지 형식은 화면 품질과 파일 크기 사이에서 각자의 타협점을 만들었어요. 사진에는 JPEG, 투명한 그림에는 PNG가 널리 쓰였지만 휴대전화 카메라의 해상도와 웹에서 오가는 이미지 수가 늘면서 더 효율적인 형식을 찾는 일이 중요해졌어요.

Google의 Chromium 팀은 2010년 9월 WebP 개발자 미리보기를 공개했어요. 동영상 압축 기술에서 가져온 아이디어로 사진의 바이트를 줄여 웹을 더 빠르게 만들려는 시도였어요. 이후 WebP는 손실 압축과 무손실 압축, 투명도와 애니메이션을 지원하며 주요 브라우저에 자리 잡았어요. 현재 Google의 WebP 설명도 WebP의 목적을 더 작고 풍부한 웹 이미지로 정리해요.

형식이 좋아졌다고 모든 사진이 같은 비율로 줄어드는 것은 아니에요. 색과 질감이 복잡한 사진, 이미 강하게 압축된 파일, 글자가 많은 그림은 서로 다른 결과를 내요. 새 형식은 만능 압축기가 아니라 품질과 크기를 다시 선택할 수 있는 도구예요.

브라우저 안에서 먼저 다듬는 이유

사진을 원본 그대로 올린 뒤 서버에서 줄일 수도 있어요. 이 방식은 결과를 한곳에서 관리하기 쉽지만, 사용자는 큰 파일 전체가 전송될 때까지 기다려야 해요. 브라우저에서 필요한 크기로 먼저 줄이면 업로드 전에 보내야 할 데이터가 작아지고 느린 네트워크에서 기다리는 시간도 줄어들어요.

브라우저의 createImageBitmap()은 이미지 소스를 비동기로 준비하며 크기를 바꿀 수 있고, Canvas의 toBlob()은 그 결과를 다시 파일 형태로 만들어요. 여기서 Blob은 브라우저가 이미지처럼 큰 이진 데이터를 파일과 비슷하게 다루는 그릇이에요.

중요한 것은 특정 크기나 품질 값을 정답처럼 복사하지 않는 일이에요. 프로필 사진, 중고 거래 상품 사진, 인쇄 원본은 필요한 해상도가 달라요. 브라우저와 사진 내용에 따라 결과 형식과 용량도 달라지므로, 화면에서 필요한 품질을 먼저 정하고 결과가 그 기대를 만족하는지 확인해야 해요.

어느 값을 바꾸면 무엇이 흔들리는지도 함께 알아 두는 편이 나아요.

조정하는 값줄어드는 것대신 고려할 점
목표 해상도를 낮춘다출력 픽셀 수와 결과 파일 크기원본 디코딩 메모리는 남을 수 있음
압축 품질을 낮춘다결과 파일의 바이트복잡한 질감이나 글자의 화질
한 번에 처리할 장수를 줄인다동시에 존재하는 비트맵전체 작업에 걸리는 시간

목표 이미지를 작게 정해도 원본을 먼저 크게 펼치는 경로라면 순간적인 메모리 사용량은 여전히 클 수 있어요. 브라우저가 실제로 어떻게 디코딩하는지에 따라 달라지는 부분이에요. 그래서 결과 파일을 작게 만드는 일과 한 번에 펼치는 원본 수를 줄이는 일을 함께 생각해야 해요.

같은 변환에서 갈리는 이미지 결과 같은 해상도와 품질 설정도 장면 복잡도에 따라 파일 크기와 손실이 달라진다. 개념 도해 같은 변환에서 갈리는 이미지 결과 모든 사진에 같은 변환 ① 목표 해상도 ② 출력 형식 ③ 품질 설정 사진마다 다른 입력 복잡도 단순한 장면 반복되는 색과 면이 많다 세부 손실이 덜 드러남 결과 바이트 복잡한 장면 경계와 질감이 촘촘하다 세부 손실이 먼저 드러남 결과 바이트 같은 해상도와 품질 설정도 장면 복잡도에 따라 파일 크기와 손실이 달라진다. SOSHIN · DEV NOTES
같은 변환을 거쳐도 사진의 질감과 목표 화면에 따라 적절한 결과는 달라져요.

화면이 부드러운 것과 메모리가 넉넉한 것은 다르다

이미지 변환을 화면 동작과 같은 작업 줄에서 오래 실행하면 버튼과 스크롤도 함께 굳어 보여요. 웹 워커(Web Worker)는 무거운 계산을 화면을 다루는 주 작업 줄과 분리하는 브라우저 기능이에요. OffscreenCanvas 문서는 워커 안에서 Canvas 결과를 파일로 만드는 방법을 설명해요.

그러나 일을 다른 줄로 옮겨도 펼쳐야 할 픽셀 수는 사라지지 않아요. 워커는 반응성을 도울 수 있지만 메모리를 무한히 늘려 주지는 않아요. 큰 사진을 한꺼번에 처리하기보다 사용이 끝난 비트맵과 미리보기 주소를 놓아주고, 실패했을 때 다시 선택할 길을 보여 주는 설계가 여전히 필요해요.

브라우저에서 파일을 줄이는 일은 사용자 경험을 위한 최적화이지 보안 경계도 아니에요. 누군가는 브라우저 화면을 거치지 않고 서버로 직접 파일을 보낼 수 있어요. OWASP 파일 업로드 지침이 클라이언트가 보낸 파일 형식 정보를 그대로 믿지 말라고 권하는 이유예요.

사진 한 장이 가르쳐 준 두 크기

제가 이 문제를 만난 곳은 여러 사진을 한 번에 고르는 업로드 화면이었어요. 전송량을 줄이려고 브라우저에서 사진을 다듬었는데, 파일 선택 직후 화면이 멈추는 현상은 네트워크만 바라봐서는 설명되지 않았어요. 압축 파일 뒤에 펼쳐지는 픽셀 작업대를 보고 나서야 원인이 보였어요.

그 뒤로 이미지 최적화를 볼 때 결과 파일이 얼마나 작아졌는지만 보지 않아요. 처리하는 동안 무엇이 동시에 메모리에 남는지, 기다리는 동안 화면이 반응하는지, 서버가 마지막 검사를 맡고 있는지를 함께 봐요.

특히 남은 것은 실패를 어떻게 다룰지 미리 정해 두는 일이었어요. 메모리가 부족해 변환이 실패하는 상황은 기기와 사진에 따라 갈리므로 개발 기기에서는 거의 재현되지 않아요. 그때 화면이 조용히 멈추는 대신 원본을 그대로 올리거나 다시 고르게 안내하는 길이 있으면, 같은 실패가 사용자에게는 불편으로만 남아요. 작은 파일과 가벼운 작업이 같은 말이 아니라는 것보다, 안 되는 기기가 반드시 있다는 전제가 더 오래 쓸모 있었어요.

소신을 상징하는 까마귀 목판화 일러스트
작성자소신 · Soshin

웹과 서버를 만들고, 개발하며 배운 것들을 글로 남깁니다.

좌우로 움직여 보세요