pngquant 사용법: PNG 이미지 용량 줄이기

pngquant 사용법: PNG 이미지 용량 줄이기

웹사이트를 운영하다 보면 이미지 용량 때문에 고민하는 순간이 꼭 찾아옵니다. 특히 PNG 파일은 무손실 포맷이라 화질은 좋지만 용량이 크다는 게 늘 아쉬운 부분이죠. 로고, 아이콘, 스크린샷 같은 이미지는 JPEG으로 바꾸기도 애매하고, 그렇다고 용량이 큰 채로 두자니 페이지 로딩 속도가 걱정됩니다.

이런 상황에서 pngquant를 사용하면 PNG 이미지의 용량을 60~80%까지 줄이면서도 눈으로 보기에는 거의 차이가 없는 수준의 화질을 유지할 수 있습니다. 이번 글에서는 pngquant의 설치부터 실무에서 바로 활용할 수 있는 다양한 옵션까지 하나씩 살펴보겠습니다.

PNG 양자화란?

pngquant가 어떻게 PNG 파일의 용량을 줄이는지 이해하려면 양자화(quantization)라는 개념을 먼저 알아야 합니다.

일반적인 PNG 파일은 24비트(RGB) 또는 32비트(RGBA) 트루컬러 포맷을 사용합니다. 이론적으로 약 1,677만 가지 색상을 표현할 수 있는데, 실제로 하나의 이미지에서 그 많은 색상이 전부 쓰이는 경우는 드물죠.

양자화는 이미지에서 실제로 사용되는 색상을 분석해서 256색 이하의 팔레트(palette)로 줄이는 과정입니다. 트루컬러 PNG를 8비트 팔레트 PNG로 변환하는 셈인데요. 픽셀당 차지하는 데이터 크기가 24~32비트에서 8비트로 줄어드니까 파일 용량도 크게 줄어드는 것입니다.

pngquant는 이 과정에서 Median Cut이라는 양자화 알고리즘을 사용합니다. 원본 이미지의 색상 분포를 분석해서 가장 중요한 색상들을 팔레트에 남기고, 비슷한 색상들은 하나로 합치는 방식이에요. 또한 Floyd-Steinberg 디더링이라는 기법을 적용해서, 색상 수가 줄었는데도 원본과 거의 구분이 안 되는 수준의 결과물을 만들어냅니다.

한 가지 중요한 점은 알파 채널(투명도)이 완전히 보존된다는 것입니다. 투명 배경을 사용하는 로고나 아이콘에서도 안심하고 pngquant를 사용할 수 있어요.

설치

운영체제별로 패키지 매니저를 사용해서 설치할 수 있습니다.

macOS에서는 Homebrew로 설치하면 됩니다.

brew install pngquant

Ubuntu/Debian에서는 apt로 설치합니다.

sudo apt install pngquant

설치가 완료되면 버전을 확인해볼까요?

pngquant --version
결과
2.18.0 (January 2024)

기본 사용법

pngquant의 가장 기본적인 사용법은 파일명만 넘기는 것입니다.

pngquant screenshot.png

이 명령어를 실행하면 같은 디렉토리에 screenshot-fs8.png라는 새 파일이 생성됩니다. 원본 파일은 건드리지 않아요.

파일명에 붙는 -fs8이라는 접미사가 좀 생소하게 느껴질 수 있는데요. 이것은 “Floyd-Steinberg dithering, 8-bit”의 약자입니다. 즉, Floyd-Steinberg 디더링이 적용된 8비트 팔레트 PNG라는 뜻이에요.

용량 차이를 한번 확인해봅시다.

ls -lh screenshot.png screenshot-fs8.png
결과
-rw-r--r--  1 user  staff   1.2M Jan 10 14:30 screenshot.png
-rw-r--r--  1 user  staff   342K Jan 10 14:30 screenshot-fs8.png

1.2MB였던 파일이 342KB로 줄었습니다. 약 72% 감소한 건데, 화면에서 두 이미지를 나란히 놓고 봐도 차이를 느끼기 어려운 수준이에요.

품질 조절

기본 설정도 충분히 좋지만, 용도에 따라 품질과 용량의 균형을 직접 조절하고 싶을 수 있습니다. --quality 옵션으로 원하는 품질 범위를 지정할 수 있어요.

pngquant --quality 60-80 screenshot.png

여기서 60-80은 최소 품질과 최대 품질을 의미합니다. pngquant는 최대 품질(80) 이하로 유지하면서 가능한 한 작은 파일을 만들려고 시도하는데요. 만약 최소 품질(60) 이상을 달성하지 못하면 변환을 포기하고 에러 코드 99를 반환합니다.

이 동작 방식이 꽤 실용적인데, 양자화로 인해 품질이 너무 떨어지는 이미지는 자동으로 건너뛰게 되니까요.

품질 범위를 다양하게 시도해보면 용도에 맞는 값을 찾을 수 있습니다.

# 웹용: 용량 절감을 좀 더 공격적으로
pngquant --quality 40-70 banner.png

