블로그 "1MB 이하로" 맞추기가 생각보다 어려운 이유

"1MB 이하로" 맞추기가 생각보다 어려운 이유

2026-08-13 · 약 6분 JPEG 이미지

서류를 온라인으로 제출할 때 "사진은 1MB 이하"라는 조건을 자주 만납니다. 대부분의 이미지 편집 도구는 품질을 1부터 100까지 슬라이더로 조절하게 해두었는데, 여기서 곤란해집니다. 1MB를 만들려면 품질을 몇으로 둬야 할까요?

답은, 계산으로는 알 수 없습니다. 저장해 보기 전에는 아무도 모릅니다.

품질 숫자는 용량을 뜻하지 않습니다

JPEG의 품질 값은 압축 과정에서 세부 정보를 얼마나 버릴지를 정하는 계수입니다. 용량을 지정하는 값이 아닙니다. 그래서 같은 품질 80이라도 결과 파일 크기는 사진마다 크게 다릅니다.

단색 배경에 글씨만 있는 이미지는 버릴 정보가 애초에 적어서 품질 80이든 95든 파일이 작습니다. 반대로 나뭇잎이 가득한 풍경 사진은 인접한 픽셀이 제각각이라 압축이 잘 듣지 않고, 같은 품질에서도 몇 배 커집니다. 노이즈가 많은 야간 사진도 마찬가지입니다.

품질과 용량의 관계는 비선형이기도 합니다. 90에서 80으로 내리면 용량이 크게 줄지만, 50에서 40으로 내리면 거의 줄지 않습니다. 이미 버릴 만큼 버린 상태이기 때문입니다. 그래서 "절반으로 줄이려면 품질을 절반으로" 같은 직관이 통하지 않습니다.

그래서 이진 탐색을 씁니다

공식으로 풀 수 없다면 남는 방법은 시도해 보는 것입니다. 다만 1부터 100까지 다 해볼 수는 없으니 이진 탐색을 씁니다. 이게 성립하는 이유는 한 가지 성질 덕분입니다 — 품질을 올리면 용량은 반드시 늘어난다. 값이 단조롭게 증가하니 중간을 찔러보고 범위를 반으로 줄여나갈 수 있습니다.

품질 35 ~ 95 사이에서 탐색
→ 65로 저장 → 1.4MB, 목표 초과 → 위쪽 버림
→ 50으로 저장 → 900KB, 통과 → 더 좋은 화질을 노림
→ 57로 저장 → 1.1MB, 초과 → 위쪽 버림
→ 53으로 저장 → 980KB, 통과
결과: 목표를 넘지 않는 가장 높은 품질

전부 시도하면 60번 저장해야 할 것을 6~7번으로 끝냅니다. 그리고 단순히 "목표 이하"를 찾는 게 아니라 목표를 넘지 않는 선에서 가장 높은 품질을 찾습니다. 900KB로 만들 수 있는데 굳이 400KB로 만들어 화질을 버릴 이유가 없으니까요.

품질 하한을 35로 둔 이유

탐색 범위의 아래쪽을 1이 아니라 35로 막아두었습니다. 그 아래로 내려가면 JPEG 특유의 사각 블록이 눈에 띄기 시작하기 때문입니다. 8×8 픽셀 단위로 압축하는 방식이라, 정보를 너무 버리면 그 경계가 격자로 드러납니다.

품질 20짜리 1MB 사진과, 해상도를 70%로 줄인 품질 75짜리 1MB 사진 중에서는 후자가 거의 항상 낫습니다. 그래서 품질을 더 깎는 대신 해상도를 줄이는 쪽으로 넘어갑니다.

얼마나 줄여야 하는지도 추측이 필요합니다

해상도를 줄이기로 했다면 다음 질문이 생깁니다. 몇 퍼센트로 줄여야 목표에 닿을까요. 여기서는 한 가지 근사를 씁니다 — 파일 크기는 픽셀 수에 대략 비례한다.

가로세로를 각각 s배 하면 픽셀 수는 s²배가 됩니다. 그러니 지금 3MB인 파일을 1MB로 만들고 싶다면 픽셀 수를 1/3로 줄여야 하고, 배율은 그 제곱근인 약 0.58이 됩니다. 이 계산 한 번으로 시행착오를 크게 줄일 수 있습니다.

추정식배율 = √(목표 용량 ÷ 현재 용량)
근거픽셀 수 = 가로 × 세로이므로 배율의 제곱에 비례합니다
한계어디까지나 근사입니다. 축소하면 노이즈가 뭉개져 압축이 더 잘 듣는 등 실제 결과는 조금씩 어긋납니다

그래서 이 추정으로 한 번에 맞추려 하지 않습니다. 추정한 배율에서 다시 품질 이진 탐색을 돌리고, 그래도 목표를 못 맞추면 0.8배씩 더 줄이며 최대 다섯 번 반복합니다. 그 다섯 번 안에 대부분 들어옵니다.

끝내 못 맞추는 경우

목표가 지나치게 작으면 — 예를 들어 4,000만 화소 사진을 50KB로 — 다섯 번을 다 돌려도 도달하지 못합니다. 이때 조용히 실패하거나 무한정 줄이는 대신, 가장 작게 만든 결과를 돌려주고 목표에 못 미쳤다고 알립니다. 사용자가 목표를 조정할지 그 결과를 쓸지 판단할 수 있어야 하니까요.

이 로직을 브라우저 밖으로 꺼낸 이유

압축 탐색 로직은 실제 인코딩과 분리해 두었습니다. "배율과 품질을 받아 결과 크기를 돌려주는 함수"를 밖에서 주입받는 구조입니다. 실제 서비스에서는 브라우저의 캔버스가 그 역할을 하지만, 테스트할 때는 가짜 인코더를 넣을 수 있습니다.

덕분에 브라우저를 띄우지 않고도 탐색 로직만 검증할 수 있습니다. 이진 탐색이 정말 최대 품질을 찾는지, 목표를 못 맞출 때 가장 작은 결과를 돌려주는지 같은 것들을 말이죠. 이미지 처리 코드에서 느리고 불안정해지기 쉬운 부분이 바로 이 검증인데, 인코더를 주입식으로 만들면 그 문제가 사라집니다.

목표 용량을 KB로 정해서 압축하기

여기서 설명한 탐색이 브라우저 안에서 그대로 돌아갑니다.

사진 용량 줄이기