# 포트폴리오용: 품질을 높게 유지
pngquant --quality 80-95 portfolio.png

--speed 옵션을 사용하면 압축 속도와 품질 사이의 트레이드오프를 조절할 수 있습니다. 값은 1부터 11까지 지정할 수 있고, 기본값은 4입니다.

# 느리지만 최고 품질
pngquant --speed 1 screenshot.png

# 빠르지만 품질이 약간 떨어짐
pngquant --speed 11 screenshot.png

속도 1은 가장 정교한 양자화를 수행하므로 소수의 중요한 이미지를 처리할 때 적합합니다. 반대로 속도 11은 대량의 이미지를 빠르게 처리해야 할 때 유용해요.

색상 수 지정

pngquant는 기본적으로 최대 256색 팔레트를 사용합니다. 하지만 이미지에 따라서는 색상 수를 더 줄여도 괜찮은 경우가 있어요. 위치 인자로 최대 색상 수를 직접 지정할 수 있습니다.

# 최대 64색으로 줄이기
pngquant 64 screenshot.png

# 최대 16색으로 줄이기
pngquant 16 icon.png

색상 수를 줄이면 용량이 더 작아지지만, 그만큼 색상 표현이 거칠어질 수 있습니다. 아이콘이나 로고처럼 원래 색상 수가 적은 이미지라면 64색이나 32색으로도 충분한 경우가 많아요.

색상 수에 따른 용량 변화를 비교해보면 이렇습니다.

pngquant 256 screenshot.png -o screenshot-256.png
pngquant 128 screenshot.png -o screenshot-128.png
pngquant 64 screenshot.png -o screenshot-64.png
pngquant 32 screenshot.png -o screenshot-32.png

ls -lh screenshot*.png
결과
-rw-r--r--  1 user  staff   1.2M Jan 10 14:30 screenshot.png
-rw-r--r--  1 user  staff   342K Jan 10 14:30 screenshot-256.png
-rw-r--r--  1 user  staff   278K Jan 10 14:30 screenshot-128.png
-rw-r--r--  1 user  staff   215K Jan 10 14:30 screenshot-64.png
-rw-r--r--  1 user  staff   162K Jan 10 14:30 screenshot-32.png

256색에서 32색으로 줄이니 용량이 342KB에서 162KB로 절반 가까이 더 줄었습니다. 물론 실제로 이 정도로 색상을 줄이면 화질 저하가 눈에 보일 수도 있으니, 항상 결과물을 직접 확인하는 게 좋아요.

출력 파일 제어

pngquant는 출력 파일의 이름과 저장 위치를 제어하는 여러 옵션을 제공합니다. 자주 사용하는 옵션들을 정리해보면 다음과 같습니다.

  • --output (-o) — 출력 파일의 경로를 직접 지정
  • --ext — 기본 접미사(-fs8.png)를 다른 문자열로 변경
  • --force — 출력 파일이 이미 존재할 때 덮어쓰기 허용
  • --skip-if-larger — 양자화 결과가 원본보다 크면 파일을 생성하지 않음
  • --strip — 불필요한 메타데이터를 제거하여 용량을 추가로 절감

우선 -o 옵션으로 출력 파일의 경로를 직접 지정하는 경우를 살펴보겠습니다.

pngquant screenshot.png -o optimized/screenshot.png

또한 --ext 옵션을 사용하면 기본 접미사를 바꿀 수 있어요.

# 접미사를 -min.png으로 변경
pngquant --ext -min.png screenshot.png

이 명령어를 실행하면 screenshot-min.png이라는 파일이 생성됩니다.

--skip-if-larger 옵션은 이미 잘 최적화된 PNG 파일을 다시 처리할 때 유용합니다. 양자화 후 파일 크기가 오히려 커지는 드문 경우에 불필요한 파일 생성을 막아주거든요.

pngquant --skip-if-larger screenshot.png

원본 파일 덮어쓰기

실무에서 가장 많이 쓰는 패턴 중 하나가 바로 원본 파일을 양자화된 파일로 덮어쓰는 것입니다. 별도의 파일을 만들지 않고 원본 자체의 용량을 줄이고 싶을 때 사용하죠.

--ext--force 옵션을 함께 사용하면 됩니다.

pngquant --ext .png --force screenshot.png

--ext .png은 출력 파일의 확장자를 .png으로 유지하라는 뜻이고, --force는 같은 이름의 파일이 이미 있어도 덮어쓰라는 뜻입니다. 결과적으로 원본 파일명 그대로 양자화된 이미지가 저장되는 거예요.

이 패턴은 Git 저장소에 커밋하기 전에 이미지 용량을 줄이거나, 빌드 파이프라인에서 이미지를 최적화할 때 특히 편리합니다.

다만 원본이 사라지기 때문에 중요한 이미지라면 백업을 먼저 해두는 게 안전하겠죠.

# 원본 백업 후 덮어쓰기
cp screenshot.png screenshot.original.png
pngquant --ext .png --force screenshot.png

일괄 처리

이미지가 한두 장이면 하나씩 처리해도 되지만, 수십 장 이상이라면 일괄 처리가 필요합니다.

pngquant는 여러 파일을 한 번에 넘길 수 있어요.

pngquant *.png

현재 디렉토리의 모든 PNG 파일이 양자화되어 -fs8.png 접미사가 붙은 파일로 저장됩니다.

원본을 덮어쓰면서 일괄 처리하려면 앞에서 배운 패턴을 그대로 적용하면 됩니다.

pngquant --ext .png --force *.png

하위 디렉토리까지 포함해서 처리하고 싶다면 find 명령어와 함께 사용할 수 있습니다.

find . -name "*.png" -exec pngquant --ext .png --force {} \;

find-exec 옵션으로 찾은 파일마다 pngquant를 실행하는 방식인데요. 파일 수가 많으면 시간이 오래 걸릴 수 있습니다.

xargs를 사용하면 병렬 처리가 가능해서 더 빠릅니다.

find . -name "*.png" -print0 | xargs -0 -P 4 pngquant --ext .png --force

-P 4 옵션으로 최대 4개의 프로세스를 동시에 실행하도록 지정했습니다. CPU 코어 수에 맞춰 조절하면 대량의 이미지를 훨씬 빠르게 처리할 수 있어요.

특정 디렉토리의 이미지만 품질을 지정해서 일괄 처리하는 것도 가능합니다.

find ./src/assets/images -name "*.png" -print0 | \
  xargs -0 -P 4 pngquant --quality 60-80 --ext .png --force --skip-if-larger

--skip-if-larger 옵션을 함께 사용하면 이미 충분히 최적화된 파일은 건너뛰니까 안전하게 반복 실행할 수 있습니다.

실전 활용 예제

지금까지 배운 옵션들을 조합해서 실무에서 바로 활용할 수 있는 예제를 몇 가지 정리해보겠습니다.

웹 프로젝트에서 이미지 최적화 스크립트를 만들어 사용하면 빌드 전에 간편하게 이미지 용량을 줄일 수 있습니다.

#!/bin/bash
# optimize-png.sh - PNG 이미지 일괄 최적화

IMAGE_DIR="./src/assets/images"

echo "PNG 이미지 최적화를 시작합니다..."

find "$IMAGE_DIR" -name "*.png" -print0 | \
  xargs -0 -P 4 pngquant \
    --quality 60-80 \
    --speed 1 \
    --ext .png \
    --force \
    --skip-if-larger

echo "최적화 완료!"

CI/CD 파이프라인에서도 pngquant를 활용할 수 있습니다. GitHub Actions 워크플로우에 이미지 최적화 단계를 추가하는 예제입니다.

- name: PNG 이미지 최적화
  run: |
    sudo apt-get install -y pngquant
    find ./src/assets/images -name "*.png" -print0 | \
      xargs -0 -P 2 pngquant \
        --quality 60-80 \
        --ext .png \
        --force \
        --skip-if-larger

pngquant와 다른 도구를 조합하면 더 나은 결과를 얻을 수 있습니다. pngquant로 양자화를 수행한 후 oxipng로 추가적인 무손실 압축을 적용하는 방법이에요.

# 1단계: pngquant로 양자화 (손실 압축)
pngquant --quality 60-80 --ext .png --force screenshot.png

# 2단계: oxipng로 무손실 압축 (추가 용량 절감)
oxipng -o 4 --strip safe screenshot.png

pngquant가 색상 수를 줄여서 대폭 용량을 줄인 다음, oxipng가 PNG 내부 구조를 최적화해서 추가로 5~15% 정도 더 줄여주는 식입니다. 두 도구는 역할이 다르기 때문에 함께 쓰면 결과가 꽤 좋습니다.

마치며

pngquant는 PNG 이미지 용량을 줄이는 데 이만한 도구가 없습니다. 양자화라는 간단한 원리로 60~80%의 용량 절감을 달성하면서도 육안으로는 차이를 구분하기 어려운 수준의 품질을 유지해주니까요.

특히 --ext .png --force 패턴으로 원본을 바로 덮어쓸 수 있어서 빌드 스크립트나 CI/CD 파이프라인에 통합하기도 쉽습니다. --quality 옵션으로 품질 하한선을 설정하고 --skip-if-larger로 안전장치를 걸어두면 자동화해도 안심이에요.

PNG 말고 WebP 포맷으로의 변환도 고려하고 있다면 libwebp 사용법을 참고해보시고, Node.js 프로젝트에서 프로그래밍 방식으로 이미지를 처리하고 싶다면 Sharp 라이브러리도 살펴보세요. 터미널에서 더 다양한 이미지 작업이 필요하다면 libvips CLI가 강력한 선택지입니다.

더 자세한 내용은 pngquant 공식 사이트를 참고하시면 좋겠습니다.

This work is licensed under CC BY 4.0 CC BY

개발자를 위한 뉴스레터

달레가 정리한 AI 개발 트렌드와 직접 만든 콘텐츠를 전해드립니다.

Discord